@elaraai/east 1.0.70 → 1.0.72
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/expr/libs/string.d.ts +15 -2
- package/dist/src/expr/libs/string.d.ts.map +1 -1
- package/dist/src/expr/libs/string.js +15 -2
- package/dist/src/expr/libs/string.js.map +1 -1
- package/dist/src/location.d.ts +12 -0
- package/dist/src/location.d.ts.map +1 -1
- package/dist/src/location.js +15 -3
- package/dist/src/location.js.map +1 -1
- package/dist/src/serialization/index.d.ts +2 -0
- package/dist/src/serialization/index.d.ts.map +1 -1
- package/dist/src/serialization/index.js +2 -0
- package/dist/src/serialization/index.js.map +1 -1
- package/dist/src/serialization/json.d.ts +43 -2
- package/dist/src/serialization/json.d.ts.map +1 -1
- package/dist/src/serialization/json.js +138 -9
- package/dist/src/serialization/json.js.map +1 -1
- package/dist/src/serialization/json.spec.js +99 -15
- package/dist/src/serialization/json.spec.js.map +1 -1
- package/dist/src/serialization/json_schema.d.ts +81 -0
- package/dist/src/serialization/json_schema.d.ts.map +1 -0
- package/dist/src/serialization/json_schema.js +305 -0
- package/dist/src/serialization/json_schema.js.map +1 -0
- package/dist/src/serialization/json_schema.spec.d.ts +2 -0
- package/dist/src/serialization/json_schema.spec.d.ts.map +1 -0
- package/dist/src/serialization/json_schema.spec.js +427 -0
- package/dist/src/serialization/json_schema.spec.js.map +1 -0
- package/dist/src/serialization/json_schema_to_type.d.ts +76 -0
- package/dist/src/serialization/json_schema_to_type.d.ts.map +1 -0
- package/dist/src/serialization/json_schema_to_type.js +576 -0
- package/dist/src/serialization/json_schema_to_type.js.map +1 -0
- package/dist/src/serialization/json_schema_to_type.spec.d.ts +2 -0
- package/dist/src/serialization/json_schema_to_type.spec.d.ts.map +1 -0
- package/dist/src/serialization/json_schema_to_type.spec.js +428 -0
- package/dist/src/serialization/json_schema_to_type.spec.js.map +1 -0
- package/package.json +2 -1
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, test } from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { createHash } from "node:crypto";
|
|
8
|
+
import { Ajv } from "ajv";
|
|
9
|
+
import { Ajv2020 } from "ajv/dist/2020.js";
|
|
10
|
+
import { ArrayType, AsyncFunctionType, BlobType, BooleanType, DateTimeType, DictType, FloatType, FunctionType, IntegerType, MatrixType, NeverType, NullType, OptionType, RecursiveType, RefType, SetType, StringType, StructType, VariantType, VectorType, } from "../types.js";
|
|
11
|
+
import { none, some } from "../containers/variant.js";
|
|
12
|
+
import { EAST_JSON_PATTERNS, jsonSchemaFor } from "./json_schema.js";
|
|
13
|
+
import { toJSONFor } from "./json.js";
|
|
14
|
+
/**
|
|
15
|
+
* A validator a partner would use, for the releases JSON Schema validators
|
|
16
|
+
* implement. Unknown keywords (`x-east-type`) and formats are tolerated, as a
|
|
17
|
+
* partner's validator would be configured to tolerate them.
|
|
18
|
+
*/
|
|
19
|
+
function validatorFor(draft, schema) {
|
|
20
|
+
const ajv = draft === "2020-12"
|
|
21
|
+
? new Ajv2020({ strict: false, validateFormats: false })
|
|
22
|
+
: new Ajv({ strict: false, validateFormats: false });
|
|
23
|
+
const validate = ajv.compile(schema);
|
|
24
|
+
return (doc) => validate(doc) === true;
|
|
25
|
+
}
|
|
26
|
+
/** The pattern a leaf type's schema pins, as a compiled regex. */
|
|
27
|
+
function patternOf(schema) {
|
|
28
|
+
const pattern = schema["pattern"];
|
|
29
|
+
assert.equal(typeof pattern, "string", "expected the schema to carry a pattern");
|
|
30
|
+
return new RegExp(pattern);
|
|
31
|
+
}
|
|
32
|
+
/** A schema with `$schema` dropped, for comparing the body alone. */
|
|
33
|
+
function body(schema) {
|
|
34
|
+
const { $schema: _drop, ...rest } = schema;
|
|
35
|
+
return rest;
|
|
36
|
+
}
|
|
37
|
+
describe("jsonSchemaFor", () => {
|
|
38
|
+
describe("primitives", () => {
|
|
39
|
+
test("describes Null, Boolean and String directly", () => {
|
|
40
|
+
assert.deepEqual(body(jsonSchemaFor(NullType)), { type: "null" });
|
|
41
|
+
assert.deepEqual(body(jsonSchemaFor(BooleanType)), { type: "boolean" });
|
|
42
|
+
assert.deepEqual(body(jsonSchemaFor(StringType)), { type: "string" });
|
|
43
|
+
});
|
|
44
|
+
test("describes Float as a number or one of the non-finite spellings", () => {
|
|
45
|
+
assert.deepEqual(body(jsonSchemaFor(FloatType)), {
|
|
46
|
+
oneOf: [
|
|
47
|
+
{ type: "number" },
|
|
48
|
+
{ type: "string", enum: ["-0.0", "-Infinity", "Infinity", "NaN"] },
|
|
49
|
+
],
|
|
50
|
+
"x-east-type": "Float",
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
test("stamps $schema for the releases that carry one", () => {
|
|
54
|
+
assert.equal(jsonSchemaFor(StringType)["$schema"], "https://json-schema.org/draft/2020-12/schema");
|
|
55
|
+
assert.equal(jsonSchemaFor(StringType, { draft: "draft-07" })["$schema"], "http://json-schema.org/draft-07/schema#");
|
|
56
|
+
// An OpenAPI 3.0 schema object lives inside an OpenAPI document and
|
|
57
|
+
// has no $schema of its own.
|
|
58
|
+
assert.equal(jsonSchemaFor(StringType, { draft: "openapi-3.0" })["$schema"], undefined);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
describe("Integer", () => {
|
|
62
|
+
const pattern = patternOf(jsonSchemaFor(IntegerType));
|
|
63
|
+
test("accepts exactly the i64 range", () => {
|
|
64
|
+
for (const ok of ["0", "1", "-1", "42", "9223372036854775807", "-9223372036854775808"]) {
|
|
65
|
+
assert.ok(pattern.test(ok), `${ok} should be accepted`);
|
|
66
|
+
}
|
|
67
|
+
for (const bad of ["9223372036854775808", "-9223372036854775809"]) {
|
|
68
|
+
assert.ok(!pattern.test(bad), `${bad} should be rejected`);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
test("rejects an unsigned 64-bit id", () => {
|
|
72
|
+
// The naive `^(0|-?[1-9][0-9]{0,18})$` admits this, so a producer
|
|
73
|
+
// would validate it and we would then reject it on receipt.
|
|
74
|
+
assert.ok(!pattern.test("18446744073709551615"));
|
|
75
|
+
assert.ok(!pattern.test("9999999999999999999"));
|
|
76
|
+
});
|
|
77
|
+
test("rejects everything the decoder tolerates but the encoder never emits", () => {
|
|
78
|
+
// BigInt() accepts all of these; the published contract must not.
|
|
79
|
+
for (const bad of ["0x10", "0b101", "0o17", " 7 ", "+7", "007", "-0", "", "1e3", "7.5"]) {
|
|
80
|
+
assert.ok(!pattern.test(bad), `${JSON.stringify(bad)} should be rejected`);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
test("accepts everything the encoder emits", () => {
|
|
84
|
+
const encode = toJSONFor(IntegerType);
|
|
85
|
+
const values = [
|
|
86
|
+
0n, 1n, -1n, 7n, -7n, 10n, 99n, 100n, 12345n, -12345n,
|
|
87
|
+
9007199254740993n, -9007199254740993n,
|
|
88
|
+
9223372036854775807n, -9223372036854775808n,
|
|
89
|
+
];
|
|
90
|
+
for (const v of values) {
|
|
91
|
+
assert.ok(pattern.test(encode(v)), `encoder output for ${v} should validate`);
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
describe("DateTime", () => {
|
|
96
|
+
const pattern = patternOf(jsonSchemaFor(DateTimeType));
|
|
97
|
+
test("accepts the canonical form the encoder emits", () => {
|
|
98
|
+
const encode = toJSONFor(DateTimeType);
|
|
99
|
+
for (const d of [new Date(0), new Date("2022-06-29T13:43:00.123Z"), new Date("2026-12-31T23:59:59.999Z")]) {
|
|
100
|
+
assert.ok(pattern.test(encode(d)), `${encode(d)} should validate`);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
test("rejects the offsets the decoder tolerates", () => {
|
|
104
|
+
// The decoder takes a Z suffix or any numeric offset; the encoder
|
|
105
|
+
// only ever writes +00:00, so the contract pins that.
|
|
106
|
+
assert.ok(!pattern.test("2022-06-29T13:43:00.123Z"));
|
|
107
|
+
assert.ok(!pattern.test("2022-06-29T13:43:00.123+05:00"));
|
|
108
|
+
assert.ok(!pattern.test("2022-06-29T13:43:00.123-08:00"));
|
|
109
|
+
});
|
|
110
|
+
test("rejects out-of-range calendar fields", () => {
|
|
111
|
+
for (const bad of [
|
|
112
|
+
"0000-01-01T00:00:00.000+00:00", // year 0, below the range every runtime reads
|
|
113
|
+
"2022-13-29T13:43:00.123+00:00", // month 13
|
|
114
|
+
"2022-06-32T13:43:00.123+00:00", // day 32
|
|
115
|
+
"2022-06-29T24:43:00.123+00:00", // hour 24
|
|
116
|
+
"2022-06-29T13:60:00.123+00:00", // minute 60
|
|
117
|
+
"2022-06-29T13:43:60.123+00:00", // second 60
|
|
118
|
+
"2022-06-29T13:43:00+00:00", // no milliseconds
|
|
119
|
+
"2022-06-29 13:43:00.123+00:00", // space, not T
|
|
120
|
+
]) {
|
|
121
|
+
assert.ok(!pattern.test(bad), `${bad} should be rejected`);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
test("accepts the first and last years the reader does", () => {
|
|
125
|
+
assert.ok(pattern.test("0001-01-01T00:00:00.000+00:00"));
|
|
126
|
+
assert.ok(pattern.test("9999-12-31T23:59:59.999+00:00"));
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
describe("digit classes", () => {
|
|
130
|
+
test("spells every digit as [0-9], never \\d", () => {
|
|
131
|
+
// A validator built on python's `re` reads \d as any Unicode digit,
|
|
132
|
+
// so a timestamp in Arabic-Indic digits would pass a partner's check
|
|
133
|
+
// and then fail on receipt. The contract has to read the same on
|
|
134
|
+
// every regex engine a partner might use.
|
|
135
|
+
for (const p of [EAST_JSON_PATTERNS.integer, EAST_JSON_PATTERNS.datetime, EAST_JSON_PATTERNS.blob]) {
|
|
136
|
+
assert.ok(!p.includes("\\d"), `${p} must not use \\d`);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
describe("Blob", () => {
|
|
141
|
+
const pattern = patternOf(jsonSchemaFor(BlobType));
|
|
142
|
+
test("accepts the lowercase hex the encoder emits", () => {
|
|
143
|
+
const encode = toJSONFor(BlobType);
|
|
144
|
+
assert.ok(pattern.test(encode(new Uint8Array([]))));
|
|
145
|
+
assert.ok(pattern.test(encode(new Uint8Array([1, 3, 3, 7]))));
|
|
146
|
+
assert.ok(pattern.test(encode(new Uint8Array([0xde, 0xad, 0xbe, 0xef]))));
|
|
147
|
+
});
|
|
148
|
+
test("rejects uppercase hex, which only the decoder allows", () => {
|
|
149
|
+
assert.ok(!pattern.test("0xDEADBEEF"));
|
|
150
|
+
assert.ok(!pattern.test("0xAb"));
|
|
151
|
+
});
|
|
152
|
+
test("rejects a missing prefix or an odd digit count", () => {
|
|
153
|
+
assert.ok(!pattern.test("deadbeef"));
|
|
154
|
+
assert.ok(!pattern.test("0x123"));
|
|
155
|
+
assert.ok(!pattern.test("0xgg"));
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
describe("collections", () => {
|
|
159
|
+
test("describes Array as an array of its element", () => {
|
|
160
|
+
assert.deepEqual(body(jsonSchemaFor(ArrayType(StringType))), {
|
|
161
|
+
type: "array",
|
|
162
|
+
items: { type: "string" },
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
test("marks Set unique", () => {
|
|
166
|
+
assert.deepEqual(body(jsonSchemaFor(SetType(StringType))), {
|
|
167
|
+
type: "array",
|
|
168
|
+
items: { type: "string" },
|
|
169
|
+
uniqueItems: true,
|
|
170
|
+
"x-east-type": "Set",
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
test("describes Dict as its array-of-entries encoding", () => {
|
|
174
|
+
assert.deepEqual(body(jsonSchemaFor(DictType(StringType, BooleanType))), {
|
|
175
|
+
type: "array",
|
|
176
|
+
items: {
|
|
177
|
+
type: "object",
|
|
178
|
+
properties: { key: { type: "string" }, value: { type: "boolean" } },
|
|
179
|
+
required: ["key", "value"],
|
|
180
|
+
additionalProperties: false,
|
|
181
|
+
},
|
|
182
|
+
uniqueItems: true,
|
|
183
|
+
"x-east-type": "Dict",
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
test("closes Struct to its declared fields, all required", () => {
|
|
187
|
+
const schema = body(jsonSchemaFor(StructType({ a: StringType, b: BooleanType })));
|
|
188
|
+
assert.equal(schema["type"], "object");
|
|
189
|
+
assert.deepEqual(schema["required"], ["a", "b"]);
|
|
190
|
+
assert.equal(schema["additionalProperties"], false);
|
|
191
|
+
});
|
|
192
|
+
test("describes Vector and Matrix as arrays", () => {
|
|
193
|
+
assert.deepEqual(body(jsonSchemaFor(VectorType(FloatType)))["type"], "array");
|
|
194
|
+
const m = body(jsonSchemaFor(MatrixType(IntegerType)));
|
|
195
|
+
assert.equal(m["type"], "array");
|
|
196
|
+
assert.equal(m["items"]["type"], "array");
|
|
197
|
+
});
|
|
198
|
+
test("describes Ref as a one-element array, without the aliasing form", () => {
|
|
199
|
+
// The encoder ALSO writes {"$ref": …} for a target it has already
|
|
200
|
+
// written, but no reader resolves that back — a streaming reader has
|
|
201
|
+
// discarded what the pointer refers to — so advertising it would
|
|
202
|
+
// describe documents the reader then rejects. Excluded for the same
|
|
203
|
+
// reason as Array/Set/Dict aliasing, with the same stated
|
|
204
|
+
// consequence: a value with shared references does not validate
|
|
205
|
+
// against its own published schema.
|
|
206
|
+
assert.deepEqual(body(jsonSchemaFor(RefType(StringType))), {
|
|
207
|
+
type: "array",
|
|
208
|
+
items: { type: "string" },
|
|
209
|
+
minItems: 1,
|
|
210
|
+
maxItems: 1,
|
|
211
|
+
"x-east-type": "Ref",
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
describe("Variant", () => {
|
|
216
|
+
test("pins each case's tag and closes the object", () => {
|
|
217
|
+
const schema = body(jsonSchemaFor(VariantType({ ok: IntegerType, err: StringType })));
|
|
218
|
+
const alternatives = schema["oneOf"];
|
|
219
|
+
// VariantType sorts its cases, so the order is fixed by the type.
|
|
220
|
+
assert.equal(alternatives.length, 2);
|
|
221
|
+
const tags = alternatives.map(a => a["properties"]["type"]["const"]);
|
|
222
|
+
assert.deepEqual(tags, ["err", "ok"]);
|
|
223
|
+
for (const a of alternatives) {
|
|
224
|
+
assert.deepEqual(a["required"], ["type", "value"]);
|
|
225
|
+
assert.equal(a["additionalProperties"], false);
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
test("uses a single-valued enum where the release has no const", () => {
|
|
229
|
+
const schema = body(jsonSchemaFor(VariantType({ ok: IntegerType, err: StringType }), { draft: "openapi-3.0" }));
|
|
230
|
+
const alternatives = schema["oneOf"];
|
|
231
|
+
const tag = alternatives[0]["properties"]["type"];
|
|
232
|
+
assert.deepEqual(tag["enum"], ["err"]);
|
|
233
|
+
assert.equal(tag["const"], undefined);
|
|
234
|
+
});
|
|
235
|
+
});
|
|
236
|
+
describe("Option", () => {
|
|
237
|
+
test("describes a flat Option as null or its payload, annotated", () => {
|
|
238
|
+
// The one type-directed choice of form East JSON makes: an Option
|
|
239
|
+
// whose payload can never encode as null is null or the payload.
|
|
240
|
+
assert.deepEqual(body(jsonSchemaFor(OptionType(StringType))), {
|
|
241
|
+
oneOf: [{ type: "null" }, { type: "string" }],
|
|
242
|
+
"x-east-type": "Option",
|
|
243
|
+
});
|
|
244
|
+
// The null alternative is the release's own spelling of Null.
|
|
245
|
+
assert.deepEqual(body(jsonSchemaFor(OptionType(StringType), { draft: "openapi-3.0" })), {
|
|
246
|
+
oneOf: [{ nullable: true, enum: [null] }, { type: "string" }],
|
|
247
|
+
"x-east-type": "Option",
|
|
248
|
+
});
|
|
249
|
+
// A variant is always an object, so it is a flat payload.
|
|
250
|
+
const inner = body(jsonSchemaFor(OptionType(VariantType({ ok: NullType, err: StringType }))));
|
|
251
|
+
assert.equal(inner["x-east-type"], "Option");
|
|
252
|
+
assert.deepEqual(inner["oneOf"][0], { type: "null" });
|
|
253
|
+
});
|
|
254
|
+
test("keeps the tagged form where the payload can itself be null", () => {
|
|
255
|
+
// some(none) must stay distinct from none, and some(null) from
|
|
256
|
+
// none, so these two carry the tag — and no Option annotation.
|
|
257
|
+
for (const T of [OptionType(NullType), OptionType(OptionType(StringType))]) {
|
|
258
|
+
const schema = body(jsonSchemaFor(T));
|
|
259
|
+
assert.equal(schema["x-east-type"], undefined);
|
|
260
|
+
const tags = schema["oneOf"]
|
|
261
|
+
.map(a => a["properties"]["type"]["const"]);
|
|
262
|
+
assert.deepEqual(tags, ["none", "some"]);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
test("judges a recursive payload by what the wrapper encodes", () => {
|
|
266
|
+
// next: Option<self> is the ordinary linked list; self is a struct.
|
|
267
|
+
const ChainType = RecursiveType((self) => StructType({ head: IntegerType, next: OptionType(self) }));
|
|
268
|
+
const schema = jsonSchemaFor(ChainType);
|
|
269
|
+
const properties = schema["$defs"]["Recursive1"]["properties"];
|
|
270
|
+
assert.deepEqual(properties["next"], {
|
|
271
|
+
oneOf: [{ type: "null" }, { $ref: "#/$defs/Recursive1" }],
|
|
272
|
+
"x-east-type": "Option",
|
|
273
|
+
});
|
|
274
|
+
assert.equal(body(jsonSchemaFor(OptionType(ChainType)))["x-east-type"], "Option");
|
|
275
|
+
});
|
|
276
|
+
test("a flat none validates and the tagged object no longer does, under a real validator", () => {
|
|
277
|
+
// What the encoder writes validates against the published schema,
|
|
278
|
+
// and the object the old encoding wrote is now refused by it — for
|
|
279
|
+
// every form an Option takes, in the releases validators implement.
|
|
280
|
+
const RowType = StructType({
|
|
281
|
+
note: OptionType(StringType),
|
|
282
|
+
count: OptionType(IntegerType),
|
|
283
|
+
maybe: OptionType(OptionType(IntegerType)),
|
|
284
|
+
unit: OptionType(NullType),
|
|
285
|
+
flags: ArrayType(OptionType(BooleanType)),
|
|
286
|
+
chain: RecursiveType((self) => StructType({ head: IntegerType, next: OptionType(self) })),
|
|
287
|
+
});
|
|
288
|
+
const rows = [
|
|
289
|
+
{ note: none, count: some(7n), maybe: some(none), unit: some(null), flags: [none, some(true)], chain: { head: 1n, next: some({ head: 2n, next: none }) } },
|
|
290
|
+
{ note: some("x"), count: none, maybe: none, unit: none, flags: [], chain: { head: 0n, next: none } },
|
|
291
|
+
{ note: some(""), count: some(-1n), maybe: some(some(3n)), unit: none, flags: [some(false)], chain: { head: 3n, next: none } },
|
|
292
|
+
];
|
|
293
|
+
const encode = toJSONFor(RowType);
|
|
294
|
+
for (const draft of ["2020-12", "draft-07"]) {
|
|
295
|
+
const valid = validatorFor(draft, jsonSchemaFor(RowType, { draft }));
|
|
296
|
+
for (const row of rows) {
|
|
297
|
+
assert.ok(valid(encode(row)), `${draft}: the encoder's output validates`);
|
|
298
|
+
}
|
|
299
|
+
const base = encode(rows[0]);
|
|
300
|
+
assert.equal(valid({ ...base, note: { type: "none", value: null } }), false, `${draft}: the tagged object no longer validates under a flat Option`);
|
|
301
|
+
assert.equal(valid({ ...base, count: { type: "some", value: "7" } }), false, `${draft}: the tagged object no longer validates under a flat Option`);
|
|
302
|
+
assert.equal(valid({ ...base, maybe: null }), false, `${draft}: a bare null does not validate under an Option of an Option`);
|
|
303
|
+
assert.equal(valid({ ...base, unit: null }), false, `${draft}: a bare null does not validate under an Option of Null`);
|
|
304
|
+
assert.equal(valid({ ...base, chain: { head: "1", next: { type: "none", value: null } } }), false, `${draft}: the tagged object no longer validates through a recursive wrapper`);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
describe("recursive types", () => {
|
|
309
|
+
const LinkedListType = RecursiveType((self) => VariantType({
|
|
310
|
+
nil: NullType,
|
|
311
|
+
cons: StructType({ head: IntegerType, tail: self }),
|
|
312
|
+
}));
|
|
313
|
+
test("lifts the body into $defs and refers to it", () => {
|
|
314
|
+
const schema = jsonSchemaFor(LinkedListType);
|
|
315
|
+
assert.deepEqual(body(schema)["$ref"], "#/$defs/Recursive1");
|
|
316
|
+
const defs = schema["$defs"];
|
|
317
|
+
assert.ok(defs["Recursive1"] !== undefined);
|
|
318
|
+
});
|
|
319
|
+
test("names definitions by encounter order, not by type id", () => {
|
|
320
|
+
// Type ids come from a process-global counter, so a document keyed
|
|
321
|
+
// on them would differ between runs and between languages.
|
|
322
|
+
const a = JSON.stringify(jsonSchemaFor(LinkedListType));
|
|
323
|
+
const b = JSON.stringify(jsonSchemaFor(LinkedListType));
|
|
324
|
+
assert.equal(a, b);
|
|
325
|
+
assert.ok(a.includes("Recursive1"));
|
|
326
|
+
assert.ok(!/Recursive[0-9]{2,}/.test(a));
|
|
327
|
+
});
|
|
328
|
+
test("uses the release's definitions keyword", () => {
|
|
329
|
+
const seven = jsonSchemaFor(LinkedListType, { draft: "draft-07" });
|
|
330
|
+
assert.deepEqual(body(seven)["$ref"], "#/definitions/Recursive1");
|
|
331
|
+
assert.ok(seven["definitions"] !== undefined);
|
|
332
|
+
assert.equal(seven["$defs"], undefined);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
describe("releases", () => {
|
|
336
|
+
test("spells Null without a null type on OpenAPI 3.0", () => {
|
|
337
|
+
assert.deepEqual(body(jsonSchemaFor(NullType, { draft: "openapi-3.0" })), {
|
|
338
|
+
nullable: true,
|
|
339
|
+
enum: [null],
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
test("pins the same integer range in every release", () => {
|
|
343
|
+
const p2020 = jsonSchemaFor(IntegerType)["pattern"];
|
|
344
|
+
const p07 = jsonSchemaFor(IntegerType, { draft: "draft-07" })["pattern"];
|
|
345
|
+
const pOas = jsonSchemaFor(IntegerType, { draft: "openapi-3.0" })["pattern"];
|
|
346
|
+
assert.equal(p2020, p07);
|
|
347
|
+
assert.equal(p07, pOas);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
describe("types with no JSON form", () => {
|
|
351
|
+
test("refuses Never, naming it", () => {
|
|
352
|
+
assert.throws(() => jsonSchemaFor(NeverType), /cannot describe Never/);
|
|
353
|
+
});
|
|
354
|
+
test("refuses functions, naming them", () => {
|
|
355
|
+
assert.throws(() => jsonSchemaFor(FunctionType([], IntegerType)), /cannot describe Function/);
|
|
356
|
+
assert.throws(() => jsonSchemaFor(AsyncFunctionType([], IntegerType)), /cannot describe AsyncFunction/);
|
|
357
|
+
});
|
|
358
|
+
test("refuses a function nested inside a collection", () => {
|
|
359
|
+
assert.throws(() => jsonSchemaFor(StructType({ f: FunctionType([], IntegerType) })), /cannot describe Function/);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
362
|
+
test("matches the cross-language corpus digest", () => {
|
|
363
|
+
// The python twin asserts this same digest over the same corpus in the
|
|
364
|
+
// same order (east-py tests/serialization/test_json_schema.py). Two
|
|
365
|
+
// languages agreeing on one hash is what keeps a partner from being
|
|
366
|
+
// handed different contracts; changing the emitted bytes deliberately
|
|
367
|
+
// means updating both constants, which is the point.
|
|
368
|
+
const RecursiveCorpusType = RecursiveType((self) => VariantType({
|
|
369
|
+
nil: NullType,
|
|
370
|
+
cons: StructType({ head: IntegerType, tail: self }),
|
|
371
|
+
}));
|
|
372
|
+
const ChainCorpusType = RecursiveType((self) => StructType({
|
|
373
|
+
head: IntegerType, next: OptionType(self),
|
|
374
|
+
}));
|
|
375
|
+
const corpus = [
|
|
376
|
+
["Null", NullType], ["Boolean", BooleanType], ["Integer", IntegerType],
|
|
377
|
+
["Float", FloatType], ["String", StringType], ["DateTime", DateTimeType],
|
|
378
|
+
["Blob", BlobType],
|
|
379
|
+
["Array", ArrayType(IntegerType)], ["Set", SetType(StringType)],
|
|
380
|
+
["Dict", DictType(StringType, IntegerType)],
|
|
381
|
+
["Struct", StructType({ a: StringType, b: IntegerType, c: DateTimeType })],
|
|
382
|
+
["Variant", VariantType({ ok: IntegerType, err: StringType })],
|
|
383
|
+
["Option", OptionType(StringType)],
|
|
384
|
+
["Ref", RefType(IntegerType)],
|
|
385
|
+
["Vector", VectorType(FloatType)], ["Matrix", MatrixType(IntegerType)],
|
|
386
|
+
["nested", ArrayType(StructType({
|
|
387
|
+
id: IntegerType, tags: SetType(StringType),
|
|
388
|
+
note: OptionType(StringType), when: DateTimeType,
|
|
389
|
+
}))],
|
|
390
|
+
["recursive", RecursiveCorpusType],
|
|
391
|
+
["arrayRecursive", ArrayType(RecursiveCorpusType)],
|
|
392
|
+
// Every form an Option takes: flat over each kind of payload, and
|
|
393
|
+
// tagged over the two payloads that can themselves be null.
|
|
394
|
+
["optionInteger", OptionType(IntegerType)],
|
|
395
|
+
["optionNull", OptionType(NullType)],
|
|
396
|
+
["optionOption", OptionType(OptionType(StringType))],
|
|
397
|
+
["optionVariant", OptionType(VariantType({ ok: NullType, err: StringType }))],
|
|
398
|
+
["arrayOption", ArrayType(OptionType(StringType))],
|
|
399
|
+
["dictOption", DictType(StringType, OptionType(IntegerType))],
|
|
400
|
+
["optionRecursive", OptionType(RecursiveCorpusType)],
|
|
401
|
+
["chain", ChainCorpusType],
|
|
402
|
+
];
|
|
403
|
+
const lines = [];
|
|
404
|
+
for (const draft of ["2020-12", "draft-07", "openapi-3.0"]) {
|
|
405
|
+
for (const [name, type] of corpus) {
|
|
406
|
+
lines.push(`${draft}|${name}=${JSON.stringify(jsonSchemaFor(type, { draft }))}`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
assert.equal(lines.length, 81);
|
|
410
|
+
assert.equal(createHash("sha256").update(lines.join("\n")).digest("hex"), "457a0ca6a2d616a37c54bbd85bb1cf35908160152761004eb4c83a000755cae0");
|
|
411
|
+
});
|
|
412
|
+
test("emits byte-identical documents for the same type and release", () => {
|
|
413
|
+
const T = StructType({
|
|
414
|
+
id: IntegerType,
|
|
415
|
+
at: DateTimeType,
|
|
416
|
+
tags: SetType(StringType),
|
|
417
|
+
note: OptionType(StringType),
|
|
418
|
+
blob: BlobType,
|
|
419
|
+
});
|
|
420
|
+
for (const draft of ["2020-12", "draft-07", "openapi-3.0"]) {
|
|
421
|
+
const first = JSON.stringify(jsonSchemaFor(ArrayType(T), { draft }));
|
|
422
|
+
const second = JSON.stringify(jsonSchemaFor(ArrayType(T), { draft }));
|
|
423
|
+
assert.equal(first, second, `${draft} output should be stable`);
|
|
424
|
+
}
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
//# sourceMappingURL=json_schema.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json_schema.spec.js","sourceRoot":"","sources":["../../../src/serialization/json_schema.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { type EastType } from "../types.js";
|
|
6
|
+
import type { JsonSchema } from "./json_schema.js";
|
|
7
|
+
/**
|
|
8
|
+
* Raised when a schema cannot be expressed as an East type.
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* Carries the RFC 6901 pointer to the offending node, because a contract
|
|
12
|
+
* document is large and "unsupported keyword" without a location is not
|
|
13
|
+
* actionable.
|
|
14
|
+
*/
|
|
15
|
+
export declare class JsonSchemaUnsupportedError extends Error {
|
|
16
|
+
/** RFC 6901 pointer to the schema node that could not be converted. */
|
|
17
|
+
readonly pointer: string;
|
|
18
|
+
constructor(message: string, pointer: string);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Builds an East type from a JSON Schema document.
|
|
22
|
+
*
|
|
23
|
+
* @param schema - The schema document
|
|
24
|
+
* @returns The East type the schema describes
|
|
25
|
+
* @throws {JsonSchemaUnsupportedError} When the schema uses a keyword East's
|
|
26
|
+
* type system cannot express, naming the keyword and its RFC 6901 pointer
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* This is the one place the full JSON Schema vocabulary is confronted, and it
|
|
30
|
+
* runs at build time, so nothing it rejects can reach a runtime.
|
|
31
|
+
*
|
|
32
|
+
* A document emitted by {@link jsonSchemaFor} carries `x-east-type`
|
|
33
|
+
* annotations and inverts exactly — JSON Schema alone cannot tell `DateTime`
|
|
34
|
+
* from a `String` with `format: date-time`, `Set` from `Array`, or `Dict`
|
|
35
|
+
* from an array of two-property objects. A foreign document without those
|
|
36
|
+
* annotations still converts, under the structural mapping below, but does
|
|
37
|
+
* not promise to round-trip:
|
|
38
|
+
*
|
|
39
|
+
* | schema | East type |
|
|
40
|
+
* |---|---|
|
|
41
|
+
* | `{"type":"null"}`, or OpenAPI 3.0's `nullable` + `enum: [null]` | `Null` |
|
|
42
|
+
* | `{"type":"boolean"}` | `Boolean` |
|
|
43
|
+
* | `{"type":"string"}` | `String` |
|
|
44
|
+
* | `{"type":"number"}`, `{"type":"integer"}` | `Float`, `Integer` |
|
|
45
|
+
* | `{"type":"array","items":X}` | `Array<X>` |
|
|
46
|
+
* | a closed object with `required` covering every property | `Struct` |
|
|
47
|
+
* | `oneOf` of objects tagged by a constant `type` | `Variant` |
|
|
48
|
+
* | `nullable: true` beside a type, `{"type":["string","null"]}`, or a `oneOf` of null and one other schema | `Option<String>` |
|
|
49
|
+
*
|
|
50
|
+
* The last row reads as an Option because East JSON writes a `none` whose
|
|
51
|
+
* payload cannot itself be null as `null`, so the nulls such a contract
|
|
52
|
+
* permits are exactly what the reader accepts. A type that already admits
|
|
53
|
+
* null — `Null`, or an Option, however the document spells it — is left as
|
|
54
|
+
* it is.
|
|
55
|
+
*
|
|
56
|
+
* Definitions are resolved through `$defs` or `definitions`, whichever the
|
|
57
|
+
* document uses. Cycles among definitions become `RecursiveType`s, one per
|
|
58
|
+
* cycle group: `Node → NodeList → Node`, the ordinary way a recursive schema is
|
|
59
|
+
* written, is the single type `RecursiveType(self => Struct({ children:
|
|
60
|
+
* Array(self) }))` with the alias inlined. A group whose cycles do not all pass
|
|
61
|
+
* through one definition would need two binders, which East does not support,
|
|
62
|
+
* and is refused naming the group.
|
|
63
|
+
*
|
|
64
|
+
* A `$schema` is honoured when present, and a release this cannot read — a
|
|
65
|
+
* draft-04 document, say — is refused by name instead of being structurally
|
|
66
|
+
* guessed at. It is not required: an OpenAPI 3.0 schema object is a fragment of
|
|
67
|
+
* a larger document and carries none, so demanding one would reject what
|
|
68
|
+
* `jsonSchemaFor(T, { draft: "openapi-3.0" })` emits.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* const T = typeFromJsonSchema(JSON.parse(readFileSync("contract.schema.json", "utf-8")));
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function typeFromJsonSchema(schema: JsonSchema): EastType;
|
|
76
|
+
//# sourceMappingURL=json_schema_to_type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json_schema_to_type.d.ts","sourceRoot":"","sources":["../../../src/serialization/json_schema_to_type.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAkBL,KAAK,QAAQ,EAEd,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,UAAU,EAAoC,MAAM,kBAAkB,CAAC;AAErF;;;;;;;GAOG;AACH,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,uEAAuE;IACvE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK7C;AA2ID;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAuB/D"}
|