1import { assertTrue, deepStrictEqual } from "@effect/vitest/utils"
2import { Schema } from "effect"
3import type { StandardJSONSchemaV1 } from "effect/StandardSchema"
4import { describe, it } from "vitest"
5
6function standardConvertToJSONSchemaInput(
7 schema: StandardJSONSchemaV1,
8 target?: StandardJSONSchemaV1.Target
9): Record<string, unknown> {
10 return schema["~standard"].jsonSchema.input({
11 target: target ?? "draft-2020-12"
12 })
13}
14
15function standardConvertToJSONSchemaOutput(
16 schema: StandardJSONSchemaV1,
17 target?: StandardJSONSchemaV1.Target
18): Record<string, unknown> {
19 return schema["~standard"].jsonSchema.output({
20 target: target ?? "draft-2020-12"
21 })
22}
23
24describe("toStandardJSONSchemaV1", () => {
25 it("should return a schema with Standard JSON Schema metadata", () => {
26 const schema = Schema.FiniteFromString
27 const standardSchema = Schema.toStandardJSONSchemaV1(schema)
28 assertTrue(Schema.isSchema(standardSchema))
29 })
30
31 it("should support both standards", () => {
32 const schema = Schema.String
33 const both = Schema.toStandardSchemaV1(Schema.toStandardJSONSchemaV1(schema))
34 deepStrictEqual(standardConvertToJSONSchemaInput(both), {
35 "type": "string"
36 })
37 })
38
39 describe("draft-2020-12", () => {
40 it("should return the input JSON Schema", () => {
41 const schema = Schema.Tuple([Schema.FiniteFromString])
42 const standardJSONSchema = Schema.toStandardJSONSchemaV1(schema)
43 deepStrictEqual(standardConvertToJSONSchemaInput(standardJSONSchema), {
44 "type": "array",
45 "prefixItems": [{ "type": "string" }],
46 "minItems": 1,
47 "maxItems": 1
48 })
49 })
50
51 it("should return the output JSON Schema", () => {
52 const schema = Schema.Tuple([Schema.FiniteFromString])
53 const standardJSONSchema = Schema.toStandardJSONSchemaV1(schema)
54 deepStrictEqual(standardConvertToJSONSchemaOutput(standardJSONSchema), {
55 "type": "array",
56 "prefixItems": [{ "type": "number" }],
57 "minItems": 1,
58 "maxItems": 1
59 })
60 })
61
62 it("a schema with identifier", () => {
63 const S = Schema.String.annotate({ identifier: "id" })
64 const schema = Schema.Tuple([S, S])
65 const standardJSONSchema = Schema.toStandardJSONSchemaV1(schema)
66 deepStrictEqual(standardConvertToJSONSchemaInput(standardJSONSchema), {
67 "type": "array",
68 "prefixItems": [
69 { "$ref": "#/$defs/id" },
70 { "$ref": "#/$defs/id" }
71 ],
72 "minItems": 2,
73 "maxItems": 2,
74 "$defs": {
75 "id": {
76 "type": "string"
77 }
78 }
79 })
80 })
81 })
82
83 describe("draft-07", () => {
84 it("should return the input JSON Schema", () => {
85 const schema = Schema.Tuple([Schema.FiniteFromString])
86 const standardJSONSchema = Schema.toStandardJSONSchemaV1(schema)
87 deepStrictEqual(standardConvertToJSONSchemaInput(standardJSONSchema, "draft-07"), {
88 "type": "array",
89 "items": [{ "type": "string" }],
90 "minItems": 1,
91 "maxItems": 1
92 })
93 })
94
95 it("should return the output JSON Schema", () => {
96 const schema = Schema.Tuple([Schema.FiniteFromString])
97 const standardJSONSchema = Schema.toStandardJSONSchemaV1(schema)
98 deepStrictEqual(standardConvertToJSONSchemaOutput(standardJSONSchema, "draft-07"), {
99 "type": "array",
100 "items": [{ "type": "number" }],
101 "minItems": 1,
102 "maxItems": 1
103 })
104 })
105
106 it("a schema with identifier", () => {
107 const S = Schema.String.annotate({ identifier: "id" })
108 const schema = Schema.Tuple([S, S])
109 const standardJSONSchema = Schema.toStandardJSONSchemaV1(schema)
110 deepStrictEqual(standardConvertToJSONSchemaInput(standardJSONSchema, "draft-07"), {
111 "type": "array",
112 "items": [
113 { "$ref": "#/definitions/id" },
114 { "$ref": "#/definitions/id" }
115 ],
116 "minItems": 2,
117 "maxItems": 2,
118 "definitions": {
119 "id": {
120 "type": "string"
121 }
122 }
123 })
124 })
125 })
126})