1import { assert, describe, it } from "@effect/vitest"
2import { Schema, SchemaRepresentation } from "effect"
3
4function decode(schema: Schema.Top, input: unknown): unknown {
5 return Schema.decodeUnknownSync(schema as Schema.Codec<unknown>)(input)
6}
7
8describe("SchemaRepresentation.fromRepresentations", () => {
9 it("preserves root order", () => {
10 const schemas = SchemaRepresentation.fromRepresentations({
11 representations: [
12 { _tag: "String", checks: [] },
13 { _tag: "Boolean", checks: [] },
14 { _tag: "Number", checks: [] }
15 ],
16 references: {}
17 }, { revivers: [] })
18
19 assert.strictEqual(decode(schemas[0], "value"), "value")
20 assert.strictEqual(decode(schemas[1], true), true)
21 assert.strictEqual(decode(schemas[2], 1), 1)
22 })
23
24 it("does not revive unreachable references", () => {
25 const schemas = SchemaRepresentation.fromRepresentations({
26 representations: [{ _tag: "String", checks: [] }],
27 references: {
28 Unused: {
29 _tag: "Declaration",
30 typeParameters: [],
31 representation: { id: "missing", payload: null },
32 checks: []
33 }
34 }
35 }, { revivers: [] })
36
37 assert.strictEqual(decode(schemas[0], "value"), "value")
38 })
39
40 it("normalizes aliases while preserving the outer reference", () => {
41 const schemas = SchemaRepresentation.fromRepresentations({
42 representations: [{ _tag: "Reference", $ref: "Alias" }],
43 references: {
44 Alias: { _tag: "Reference", $ref: "Value" },
45 Value: { _tag: "String", checks: [] }
46 }
47 }, { revivers: [] })
48
49 assert.strictEqual(schemas[0].ast._tag, "String")
50 assert.strictEqual(decode(schemas[0], "value"), "value")
51 assert.deepStrictEqual(SchemaRepresentation.toRepresentation(schemas[0].ast).representation, {
52 _tag: "Reference",
53 $ref: "Alias"
54 })
55 })
56
57 it("shares a resolved reference between roots", () => {
58 const schemas = SchemaRepresentation.fromRepresentations({
59 representations: [
60 { _tag: "Reference", $ref: "Shared" },
61 { _tag: "Reference", $ref: "Shared" }
62 ],
63 references: {
64 Shared: { _tag: "Number", checks: [] }
65 }
66 }, { revivers: [] })
67
68 assert.strictEqual(schemas[0], schemas[1])
69 assert.strictEqual(schemas[0].ast._tag, "Number")
70 })
71
72 it("resolves a reachable __proto__ reference", () => {
73 const references: Record<string, SchemaRepresentation.Representation> = {}
74 Object.defineProperty(references, "__proto__", {
75 value: { _tag: "String", checks: [] },
76 enumerable: true
77 })
78 const schemas = SchemaRepresentation.fromRepresentations({
79 representations: [{ _tag: "Reference", $ref: "__proto__" }],
80 references
81 }, { revivers: [] })
82
83 assert.strictEqual(decode(schemas[0], "value"), "value")
84 })
85
86 it("revives recursive definitions", () => {
87 const schemas = SchemaRepresentation.fromRepresentations({
88 representations: [{ _tag: "Reference", $ref: "Recursive" }],
89 references: {
90 Recursive: {
91 _tag: "Objects",
92 checks: [],
93 propertySignatures: [
94 {
95 name: "value",
96 type: { _tag: "Number", checks: [] },
97 isOptional: false,
98 isMutable: false
99 },
100 {
101 name: "next",
102 type: { _tag: "Reference", $ref: "Recursive" },
103 isOptional: true,
104 isMutable: false
105 }
106 ],
107 indexSignatures: []
108 }
109 }
110 }, { revivers: [] })
111
112 assert.strictEqual(schemas[0].ast._tag, "Objects")
113 if (schemas[0].ast._tag === "Objects") {
114 assert.strictEqual(schemas[0].ast.propertySignatures[1].type._tag, "Suspend")
115 }
116 assert.deepStrictEqual(
117 decode(schemas[0], {
118 value: 1,
119 next: { value: 2 }
120 }),
121 {
122 value: 1,
123 next: { value: 2 }
124 }
125 )
126 })
127
128 it("revives mutually recursive definitions with concrete roots", () => {
129 const schemas = SchemaRepresentation.fromRepresentations({
130 representations: [
131 { _tag: "Reference", $ref: "A" },
132 { _tag: "Reference", $ref: "B" }
133 ],
134 references: {
135 A: {
136 _tag: "Objects",
137 checks: [],
138 propertySignatures: [{
139 name: "b",
140 type: { _tag: "Reference", $ref: "B" },
141 isOptional: true,
142 isMutable: false
143 }],
144 indexSignatures: []
145 },
146 B: {
147 _tag: "Objects",
148 checks: [],
149 propertySignatures: [{
150 name: "a",
151 type: { _tag: "Reference", $ref: "A" },
152 isOptional: true,
153 isMutable: false
154 }],
155 indexSignatures: []
156 }
157 }
158 }, { revivers: [] })
159
160 assert.strictEqual(schemas[0].ast._tag, "Objects")
161 assert.strictEqual(schemas[1].ast._tag, "Objects")
162 if (schemas[0].ast._tag === "Objects" && schemas[1].ast._tag === "Objects") {
163 const b = schemas[0].ast.propertySignatures[0].type
164 const a = schemas[1].ast.propertySignatures[0].type
165 assert.isTrue(b._tag === "Suspend" || a._tag === "Suspend")
166 }
167 assert.deepStrictEqual(decode(schemas[0], { b: { a: {} } }), { b: { a: {} } })
168 assert.deepStrictEqual(decode(schemas[1], { a: { b: {} } }), { a: { b: {} } })
169 })
170})