Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/brown-glasses-thank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"effect": patch
---

Handle BigInt values safely when formatting JSON diagnostics.
10 changes: 7 additions & 3 deletions packages/effect/src/Formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,10 @@ function safeToString(input: any): string {
* Uses `JSON.stringify` internally with a replacer that tracks the current
* object ancestry. Circular references are replaced with `undefined`, which
* omits them from object output. `Redactable` values are automatically redacted
* before serialization. Values not supported by JSON, such as `BigInt`,
* `Symbol`, `undefined`, and functions, follow standard `JSON.stringify`
* behavior. The `space` parameter controls indentation and defaults to `0`.
* before serialization. `BigInt` values are stringified with an `n` suffix.
* Other values not supported by JSON, such as `Symbol`, `undefined`, and
* functions, follow standard `JSON.stringify` behavior. The `space` parameter
* controls indentation and defaults to `0`.
*
* **Example** (Formatting compact JSON)
*
Expand Down Expand Up @@ -302,6 +303,9 @@ export function formatJson(input: unknown, options?: {
input,
function(this: unknown, _key: string, value: unknown) {
const redacted = redact(value)
if (typeof redacted === "bigint") {
return `${redacted}n`
}
if (typeof redacted !== "object" || redacted === null) {
return redacted
}
Expand Down
18 changes: 17 additions & 1 deletion packages/effect/test/Formatter.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Context, Option, Redactable, Redacted, Schema } from "effect"
import { Context, Inspectable, Option, Redactable, Redacted, Schema } from "effect"
import { format, formatJson } from "effect/Formatter"
import { describe, it } from "vitest"
import { strictEqual } from "./utils/assert.ts"
Expand Down Expand Up @@ -239,9 +239,25 @@ describe("Formatter", () => {
strictEqual(formatJson({ left: shared, right: shared }), `{"left":{"a":1},"right":{"a":1}}`)
})

it("should stringify BigInt values", () => {
strictEqual(formatJson({ value: 123n }), `{"value":"123n"}`)
strictEqual(formatJson([1n, 2n]), `["1n","2n"]`)
})

it("should redact sensitive data", () => {
strictEqual(formatJson(data), `{"secret":"[REDACTED]"}`)
strictEqual(formatJson({ a: data }), `{"a":{"secret":"[REDACTED]"}}`)
})
})

describe("Inspectable.toStringUnknown", () => {
it("should stringify BigInt values", () => {
strictEqual(
Inspectable.toStringUnknown({ value: 123n }),
`{
"value": "123n"
}`
)
})
})
})