diff --git a/.changeset/sharp-masks-jam.md b/.changeset/sharp-masks-jam.md new file mode 100644 index 00000000000..01796bd1f9e --- /dev/null +++ b/.changeset/sharp-masks-jam.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +improve: Pretty cause printing diff --git a/packages/effect/src/Inspectable.ts b/packages/effect/src/Inspectable.ts index c187e8abe94..c9f7cabd34a 100644 --- a/packages/effect/src/Inspectable.ts +++ b/packages/effect/src/Inspectable.ts @@ -113,6 +113,8 @@ export const stringifyCircular = (obj: unknown, whitespace?: number | string | u : cache.push(value) && (redactableState.fiberRefs !== undefined && isRedactable(value) ? value[symbolRedactable](redactableState.fiberRefs) : value) + : typeof value === "bigint" + ? value.toString() : value, whitespace ) diff --git a/packages/effect/src/internal/cause.ts b/packages/effect/src/internal/cause.ts index 38bcbb4ddd1..78ad3465953 100644 --- a/packages/effect/src/internal/cause.ts +++ b/packages/effect/src/internal/cause.ts @@ -977,10 +977,16 @@ export const pretty = (cause: Cause.Cause, options?: { return "All fibers interrupted without errors." } return prettyErrors(cause).map(function(e) { - if (options?.renderErrorCause !== true || e.cause === undefined) { + if (options?.renderErrorCause !== true) { return e.stack } - return `${e.stack} {\n${renderErrorCause(e.cause as PrettyError, " ")}\n}` + const { cause, message: _, name: __, stack, ...rest } = e + const json = stringifyCircular(toJSON(rest), 2) + return !cause && !!Object.keys(rest).length ? + stack : + `${stack} {${json.substring(1, json.length - 1).split("\n").join("\n").trimEnd()}${ + cause ? ",\n" + renderErrorCause(cause as PrettyError, " ") : "" + }\n}` }).join("\n") } diff --git a/packages/effect/test/Cause.test.ts b/packages/effect/test/Cause.test.ts index e1efbb31f30..72f669b2c41 100644 --- a/packages/effect/test/Cause.test.ts +++ b/packages/effect/test/Cause.test.ts @@ -8,6 +8,7 @@ import * as Predicate from "effect/Predicate" import { causes, equalCauses, errorCauseFunctions, errors } from "effect/test/utils/cause" import * as fc from "fast-check" import { assert, describe, expect, it } from "vitest" +import { Data } from "../src/index.js" describe("Cause", () => { it("[internal] prettyErrorMessage", () => { @@ -81,6 +82,19 @@ describe("Cause", () => { } } expect(Cause.pretty(Cause.fail(new Error5()))).toEqual(`Error: my string`) + + class Error6 extends Data.TaggedError("Error6")<{ message: string; code: number; cause: Error }> { + } + expect( + Cause.pretty(Cause.fail(new Error6({ message: "test", code: 10, cause: new Error("cause") })), { + renderErrorCause: true + }) + ).includes( + `{ + "code": 10, + "_tag": "Error6", + [cause]: Error: cause` + ) }) it("Interrupt", () => { @@ -350,7 +364,7 @@ describe("Cause", () => { if (typeof window === "undefined") { // eslint-disable-next-line @typescript-eslint/no-var-requires const { inspect } = require("node:util") - expect(inspect(ex)).include("Cause.test.ts:348") + expect(inspect(ex)).include("Cause.test.ts:362") } }) })