schemair 0.1.0 → 0.2.0

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.
Files changed (69) hide show
  1. package/README.md +420 -11
  2. package/dist/authoring/index.cjs +13 -350
  3. package/dist/authoring/index.d.cts +2 -90
  4. package/dist/authoring/index.d.ts +2 -90
  5. package/dist/authoring/index.js +2 -304
  6. package/dist/authoring-D3V0iyTe.js +362 -0
  7. package/dist/authoring-Dnrg5TXm.cjs +389 -0
  8. package/dist/chunk-BgLxgFZR.js +18 -0
  9. package/dist/definition/index.cjs +10 -2
  10. package/dist/definition/index.d.cts +3 -21
  11. package/dist/definition/index.d.ts +3 -21
  12. package/dist/definition/index.js +2 -2
  13. package/dist/definition-BLLBpLKv.cjs +1187 -0
  14. package/dist/definition-DmYnDmQO.js +1115 -0
  15. package/dist/index-4aMF0cTE.d.ts +368 -0
  16. package/dist/index-BqfGAU1K.d.ts +56 -0
  17. package/dist/{index-eK2Xgrwp.d.ts → index-CBbd4hXJ.d.ts} +13 -2
  18. package/dist/index-CIim1dG7.d.cts +92 -0
  19. package/dist/{index-TACcK_mi.d.cts → index-CNjYUKvu.d.cts} +13 -2
  20. package/dist/index-CQynt7ft.d.cts +420 -0
  21. package/dist/index-D3mfwaSO.d.cts +56 -0
  22. package/dist/index-DDMwVy2I.d.cts +368 -0
  23. package/dist/index-DM5DSLLL.d.ts +99 -0
  24. package/dist/index-DXWoNYFB.d.ts +92 -0
  25. package/dist/index-DhmHCGpT.d.cts +99 -0
  26. package/dist/index-bQy-C-1l.d.ts +418 -0
  27. package/dist/index.cjs +64 -52
  28. package/dist/index.d.cts +7 -7
  29. package/dist/index.d.ts +7 -7
  30. package/dist/index.js +7 -5
  31. package/dist/integrations/json-schema/index.cjs +328 -0
  32. package/dist/integrations/json-schema/index.d.cts +53 -0
  33. package/dist/integrations/json-schema/index.d.ts +53 -0
  34. package/dist/integrations/json-schema/index.js +324 -0
  35. package/dist/integrations/standard-schema/index.cjs +32 -0
  36. package/dist/integrations/standard-schema/index.d.cts +22 -0
  37. package/dist/integrations/standard-schema/index.d.ts +22 -0
  38. package/dist/integrations/standard-schema/index.js +32 -0
  39. package/dist/payload/index.cjs +1 -1
  40. package/dist/payload/index.d.cts +1 -55
  41. package/dist/payload/index.d.ts +1 -55
  42. package/dist/payload/index.js +1 -1
  43. package/dist/relations/index.cjs +3 -1
  44. package/dist/relations/index.d.cts +2 -2
  45. package/dist/relations/index.d.ts +2 -2
  46. package/dist/relations/index.js +2 -2
  47. package/dist/{relations-CMz_0nf4.cjs → relations-Cymx4iTc.cjs} +158 -5
  48. package/dist/{relations-By0bK3UK.js → relations-ysXDmi-Z.js} +147 -6
  49. package/dist/spec/index.cjs +9 -0
  50. package/dist/spec/index.d.cts +2 -2
  51. package/dist/spec/index.d.ts +2 -2
  52. package/dist/spec/index.js +3 -1
  53. package/dist/standard/index.cjs +810 -0
  54. package/dist/standard/index.d.cts +3 -0
  55. package/dist/standard/index.d.ts +3 -0
  56. package/dist/standard/index.js +777 -0
  57. package/dist/standard-DhKsxu9U.js +471 -0
  58. package/dist/standard-etPFZDJI.cjs +513 -0
  59. package/dist/type-interpreter/index.cjs +3 -3
  60. package/dist/type-interpreter/index.d.cts +2 -99
  61. package/dist/type-interpreter/index.d.ts +2 -99
  62. package/dist/type-interpreter/index.js +2 -2
  63. package/dist/{type-interpreter-Ck0VDhzn.js → type-interpreter-DnrId8aM.js} +5 -284
  64. package/dist/{type-interpreter-DAIBUqKf.cjs → type-interpreter-OLt2W2yd.cjs} +15 -294
  65. package/package.json +38 -3
  66. package/dist/definition-BXj3T94L.js +0 -467
  67. package/dist/definition-DSZZTz4e.cjs +0 -473
  68. package/dist/index-CEzHfht2.d.ts +0 -269
  69. package/dist/index-rzkFjgrt.d.cts +0 -269
@@ -0,0 +1,777 @@
1
+ import { a as STANDARD_CONSTRAINT_PATH_LIST, i as STANDARD_CONSTRAINT_PATHS, n as STANDARD_SEMANTIC_DEFINITIONS, o as STANDARD_SEMANTIC_PATHS, r as STANDARD_SEMANTIC_RELATIONS, s as STANDARD_SEMANTIC_PATH_LIST, t as STANDARD_CONSTRAINT_DEFINITIONS } from "../standard-DhKsxu9U.js";
2
+ import { f as validateSchemaNodeDefinition } from "../definition-DmYnDmQO.js";
3
+
4
+ //#region src/standard/runtime.ts
5
+ function pathKey(path) {
6
+ return path.map((segment) => {
7
+ let key = "";
8
+ for (const character of segment) {
9
+ const code = character.charCodeAt(0);
10
+ key += character.length === 1 && code >= 55296 && code <= 57343 ? `%u${code.toString(16).toUpperCase()}` : encodeURIComponent(character);
11
+ }
12
+ return key;
13
+ }).join("/");
14
+ }
15
+ function definitionMap(definitions) {
16
+ const result = Object.create(null);
17
+ for (const definition of definitions) result[pathKey(definition.path)] = definition;
18
+ return result;
19
+ }
20
+ const STANDARD_SEMANTIC_DEFINITION_MAP = definitionMap(STANDARD_SEMANTIC_DEFINITIONS);
21
+ const STANDARD_CONSTRAINT_DEFINITION_MAP = definitionMap(STANDARD_CONSTRAINT_DEFINITIONS);
22
+ const standardVocabularyRegistry = Object.freeze({
23
+ semanticDefinitions: STANDARD_SEMANTIC_DEFINITION_MAP,
24
+ constraintDefinitions: STANDARD_CONSTRAINT_DEFINITION_MAP
25
+ });
26
+ function isStandardSemanticNamespace(path) {
27
+ return Boolean(path && path.length > 0 && path[0] === "std");
28
+ }
29
+ function isExtensionSemanticPath(path) {
30
+ return Boolean(path && path.length > 0 && path[0] === "ext");
31
+ }
32
+ function classifySemanticPath(path) {
33
+ if (!path || path.length === 0) return void 0;
34
+ const key = pathKey(path);
35
+ const definition = STANDARD_SEMANTIC_DEFINITION_MAP[key];
36
+ if (definition) return {
37
+ path: [...path],
38
+ key,
39
+ resolution: "standard",
40
+ definition
41
+ };
42
+ return {
43
+ path: [...path],
44
+ key,
45
+ resolution: isExtensionSemanticPath(path) ? "extension" : "unresolved"
46
+ };
47
+ }
48
+
49
+ //#endregion
50
+ //#region src/standard/exact-rational.ts
51
+ const DEFAULT_EXACT_RATIONAL_MAX_BITS = 4096;
52
+ function absolute(value) {
53
+ return value < 0n ? -value : value;
54
+ }
55
+ function greatestCommonDivisorInteger(left, right) {
56
+ let a = absolute(left);
57
+ let b = absolute(right);
58
+ while (b !== 0n) {
59
+ const remainder = a % b;
60
+ a = b;
61
+ b = remainder;
62
+ }
63
+ return a;
64
+ }
65
+ function leastCommonMultipleInteger(left, right) {
66
+ if (left === 0n || right === 0n) return 0n;
67
+ return absolute(left / greatestCommonDivisorInteger(left, right) * right);
68
+ }
69
+ function bitLength(value) {
70
+ const magnitude = absolute(value);
71
+ return magnitude === 0n ? 0 : magnitude.toString(2).length;
72
+ }
73
+ function normalizeRational(numerator, denominator, maxBits) {
74
+ if (denominator === 0n) return {
75
+ ok: false,
76
+ reason: "division_by_zero"
77
+ };
78
+ if (numerator === 0n) return {
79
+ ok: true,
80
+ value: {
81
+ numerator: 0n,
82
+ denominator: 1n
83
+ }
84
+ };
85
+ const sign = denominator < 0n ? -1n : 1n;
86
+ const divisor = greatestCommonDivisorInteger(numerator, denominator);
87
+ const reducedNumerator = numerator / divisor * sign;
88
+ const reducedDenominator = absolute(denominator / divisor);
89
+ if (bitLength(reducedNumerator) > maxBits || bitLength(reducedDenominator) > maxBits) return {
90
+ ok: false,
91
+ reason: "max_bits_exceeded"
92
+ };
93
+ return {
94
+ ok: true,
95
+ value: {
96
+ numerator: reducedNumerator,
97
+ denominator: reducedDenominator
98
+ }
99
+ };
100
+ }
101
+ function exactRationalFromFiniteNumber(value, maxBits = DEFAULT_EXACT_RATIONAL_MAX_BITS) {
102
+ if (!Number.isFinite(value)) return {
103
+ ok: false,
104
+ reason: "invalid_number"
105
+ };
106
+ if (Object.is(value, -0) || value === 0) return {
107
+ ok: true,
108
+ value: {
109
+ numerator: 0n,
110
+ denominator: 1n
111
+ }
112
+ };
113
+ const source = String(value);
114
+ const match = /^(-?)(\d+)(?:\.(\d+))?(?:e([+-]?\d+))?$/i.exec(source);
115
+ if (!match) return {
116
+ ok: false,
117
+ reason: "invalid_number"
118
+ };
119
+ const sign = match[1] === "-" ? -1n : 1n;
120
+ const integerDigits = match[2] ?? "";
121
+ const fractionDigits = match[3] ?? "";
122
+ const exponent = Number(match[4] ?? 0);
123
+ const digits = BigInt(`${integerDigits}${fractionDigits}`);
124
+ const decimalScale = fractionDigits.length - exponent;
125
+ if (decimalScale <= 0) return normalizeRational(sign * digits * 10n ** BigInt(-decimalScale), 1n, maxBits);
126
+ return normalizeRational(sign * digits, 10n ** BigInt(decimalScale), maxBits);
127
+ }
128
+ function exactRationalIsIntegerMultiple(value, divisor, maxBits = DEFAULT_EXACT_RATIONAL_MAX_BITS) {
129
+ if (divisor.numerator === 0n) return {
130
+ ok: false,
131
+ reason: "division_by_zero"
132
+ };
133
+ const quotient = normalizeRational(value.numerator * divisor.denominator, value.denominator * divisor.numerator, maxBits);
134
+ if (!quotient.ok) return quotient;
135
+ return {
136
+ ok: true,
137
+ value: quotient.value.numerator % quotient.value.denominator === 0n
138
+ };
139
+ }
140
+ function greatestCommonDivisorRationals(values, maxBits = DEFAULT_EXACT_RATIONAL_MAX_BITS) {
141
+ if (values.length === 0 || values.some((value) => value.numerator === 0n)) return {
142
+ ok: false,
143
+ reason: "division_by_zero"
144
+ };
145
+ let commonDenominator = 1n;
146
+ for (const value of values) {
147
+ commonDenominator = leastCommonMultipleInteger(commonDenominator, value.denominator);
148
+ if (bitLength(commonDenominator) > maxBits) return {
149
+ ok: false,
150
+ reason: "max_bits_exceeded"
151
+ };
152
+ }
153
+ let commonNumerator;
154
+ for (const value of values) {
155
+ const scaled = absolute(value.numerator) * (commonDenominator / value.denominator);
156
+ commonNumerator = commonNumerator === void 0 ? scaled : greatestCommonDivisorInteger(commonNumerator, scaled);
157
+ }
158
+ return normalizeRational(commonNumerator ?? 0n, commonDenominator, maxBits);
159
+ }
160
+ function leastCommonMultipleRationals(values, maxBits = DEFAULT_EXACT_RATIONAL_MAX_BITS) {
161
+ if (values.length === 0 || values.some((value) => value.numerator === 0n)) return {
162
+ ok: false,
163
+ reason: "division_by_zero"
164
+ };
165
+ let result = {
166
+ numerator: absolute(values[0].numerator),
167
+ denominator: values[0].denominator
168
+ };
169
+ for (let index = 1; index < values.length; index += 1) {
170
+ const value = values[index];
171
+ const divisor = greatestCommonDivisorRationals([result, value], maxBits);
172
+ if (!divisor.ok) return divisor;
173
+ const multiplied = normalizeRational(result.numerator * absolute(value.numerator), result.denominator * value.denominator, maxBits);
174
+ if (!multiplied.ok) return multiplied;
175
+ const joined = normalizeRational(multiplied.value.numerator * divisor.value.denominator, multiplied.value.denominator * absolute(divisor.value.numerator), maxBits);
176
+ if (!joined.ok) return joined;
177
+ result = joined.value;
178
+ }
179
+ return {
180
+ ok: true,
181
+ value: result
182
+ };
183
+ }
184
+ function formatExactRational(value) {
185
+ return value.denominator === 1n ? String(value.numerator) : `${value.numerator}/${value.denominator}`;
186
+ }
187
+
188
+ //#endregion
189
+ //#region src/standard/constraint-profile.ts
190
+ const sameSegmentPath$1 = (a, b) => a.length === b.length && a.every((segment, index) => segment === b[index]);
191
+ function isStandardConstraintOwner(node) {
192
+ return node.kind === "primitive" && (node.name === "string" || node.name === "number") || node.kind === "array" || node.kind === "record";
193
+ }
194
+ function strongerLower(current, candidate) {
195
+ if (!current || candidate.value > current.value) return candidate;
196
+ if (candidate.value < current.value) return current;
197
+ return current.inclusive && !candidate.inclusive ? candidate : current;
198
+ }
199
+ function strongerUpper(current, candidate) {
200
+ if (!current || candidate.value < current.value) return candidate;
201
+ if (candidate.value > current.value) return current;
202
+ return current.inclusive && !candidate.inclusive ? candidate : current;
203
+ }
204
+ function nextUp(value) {
205
+ if (value === 0) return Number.MIN_VALUE;
206
+ const view = /* @__PURE__ */ new DataView(/* @__PURE__ */ new ArrayBuffer(8));
207
+ view.setFloat64(0, value);
208
+ const bits = view.getBigUint64(0);
209
+ view.setBigUint64(0, value > 0 ? bits + 1n : bits - 1n);
210
+ return view.getFloat64(0);
211
+ }
212
+ function intervalIsEmpty(interval) {
213
+ const { lower, upper } = interval;
214
+ if (interval.domain === "continuous") {
215
+ const first = !lower ? -Number.MAX_VALUE : lower.inclusive ? lower.value : nextUp(lower.value);
216
+ const last = !upper ? Number.MAX_VALUE : upper.inclusive ? upper.value : -nextUp(-upper.value);
217
+ return !Number.isFinite(first) || !Number.isFinite(last) || first > last;
218
+ }
219
+ if (!lower || !upper) return false;
220
+ if (lower.value > upper.value) return true;
221
+ if (lower.value === upper.value) return !lower.inclusive || !upper.inclusive;
222
+ return (lower.inclusive ? Math.ceil(lower.value) : Math.floor(lower.value) + 1) > (upper.inclusive ? Math.floor(upper.value) : Math.ceil(upper.value) - 1);
223
+ }
224
+ function intervalContainsZero(interval) {
225
+ const lowerAccepts = !interval.lower || interval.lower.value < 0 || interval.lower.value === 0 && interval.lower.inclusive;
226
+ const upperAccepts = !interval.upper || interval.upper.value > 0 || interval.upper.value === 0 && interval.upper.inclusive;
227
+ return lowerAccepts && upperAccepts;
228
+ }
229
+ function isConstraint(constraint, path) {
230
+ return sameSegmentPath$1(constraint.constraintPath, path);
231
+ }
232
+ function buildStandardConstraintProfile(node, options = {}) {
233
+ const constraints = node.constraints ?? [];
234
+ const multipleOf = [];
235
+ const patterns = [];
236
+ const unhandled = [];
237
+ const invalid = [];
238
+ let budgetExceeded = false;
239
+ let uniqueItems;
240
+ let domain;
241
+ let lower;
242
+ let upper;
243
+ if (node.kind === "primitive" && node.name === "number") domain = "continuous";
244
+ else {
245
+ domain = "integer";
246
+ lower = {
247
+ value: 0,
248
+ inclusive: true
249
+ };
250
+ if (node.kind === "record") {
251
+ lower = {
252
+ value: node.fields.filter((field) => field.required === true).length,
253
+ inclusive: true
254
+ };
255
+ if (node.additionalFields === void 0) upper = {
256
+ value: node.fields.length,
257
+ inclusive: true
258
+ };
259
+ }
260
+ }
261
+ for (const constraint of constraints) {
262
+ if (node.kind === "primitive" && node.name === "number" && isConstraint(constraint, STANDARD_CONSTRAINT_PATHS.number.multipleOf)) {
263
+ if (typeof constraint.args !== "number" || !Number.isFinite(constraint.args) || constraint.args <= 0) {
264
+ invalid.push(constraint);
265
+ continue;
266
+ }
267
+ const rational = exactRationalFromFiniteNumber(constraint.args, options.maxRationalBits ?? DEFAULT_EXACT_RATIONAL_MAX_BITS);
268
+ if (!rational.ok) if (rational.reason === "max_bits_exceeded") budgetExceeded = true;
269
+ else invalid.push(constraint);
270
+ else multipleOf.push(rational.value);
271
+ continue;
272
+ }
273
+ if (node.kind === "primitive" && node.name === "string" && isConstraint(constraint, STANDARD_CONSTRAINT_PATHS.string.pattern)) {
274
+ if (typeof constraint.args !== "string") invalid.push(constraint);
275
+ else try {
276
+ new RegExp(constraint.args);
277
+ patterns.push(constraint.args);
278
+ } catch {
279
+ invalid.push(constraint);
280
+ }
281
+ continue;
282
+ }
283
+ if (node.kind === "array" && isConstraint(constraint, STANDARD_CONSTRAINT_PATHS.array.uniqueItems)) {
284
+ if (typeof constraint.args !== "boolean") invalid.push(constraint);
285
+ else if (constraint.args) uniqueItems = true;
286
+ continue;
287
+ }
288
+ const definition = STANDARD_CONSTRAINT_DEFINITION_MAP[pathKey(constraint.constraintPath)];
289
+ const target = node.kind === "primitive" ? node.name : node.kind;
290
+ if (definition && (definition.target !== target || typeof constraint.args !== definition.argsType || definition.argsDomain === "nonNegativeInteger" && (typeof constraint.args !== "number" || !Number.isSafeInteger(constraint.args) || constraint.args < 0))) {
291
+ invalid.push(constraint);
292
+ continue;
293
+ }
294
+ if (typeof constraint.args !== "number" || !Number.isFinite(constraint.args)) {
295
+ unhandled.push(constraint);
296
+ continue;
297
+ }
298
+ let nextLower;
299
+ let nextUpper;
300
+ if (node.kind === "primitive" && node.name === "number") {
301
+ if (isConstraint(constraint, STANDARD_CONSTRAINT_PATHS.number.minimum)) nextLower = {
302
+ value: constraint.args,
303
+ inclusive: true
304
+ };
305
+ else if (isConstraint(constraint, STANDARD_CONSTRAINT_PATHS.number.exclusiveMinimum)) nextLower = {
306
+ value: constraint.args,
307
+ inclusive: false
308
+ };
309
+ else if (isConstraint(constraint, STANDARD_CONSTRAINT_PATHS.number.maximum)) nextUpper = {
310
+ value: constraint.args,
311
+ inclusive: true
312
+ };
313
+ else if (isConstraint(constraint, STANDARD_CONSTRAINT_PATHS.number.exclusiveMaximum)) nextUpper = {
314
+ value: constraint.args,
315
+ inclusive: false
316
+ };
317
+ } else {
318
+ const lowerPath = node.kind === "array" ? STANDARD_CONSTRAINT_PATHS.array.minItems : node.kind === "record" ? STANDARD_CONSTRAINT_PATHS.record.minProperties : STANDARD_CONSTRAINT_PATHS.string.minLength;
319
+ const upperPath = node.kind === "array" ? STANDARD_CONSTRAINT_PATHS.array.maxItems : node.kind === "record" ? STANDARD_CONSTRAINT_PATHS.record.maxProperties : STANDARD_CONSTRAINT_PATHS.string.maxLength;
320
+ if (isConstraint(constraint, lowerPath)) nextLower = {
321
+ value: constraint.args,
322
+ inclusive: true
323
+ };
324
+ else if (isConstraint(constraint, upperPath)) nextUpper = {
325
+ value: constraint.args,
326
+ inclusive: true
327
+ };
328
+ }
329
+ if (nextLower || nextUpper) {
330
+ if (domain === "integer" && (!Number.isSafeInteger(constraint.args) || constraint.args < 0)) {
331
+ invalid.push(constraint);
332
+ continue;
333
+ }
334
+ if (nextLower) lower = strongerLower(lower, nextLower);
335
+ if (nextUpper) upper = strongerUpper(upper, nextUpper);
336
+ } else unhandled.push(constraint);
337
+ }
338
+ const interval = {
339
+ domain,
340
+ ...lower === void 0 ? {} : { lower },
341
+ ...upper === void 0 ? {} : { upper }
342
+ };
343
+ let satisfiability;
344
+ if (intervalIsEmpty(interval)) satisfiability = "empty";
345
+ else if (invalid.length > 0 || budgetExceeded || unhandled.length > 0 || patterns.length > 0) satisfiability = "unknown";
346
+ else if (multipleOf.length > 0 && !intervalContainsZero(interval)) satisfiability = "unknown";
347
+ else satisfiability = "satisfiable";
348
+ return {
349
+ interval,
350
+ multipleOf,
351
+ ...uniqueItems === void 0 ? {} : { uniqueItems },
352
+ patterns,
353
+ unhandled,
354
+ invalid,
355
+ budgetExceeded,
356
+ satisfiability
357
+ };
358
+ }
359
+
360
+ //#endregion
361
+ //#region src/standard/payload.ts
362
+ function isIPv4(value) {
363
+ if (typeof value !== "string") return false;
364
+ const parts = value.split(".");
365
+ return parts.length === 4 && parts.every((part) => {
366
+ if (!/^\d{1,3}$/.test(part)) return false;
367
+ if (part.length > 1 && part[0] === "0") return false;
368
+ return Number(part) <= 255;
369
+ });
370
+ }
371
+ function isIPv6(value) {
372
+ if (typeof value !== "string" || value.length === 0) return false;
373
+ const halves = value.split("::");
374
+ if (halves.length > 2) return false;
375
+ const parsePart = (part) => {
376
+ if (part.length === 0) return 0;
377
+ const pieces = part.split(":");
378
+ let count = 0;
379
+ for (const [index, piece] of pieces.entries()) if (piece.includes(".")) {
380
+ if (index !== pieces.length - 1 || !isIPv4(piece)) return -1;
381
+ count += 2;
382
+ } else {
383
+ if (!/^[0-9a-f]{1,4}$/i.test(piece)) return -1;
384
+ count += 1;
385
+ }
386
+ return count;
387
+ };
388
+ const left = parsePart(halves[0]);
389
+ const right = halves.length === 2 ? parsePart(halves[1]) : 0;
390
+ if (left < 0 || right < 0) return false;
391
+ return halves.length === 2 ? left + right < 8 : left === 8;
392
+ }
393
+ /** These predicates are a TypeScript host policy, not universal protocol predicates. */
394
+ const predicates = {
395
+ "std/string/date": (value) => {
396
+ if (typeof value !== "string") return false;
397
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
398
+ if (!m) return false;
399
+ const year = Number(m[1]), month = Number(m[2]), day = Number(m[3]);
400
+ const days = month === 2 ? year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28 : [
401
+ 4,
402
+ 6,
403
+ 9,
404
+ 11
405
+ ].includes(month) ? 30 : 31;
406
+ return month >= 1 && month <= 12 && day >= 1 && day <= days;
407
+ },
408
+ "std/string/datetime": (value) => typeof value === "string" && Number.isFinite(Date.parse(value)),
409
+ "std/string/datetime/iso": (value) => typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})?$/.test(value) && predicates["std/string/date"](value.slice(0, 10)) && Number(value.slice(11, 13)) < 24 && Number(value.slice(14, 16)) < 60 && Number.isFinite(Date.parse(value)),
410
+ "std/string/email": (value) => typeof value === "string" && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
411
+ "std/string/url": (value) => typeof value === "string" && /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/i.test(value),
412
+ "std/string/ip/v4": isIPv4,
413
+ "std/string/ip/v6": isIPv6,
414
+ "std/string/uuid": (value) => typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value),
415
+ "std/string/uuid/v4": (value) => typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value),
416
+ "std/string/json": (value) => {
417
+ if (typeof value !== "string") return false;
418
+ try {
419
+ JSON.parse(value);
420
+ return true;
421
+ } catch {
422
+ return false;
423
+ }
424
+ },
425
+ "std/string/base64": (value) => typeof value === "string" && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value),
426
+ "std/string/base64url": (value) => typeof value === "string" && /^[A-Za-z0-9_-]+$/.test(value),
427
+ "std/string/hex": (value) => typeof value === "string" && /^[0-9a-f]+$/i.test(value),
428
+ "std/string/decimal": (value) => typeof value === "string" && /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?$/.test(value),
429
+ "std/string/bigint": (value) => typeof value === "string" && /^(?:0|-[1-9][0-9]*|[1-9][0-9]*)$/.test(value),
430
+ "std/number/integer": (value) => typeof value === "number" && Number.isFinite(value) && Number.isInteger(value),
431
+ "std/number/safeInteger": (value) => typeof value === "number" && Number.isSafeInteger(value),
432
+ "std/number/epochMillis": (value) => typeof value === "number" && Number.isFinite(value) && Number.isInteger(value),
433
+ "std/number/epochSeconds": (value) => typeof value === "number" && Number.isFinite(value) && Number.isInteger(value)
434
+ };
435
+ const unknown = (message) => ({
436
+ status: "unknown",
437
+ message
438
+ });
439
+ const standardSemanticProvider = (path, value, context) => {
440
+ const key = pathKey(path), definition = STANDARD_SEMANTIC_DEFINITION_MAP[key];
441
+ if (!definition) return unknown("Unknown semantic path; supply a host provider");
442
+ if (context.schema.kind !== "primitive" || context.schema.name !== definition.primitive || typeof value !== definition.primitive) return false;
443
+ if (definition.role === "annotation") return true;
444
+ return predicates[key]?.(value) ?? unknown("No standard semantic predicate");
445
+ };
446
+ /** Canonical JSON equality ignores object property order and treats -0 as 0. */
447
+ function valueKey(value, active = /* @__PURE__ */ new Set()) {
448
+ if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value);
449
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : void 0;
450
+ if (typeof value !== "object" || active.has(value)) return void 0;
451
+ if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return void 0;
452
+ active.add(value);
453
+ const keys = Array.isArray(value) ? Array.from({ length: value.length }, (_, i) => String(i)) : Object.keys(value).sort();
454
+ const parts = [];
455
+ for (const key of keys) {
456
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
457
+ if (!descriptor || !("value" in descriptor)) {
458
+ active.delete(value);
459
+ return;
460
+ }
461
+ const part = valueKey(descriptor.value, active);
462
+ if (part === void 0) {
463
+ active.delete(value);
464
+ return;
465
+ }
466
+ parts.push(Array.isArray(value) ? part : `${JSON.stringify(key)}:${part}`);
467
+ }
468
+ active.delete(value);
469
+ return Array.isArray(value) ? `[${parts.join(",")}]` : `{${parts.join(",")}}`;
470
+ }
471
+ function standardConstraintTarget(node) {
472
+ return node.kind === "primitive" ? node.name : node.kind;
473
+ }
474
+ const standardConstraintProvider = (path, args, value, context) => {
475
+ const definition = STANDARD_CONSTRAINT_DEFINITION_MAP[pathKey(path)];
476
+ if (!definition) return unknown("Unknown constraint path; supply a host provider");
477
+ if (standardConstraintTarget(context.schema) !== definition.target || typeof args !== definition.argsType) return false;
478
+ if (typeof args === "number" && (!Number.isFinite(args) || definition.argsDomain === "nonNegativeInteger" && (!Number.isSafeInteger(args) || args < 0) || definition.argsDomain === "positiveNumber" && args <= 0)) return false;
479
+ const name = definition.path[1];
480
+ if (name === "pattern") {
481
+ if (typeof value !== "string" || typeof args !== "string") return false;
482
+ try {
483
+ return new RegExp(args).test(value);
484
+ } catch {
485
+ return unknown("Pattern is unsupported by the ECMAScript regex engine");
486
+ }
487
+ }
488
+ if (name === "uniqueItems") {
489
+ if (!Array.isArray(value)) return false;
490
+ if (args === false) return true;
491
+ const keys = value.map((item) => valueKey(item));
492
+ if (keys.some((key) => key === void 0)) return unknown("uniqueItems requires finite JSON values");
493
+ return new Set(keys).size === keys.length;
494
+ }
495
+ if (typeof args !== "number") return false;
496
+ if (definition.target === "number") {
497
+ if (typeof value !== "number" || !Number.isFinite(value)) return false;
498
+ switch (name) {
499
+ case "minimum": return value >= args;
500
+ case "maximum": return value <= args;
501
+ case "exclusiveMinimum": return value > args;
502
+ case "exclusiveMaximum": return value < args;
503
+ case "multipleOf": {
504
+ const v = exactRationalFromFiniteNumber(value), d = exactRationalFromFiniteNumber(args);
505
+ if (!v.ok || !d.ok) return unknown("Exact rational budget exceeded");
506
+ const result = exactRationalIsIntegerMultiple(v.value, d.value);
507
+ return result.ok ? result.value : unknown("Exact rational budget exceeded");
508
+ }
509
+ }
510
+ }
511
+ const size = definition.target === "string" && typeof value === "string" ? [...value].length : definition.target === "array" && Array.isArray(value) ? value.length : definition.target === "record" && value !== null && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).length : void 0;
512
+ if (size === void 0) return false;
513
+ return name?.startsWith("min") ? size >= args : size <= args;
514
+ };
515
+ function providerMap(definitions, provider) {
516
+ const result = Object.create(null);
517
+ for (const definition of definitions) result[pathKey(definition.path)] = provider;
518
+ return Object.freeze(result);
519
+ }
520
+ const standardSemanticRegistry = providerMap(STANDARD_SEMANTIC_DEFINITIONS, standardSemanticProvider);
521
+ const standardConstraintRegistry = providerMap(STANDARD_CONSTRAINT_DEFINITIONS, standardConstraintProvider);
522
+ /** Opt in explicitly; core validation never silently installs vocabulary policy. */
523
+ const standardPayloadContext = Object.freeze({
524
+ semanticProvider: standardSemanticProvider,
525
+ constraintProvider: standardConstraintProvider
526
+ });
527
+
528
+ //#endregion
529
+ //#region src/standard/operations.ts
530
+ function standardSchemaSatisfiability(node) {
531
+ if (!validateSchemaNodeDefinition(node).ok || !isStandardConstraintOwner(node)) return "unknown";
532
+ const profile = buildStandardConstraintProfile(node);
533
+ if (profile.invalid.length || profile.budgetExceeded || profile.unhandled.length) return "unknown";
534
+ if (profile.satisfiability === "empty") return "emptySet";
535
+ if (node.kind === "primitive" && node.semanticPath) return "unknown";
536
+ if (node.kind === "record" || node.kind === "array") return "unknown";
537
+ return profile.satisfiability === "satisfiable" ? "inhabited" : "unknown";
538
+ }
539
+ function refineStandardSchema(node, addConstraints) {
540
+ if (!validateSchemaNodeDefinition(node).ok || !isStandardConstraintOwner(node)) return {
541
+ status: "unsupported",
542
+ message: "Expected a valid constraint-bearing schema"
543
+ };
544
+ const schema = {
545
+ ...node,
546
+ constraints: [...node.constraints ?? [], ...addConstraints]
547
+ };
548
+ if (!validateSchemaNodeDefinition(schema).ok) return {
549
+ status: "unsupported",
550
+ message: "Invalid constraint data"
551
+ };
552
+ const profile = buildStandardConstraintProfile(schema);
553
+ if (profile.invalid.length || profile.budgetExceeded || profile.unhandled.length) return {
554
+ status: "unknown",
555
+ message: "Unsupported or invalid constraint profile"
556
+ };
557
+ if (profile.satisfiability === "empty") return { status: "emptySet" };
558
+ return {
559
+ status: "resolved",
560
+ schema
561
+ };
562
+ }
563
+ function intersectStandardSchemas(left, right) {
564
+ if (!validateSchemaNodeDefinition(left).ok || !validateSchemaNodeDefinition(right).ok || left.kind !== "primitive" || right.kind !== "primitive" || left.name !== right.name || !isStandardConstraintOwner(left) || !isStandardConstraintOwner(right)) return {
565
+ status: "unsupported",
566
+ message: "Standard intersection supports string/number primitives"
567
+ };
568
+ if (left.semanticPath && right.semanticPath && JSON.stringify(left.semanticPath) !== JSON.stringify(right.semanticPath)) return {
569
+ status: "unknown",
570
+ message: "Semantic intersection cannot be proved"
571
+ };
572
+ return refineStandardSchema({
573
+ ...left,
574
+ ...right.semanticPath ? { semanticPath: [...right.semanticPath] } : {}
575
+ }, right.constraints ?? []);
576
+ }
577
+
578
+ //#endregion
579
+ //#region src/standard/relations.ts
580
+ const sameSegmentPath = (a, b) => a.length === b.length && a.every((segment, index) => segment === b[index]);
581
+ const issue = (code, message, path, details) => ({
582
+ status: code === "incompatible_schema" ? "incompatible" : "unknown",
583
+ issues: [{
584
+ code,
585
+ message,
586
+ path,
587
+ ...details === void 0 ? {} : { details }
588
+ }]
589
+ });
590
+ const ok = () => ({ status: "assignable" });
591
+ const refKey = (path) => JSON.stringify(path);
592
+ const pathEquals = (left, right) => refKey(left) === refKey(right);
593
+ function primitiveType(value) {
594
+ return typeof value;
595
+ }
596
+ function semanticRelation(source, target, path, context) {
597
+ if (source.kind !== "primitive" && source.kind !== "literal" || target.kind !== "primitive") return ok();
598
+ const sourceNameKind = source.kind === "literal" ? primitiveType(source.literal) : source.name;
599
+ if (sourceNameKind !== "string" && sourceNameKind !== "number" || sourceNameKind !== target.name) return ok();
600
+ const sourcePath = "semanticPath" in source && source.semanticPath?.length ? source.semanticPath : void 0;
601
+ const targetPath = target.semanticPath?.length ? target.semanticPath : void 0;
602
+ if (!targetPath) {
603
+ if (source.kind === "literal") return ok();
604
+ return (context.semanticIdentityPolicy ?? "ignore") === "ignore" ? ok() : issue("incompatible_schema", "Semantic identity is missing from the target schema", path);
605
+ }
606
+ if ((context.semanticIdentityPolicy ?? "ignore") !== "ignore") {
607
+ if (!sourcePath) return issue("incompatible_schema", "Semantic identity is missing from the source schema", path);
608
+ if (!(context.semanticIdentityPolicy === "exact" ? pathEquals(sourcePath, targetPath) : sourcePath.length >= targetPath.length && targetPath.every((segment, index) => sourcePath[index] === segment))) return issue("incompatible_schema", "Semantic identity is not assignable to the target identity", path);
609
+ }
610
+ if (!classifySemanticPath(targetPath)?.definition || sourcePath && !classifySemanticPath(sourcePath)?.definition) return issue("semantic_relation_unknown", "Unknown semantic path requires a host provider", path);
611
+ if (sourcePath && pathEquals(sourcePath, targetPath)) return ok();
612
+ const targetDefinition = classifySemanticPath(targetPath);
613
+ if (targetDefinition?.definition?.role === "annotation") return ok();
614
+ if (source.kind === "literal" && targetDefinition?.definition?.role === "validation") {
615
+ const validated = standardSemanticProvider(targetPath, source.literal, {
616
+ schema: target,
617
+ rootSchema: target,
618
+ path
619
+ });
620
+ return validated === true ? ok() : validated === false ? issue("incompatible_schema", "Literal does not satisfy target validation semantic", path) : issue("semantic_relation_unknown", "Semantic predicate is unknown", path);
621
+ }
622
+ const sourceDefinition = sourcePath ? classifySemanticPath(sourcePath) : void 0;
623
+ const sourceName = sourcePath?.join("/");
624
+ const targetName = targetPath.join("/");
625
+ if (STANDARD_SEMANTIC_RELATIONS.some((relation) => relation.kind === "acceptedSetSubset" && relation.source.join("/") === sourceName && relation.target.join("/") === targetName)) {
626
+ if ((context.semanticIdentityPolicy ?? "ignore") === "exact" && JSON.stringify(sourcePath) !== JSON.stringify(targetPath)) return issue("incompatible_schema", "Semantic identity is not exact", path);
627
+ return ok();
628
+ }
629
+ if (targetDefinition?.resolution === "extension") return issue("semantic_relation_unknown", "Extension vocabulary requires a provider", path);
630
+ if (sourceDefinition?.definition?.role === "validation" && targetDefinition?.definition?.role === "validation") return issue("semantic_relation_unknown", "Semantic validation relation is not proven", path, {
631
+ relation: "accepted_set",
632
+ sourceSemanticPath: sourcePath ?? null,
633
+ targetSemanticPath: targetPath
634
+ });
635
+ return issue("semantic_relation_unknown", "Accepted-set semantic implication is not proven", path);
636
+ }
637
+ function constraintsOf(node) {
638
+ return "constraints" in node ? node.constraints ?? [] : [];
639
+ }
640
+ function lowerImplies(source, target) {
641
+ if (!target) return true;
642
+ if (!source) return false;
643
+ return source.value > target.value || source.value === target.value && (target.inclusive || !source.inclusive);
644
+ }
645
+ function upperImplies(source, target) {
646
+ if (!target) return true;
647
+ if (!source) return false;
648
+ return source.value < target.value || source.value === target.value && (target.inclusive || !source.inclusive);
649
+ }
650
+ function exactConstraintIncluded(source, target) {
651
+ return source.some((candidate) => sameSegmentPath(candidate.constraintPath, target.constraintPath) && JSON.stringify(candidate.args) === JSON.stringify(target.args));
652
+ }
653
+ function constraintOwner(node) {
654
+ return node.kind === "primitive" && (node.name === "string" || node.name === "number") || node.kind === "array" || node.kind === "record" ? node : void 0;
655
+ }
656
+ function literalProfile(source, target) {
657
+ if (source.kind !== "literal") return void 0;
658
+ if (target.kind === "primitive" && target.name === "number" && typeof source.literal === "number") return {
659
+ interval: {
660
+ domain: "continuous",
661
+ lower: {
662
+ value: source.literal,
663
+ inclusive: true
664
+ },
665
+ upper: {
666
+ value: source.literal,
667
+ inclusive: true
668
+ }
669
+ },
670
+ multipleOf: [],
671
+ patterns: [],
672
+ unhandled: [],
673
+ invalid: [],
674
+ budgetExceeded: false,
675
+ satisfiability: "satisfiable"
676
+ };
677
+ if (target.kind === "primitive" && target.name === "string" && typeof source.literal === "string") {
678
+ const length = [...source.literal].length;
679
+ return {
680
+ interval: {
681
+ domain: "integer",
682
+ lower: {
683
+ value: length,
684
+ inclusive: true
685
+ },
686
+ upper: {
687
+ value: length,
688
+ inclusive: true
689
+ }
690
+ },
691
+ multipleOf: [],
692
+ patterns: [],
693
+ unhandled: [],
694
+ invalid: [],
695
+ budgetExceeded: false,
696
+ satisfiability: "satisfiable"
697
+ };
698
+ }
699
+ }
700
+ function multipleOfImplies(source, target) {
701
+ if (target.length === 0) return true;
702
+ if (source.length === 0) return false;
703
+ const joined = leastCommonMultipleRationals(source);
704
+ return joined.ok && target.every((value) => {
705
+ const relation = exactRationalIsIntegerMultiple(joined.value, value);
706
+ return relation.ok && relation.value;
707
+ });
708
+ }
709
+ function constraintRelation(source, target, path, context) {
710
+ const targetOwner = constraintOwner(target);
711
+ if (constraintsOf(target).length === 0) return ok();
712
+ if (!targetOwner) return issue("constraint_relation_unknown", "Target cannot carry these constraints", path);
713
+ if (constraintsOf(target).find((constraint) => constraint.constraintPath[0] === "ext")) return issue("constraint_relation_unknown", "Extension vocabulary requires a provider", path);
714
+ const sourceOwner = constraintOwner(source);
715
+ const sourceProfile = literalProfile(source, targetOwner) ?? (sourceOwner ? buildStandardConstraintProfile(sourceOwner) : void 0);
716
+ const targetProfile = buildStandardConstraintProfile(targetOwner);
717
+ if (!sourceProfile || sourceProfile.invalid.length > 0 || sourceProfile.budgetExceeded || targetProfile.invalid.length > 0 || targetProfile.budgetExceeded) return issue("constraint_relation_unknown", "Constraint relation cannot be proven for an invalid or unsupported profile", path);
718
+ if (sourceProfile.unhandled.length || targetProfile.unhandled.length) return issue("constraint_relation_unknown", "Unknown constraint path requires a host provider", path);
719
+ if (sourceProfile.satisfiability === "empty") return ok();
720
+ if (targetProfile.satisfiability === "empty") return issue("constraint_relation_unknown", "Source satisfiability is not established", path);
721
+ if (targetProfile.multipleOf.length > 0) {
722
+ const literal = source.kind === "literal" && typeof source.literal === "number" ? exactRationalFromFiniteNumber(source.literal) : void 0;
723
+ if (!(literal?.ok === true && targetProfile.multipleOf.every((value) => {
724
+ const relation = exactRationalIsIntegerMultiple(literal.value, value);
725
+ return relation.ok && relation.value;
726
+ })) && !multipleOfImplies(sourceProfile.multipleOf, targetProfile.multipleOf)) return issue("constraint_relation_unknown", "multipleOf relation cannot be proven", path);
727
+ }
728
+ if (targetProfile.uniqueItems === true && sourceProfile.uniqueItems !== true) return issue("constraint_relation_unknown", "uniqueItems relation cannot be proven", path);
729
+ if (targetProfile.patterns.length > 0) {
730
+ if (source.kind === "literal" && typeof source.literal === "string") for (const pattern of targetProfile.patterns) try {
731
+ if (!new RegExp(pattern).test(source.literal)) return issue("incompatible_schema", "String literal does not satisfy target pattern", path);
732
+ } catch {
733
+ return issue("constraint_relation_unknown", "Pattern relation cannot be proven", path);
734
+ }
735
+ else if (!targetProfile.patterns.every((pattern) => constraintsOf(source).some((constraint) => pathEquals(constraint.constraintPath, STANDARD_CONSTRAINT_PATHS.string.pattern) && constraint.args === pattern))) return issue("constraint_relation_unknown", "Pattern relation cannot be proven for a non-literal source", path);
736
+ }
737
+ for (const targetConstraint of targetProfile.unhandled) {
738
+ if (target.kind === "primitive" && target.name === "string" && pathEquals(targetConstraint.constraintPath, STANDARD_CONSTRAINT_PATHS.string.pattern) && source.kind === "literal" && typeof source.literal === "string") {
739
+ try {
740
+ if (!new RegExp(String(targetConstraint.args)).test(source.literal)) return issue("incompatible_schema", "String literal does not satisfy target pattern", path);
741
+ } catch {
742
+ return issue("constraint_relation_unknown", "Pattern relation cannot be proven", path);
743
+ }
744
+ continue;
745
+ }
746
+ if (!exactConstraintIncluded(constraintsOf(source), targetConstraint)) return issue("constraint_relation_unknown", "No implication handler is available for target constraint", path, { constraintPath: [...targetConstraint.constraintPath] });
747
+ }
748
+ if (!targetProfile.interval || !sourceProfile.interval || sourceProfile.interval.domain !== targetProfile.interval.domain) return issue("constraint_relation_unknown", "Constraint interval domains cannot be compared", path);
749
+ if (lowerImplies(sourceProfile.interval.lower, targetProfile.interval.lower) && upperImplies(sourceProfile.interval.upper, targetProfile.interval.upper)) return ok();
750
+ if (sourceProfile.unhandled.length > 0) return issue("constraint_relation_unknown", "Unsupported source constraints may further narrow the accepted-value set", path);
751
+ return issue("constraint_relation_unknown", "Interval implication is not proven", path);
752
+ }
753
+ function decision(result) {
754
+ const message = result.issues?.[0]?.message;
755
+ return {
756
+ status: result.status,
757
+ ...message ? { message } : {}
758
+ };
759
+ }
760
+ /** Accepted-set policy; unknown implication is never treated as compatibility. */
761
+ function createStandardRelationContext(options = {}) {
762
+ return {
763
+ semanticProvider: (_sourcePath, _targetPath, context) => decision(semanticRelation(context.sourceSchema, context.targetSchema, [], options)),
764
+ constraintProvider: (_sourceConstraints, _targetConstraints, context) => decision(constraintRelation(context.sourceSchema, context.targetSchema, [], options))
765
+ };
766
+ }
767
+ const standardRelationContext = Object.freeze(createStandardRelationContext());
768
+ const standardVocabularyProvider = Object.freeze({
769
+ payload: standardPayloadContext,
770
+ relation: standardRelationContext,
771
+ refine: refineStandardSchema,
772
+ intersect: intersectStandardSchemas,
773
+ satisfiability: standardSchemaSatisfiability
774
+ });
775
+
776
+ //#endregion
777
+ export { DEFAULT_EXACT_RATIONAL_MAX_BITS, STANDARD_CONSTRAINT_DEFINITIONS, STANDARD_CONSTRAINT_DEFINITION_MAP, STANDARD_CONSTRAINT_PATHS, STANDARD_CONSTRAINT_PATH_LIST, STANDARD_SEMANTIC_DEFINITIONS, STANDARD_SEMANTIC_DEFINITION_MAP, STANDARD_SEMANTIC_PATHS, STANDARD_SEMANTIC_PATH_LIST, STANDARD_SEMANTIC_RELATIONS, buildStandardConstraintProfile, classifySemanticPath, createStandardRelationContext, exactRationalFromFiniteNumber, exactRationalIsIntegerMultiple, formatExactRational, greatestCommonDivisorRationals, intersectStandardSchemas, isExtensionSemanticPath, isStandardConstraintOwner, isStandardSemanticNamespace, leastCommonMultipleRationals, pathKey, refineStandardSchema, standardConstraintProvider, standardConstraintRegistry, standardConstraintTarget, standardPayloadContext, standardRelationContext, standardSchemaSatisfiability, standardSemanticProvider, standardSemanticRegistry, standardVocabularyProvider, standardVocabularyRegistry };