1import * as Schema from "effect/Schema"
2import { enable } from "effect/schema/SchemaJITCompiler"
3import * as SchemaIssue from "effect/SchemaIssue"
4import * as SchemaParser from "effect/SchemaParser"
5import assert from "node:assert/strict"
6
7const fixture = (kind: "struct" | "extra" | "strings" | "symbols", strict: boolean, jit: boolean) => {
8 const schema = kind === "symbols"
9 ? Schema.Record(Schema.Symbol, Schema.Number)
10 : kind === "strings"
11 ? Schema.Record(Schema.String, Schema.Number)
12 : Schema.Struct({ name: Schema.String, age: Schema.Number, active: Schema.Boolean })
13 const input = kind === "symbols" || kind === "strings"
14 ? Object.fromEntries(Array.from({ length: 32 }, (_, i) => [kind === "symbols" ? Symbol(`key${i}`) : `key${i}`, i]))
15 : kind === "extra"
16 ? { name: "Ada", age: 37, active: true, extra: 1 }
17 : { name: "Ada", age: 37, active: true }
18 if (jit) enable(schema.ast)
19 const decode = SchemaParser.decodeUnknownSync(schema, strict ? { onExcessProperty: "error" } : undefined)
20 return {
21 run: kind === "extra"
22 ? () => {
23 try {
24 return decode(input)
25 } catch (error) {
26 return error
27 }
28 }
29 : () => decode(input),
30 validate: (result: unknown) => {
31 if (kind === "extra") {
32 assert.ok(result instanceof Error)
33 assert.ok(SchemaIssue.isIssue(result.cause))
34 assert.equal(SchemaIssue.defaultFormatter(result.cause), "Expected no excess property\n at [\"extra\"]")
35 } else {
36 assert.deepEqual(result, input)
37 }
38 }
39 }
40}
41
42export const interpretedStructDefault = () => fixture("struct", false, false)
43export const jitStructDefault = () => fixture("struct", false, true)
44export const interpretedStructStrict = () => fixture("struct", true, false)
45export const jitStructStrict = () => fixture("struct", true, true)
46export const interpretedExtraStrict = () => fixture("extra", true, false)
47export const jitExtraStrict = () => fixture("extra", true, true)
48export const interpretedStringsStrict = () => fixture("strings", true, false)
49export const jitStringsStrict = () => fixture("strings", true, true)
50export const interpretedSymbolsDefault = () => fixture("symbols", false, false)
51export const jitSymbolsDefault = () => fixture("symbols", false, true)
52export const interpretedSymbolsStrict = () => fixture("symbols", true, false)
53export const jitSymbolsStrict = () => fixture("symbols", true, true)