@atscript/typescript 0.1.34 → 0.1.35

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/utils.cjs CHANGED
@@ -1,955 +1,6 @@
1
1
  "use strict";
2
+ const require_json_schema = require('./json-schema-S5-XAOrR.cjs');
2
3
 
3
- //#region packages/typescript/src/validator.ts
4
- function _define_property(obj, key, value) {
5
- if (key in obj) Object.defineProperty(obj, key, {
6
- value,
7
- enumerable: true,
8
- configurable: true,
9
- writable: true
10
- });
11
- else obj[key] = value;
12
- return obj;
13
- }
14
- const regexCache = new Map();
15
- var Validator = class {
16
- isLimitExceeded() {
17
- if (this.stackErrors.length > 0) {
18
- const top = this.stackErrors[this.stackErrors.length - 1];
19
- return top !== null && top.length >= this.opts.errorLimit;
20
- }
21
- return this.errors.length >= this.opts.errorLimit;
22
- }
23
- push(name) {
24
- this.stackPath.push(name);
25
- this.stackErrors.push(null);
26
- this.cachedPath = this.stackPath.length <= 1 ? "" : this.stackPath[1] + (this.stackPath.length > 2 ? "." + this.stackPath.slice(2).join(".") : "");
27
- }
28
- pop(saveErrors) {
29
- this.stackPath.pop();
30
- const popped = this.stackErrors.pop();
31
- if (saveErrors && popped !== null && popped !== undefined && popped.length > 0) for (const err of popped) this.error(err.message, err.path, err.details);
32
- this.cachedPath = this.stackPath.length <= 1 ? "" : this.stackPath[1] + (this.stackPath.length > 2 ? "." + this.stackPath.slice(2).join(".") : "");
33
- return popped;
34
- }
35
- clear() {
36
- this.stackErrors[this.stackErrors.length - 1] = null;
37
- }
38
- error(message, path, details) {
39
- let errors = this.stackErrors[this.stackErrors.length - 1];
40
- if (!errors) if (this.stackErrors.length > 0) {
41
- errors = [];
42
- this.stackErrors[this.stackErrors.length - 1] = errors;
43
- } else errors = this.errors;
44
- const error = {
45
- path: path || this.cachedPath,
46
- message
47
- };
48
- if (details?.length) error.details = details;
49
- errors.push(error);
50
- }
51
- throw() {
52
- throw new ValidatorError(this.errors);
53
- }
54
- /**
55
- * Validates a value against the type definition.
56
- *
57
- * Acts as a TypeScript type guard — when it returns `true`, the value
58
- * is narrowed to `DataType`.
59
- *
60
- * @param value - The value to validate.
61
- * @param safe - If `true`, returns `false` on failure instead of throwing.
62
- * @returns `true` if the value matches the type definition.
63
- * @throws {ValidatorError} When validation fails and `safe` is not `true`.
64
- */ validate(value, safe, context) {
65
- this.errors = [];
66
- this.stackErrors = [];
67
- this.stackPath = [""];
68
- this.cachedPath = "";
69
- this.context = context;
70
- const passed = this.validateSafe(this.def, value);
71
- this.pop(!passed);
72
- this.context = undefined;
73
- if (!passed) {
74
- if (safe) return false;
75
- this.throw();
76
- }
77
- return true;
78
- }
79
- validateSafe(def, value) {
80
- if (this.isLimitExceeded()) return false;
81
- if (!isAnnotatedType(def)) throw new Error("Can not validate not-annotated type");
82
- if (typeof this.opts.replace === "function") def = this.opts.replace(def, this.cachedPath);
83
- if (def.optional && value === undefined) return true;
84
- for (const plugin of this.opts.plugins) {
85
- const result = plugin(this, def, value);
86
- if (result === false || result === true) return result;
87
- }
88
- return this.validateAnnotatedType(def, value);
89
- }
90
- get path() {
91
- return this.cachedPath;
92
- }
93
- validateAnnotatedType(def, value) {
94
- switch (def.type.kind) {
95
- case "": {
96
- if (def.type.designType === "phantom") return true;
97
- return this.validatePrimitive(def, value);
98
- }
99
- case "object": return this.validateObject(def, value);
100
- case "array": return this.validateArray(def, value);
101
- case "union": return this.validateUnion(def, value);
102
- case "intersection": return this.validateIntersection(def, value);
103
- case "tuple": return this.validateTuple(def, value);
104
- default: throw new Error(`Unknown type kind "${def.type.kind}"`);
105
- }
106
- }
107
- validateUnion(def, value) {
108
- let i = 0;
109
- const popped = [];
110
- for (const item of def.type.items) {
111
- this.push(`[${item.type.kind || item.type.designType}(${i})]`);
112
- if (this.validateSafe(item, value)) {
113
- this.pop(false);
114
- return true;
115
- }
116
- const errors = this.pop(false);
117
- if (errors) popped.push(...errors);
118
- i++;
119
- }
120
- this.clear();
121
- const expected = def.type.items.map((item, i$1) => `[${item.type.kind || item.type.designType}(${i$1})]`).join(", ");
122
- this.error(`Value does not match any of the allowed types: ${expected}`, undefined, popped);
123
- return false;
124
- }
125
- validateIntersection(def, value) {
126
- for (const item of def.type.items) if (!this.validateSafe(item, value)) return false;
127
- return true;
128
- }
129
- validateTuple(def, value) {
130
- if (!Array.isArray(value) || value.length !== def.type.items.length) {
131
- this.error(`Expected array of length ${def.type.items.length}`);
132
- return false;
133
- }
134
- let i = 0;
135
- for (const item of def.type.items) {
136
- this.push(String(i));
137
- if (!this.validateSafe(item, value[i])) {
138
- this.pop(true);
139
- return false;
140
- }
141
- this.pop(false);
142
- i++;
143
- }
144
- return true;
145
- }
146
- validateArray(def, value) {
147
- if (!Array.isArray(value)) {
148
- this.error("Expected array");
149
- return false;
150
- }
151
- const minLength = def.metadata.get("expect.minLength");
152
- if (minLength) {
153
- const length = typeof minLength === "number" ? minLength : minLength.length;
154
- if (value.length < length) {
155
- const message = typeof minLength === "object" && minLength.message ? minLength.message : `Expected minimum length of ${length} items, got ${value.length} items`;
156
- this.error(message);
157
- return false;
158
- }
159
- }
160
- const maxLength = def.metadata.get("expect.maxLength");
161
- if (maxLength) {
162
- const length = typeof maxLength === "number" ? maxLength : maxLength.length;
163
- if (value.length > length) {
164
- const message = typeof maxLength === "object" && maxLength.message ? maxLength.message : `Expected maximum length of ${length} items, got ${value.length} items`;
165
- this.error(message);
166
- return false;
167
- }
168
- }
169
- const uniqueItems = def.metadata.get("expect.array.uniqueItems");
170
- if (uniqueItems) {
171
- const separator = "▼↩";
172
- const seen = new Set();
173
- const keyProps = new Set();
174
- if (def.type.of.type.kind === "object") {
175
- for (const [key, val] of def.type.of.type.props.entries()) if (val.metadata.get("expect.array.key")) keyProps.add(key);
176
- }
177
- for (let idx = 0; idx < value.length; idx++) {
178
- const item = value[idx];
179
- let key;
180
- if (keyProps.size > 0) {
181
- key = "";
182
- for (const prop of keyProps) key += JSON.stringify(item[prop]) + separator;
183
- } else key = JSON.stringify(item);
184
- if (seen.has(key)) {
185
- this.push(String(idx));
186
- this.error(uniqueItems.message || "Duplicate items are not allowed");
187
- this.pop(true);
188
- return false;
189
- }
190
- seen.add(key);
191
- }
192
- }
193
- let i = 0;
194
- let passed = true;
195
- for (const item of value) {
196
- this.push(String(i));
197
- if (!this.validateSafe(def.type.of, item)) {
198
- passed = false;
199
- this.pop(true);
200
- if (this.isLimitExceeded()) return false;
201
- } else this.pop(false);
202
- i++;
203
- }
204
- return passed;
205
- }
206
- validateObject(def, value) {
207
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
208
- this.error("Expected object");
209
- return false;
210
- }
211
- let passed = true;
212
- const valueKeys = new Set(Object.keys(value));
213
- const typeKeys = new Set();
214
- let skipList;
215
- if (this.opts.skipList) {
216
- const path = this.stackPath.length > 1 ? `${this.cachedPath}.` : "";
217
- for (const item of this.opts.skipList) if (item.startsWith(path)) {
218
- const key = item.slice(path.length);
219
- if (!skipList) skipList = new Set();
220
- skipList.add(key);
221
- valueKeys.delete(key);
222
- }
223
- }
224
- let partialFunctionMatched = false;
225
- if (typeof this.opts.partial === "function") partialFunctionMatched = this.opts.partial(def, this.cachedPath);
226
- for (const [key, item] of def.type.props.entries()) {
227
- if (skipList && skipList.has(key) || isPhantomType(item)) continue;
228
- typeKeys.add(key);
229
- if (value[key] === undefined) {
230
- if (partialFunctionMatched || this.opts.partial === "deep" || this.opts.partial === true && this.stackPath.length <= 1) continue;
231
- }
232
- this.push(key);
233
- if (this.validateSafe(item, value[key])) this.pop(false);
234
- else {
235
- passed = false;
236
- this.pop(true);
237
- if (this.isLimitExceeded()) return false;
238
- }
239
- }
240
- for (const key of valueKeys)
241
- /** matched patterns for unknown keys */ if (!typeKeys.has(key)) {
242
- const matched = [];
243
- for (const { pattern, def: propDef } of def.type.propsPatterns) if (pattern.test(key)) matched.push({
244
- pattern,
245
- def: propDef
246
- });
247
- if (matched.length > 0) {
248
- this.push(key);
249
- let keyPassed = false;
250
- for (const { def: propDef } of matched) {
251
- if (this.validateSafe(propDef, value[key])) {
252
- keyPassed = true;
253
- break;
254
- }
255
- this.clear();
256
- }
257
- if (!keyPassed) {
258
- this.validateSafe(matched[0].def, value[key]);
259
- this.pop(true);
260
- passed = false;
261
- if (this.isLimitExceeded()) return false;
262
- } else this.pop(false);
263
- } else if (this.opts.unknownProps !== "ignore") {
264
- if (this.opts.unknownProps === "error") {
265
- this.push(key);
266
- this.error(`Unexpected property`);
267
- this.pop(true);
268
- if (this.isLimitExceeded()) return false;
269
- passed = false;
270
- } else if (this.opts.unknownProps === "strip") delete value[key];
271
- }
272
- }
273
- return passed;
274
- }
275
- validatePrimitive(def, value) {
276
- if (def.type.value !== undefined) {
277
- if (value !== def.type.value) {
278
- this.error(`Expected ${def.type.value}, got ${value}`);
279
- return false;
280
- }
281
- return true;
282
- }
283
- const typeOfValue = Array.isArray(value) ? "array" : typeof value;
284
- switch (def.type.designType) {
285
- case "never": {
286
- this.error(`This type is impossible, must be an internal problem`);
287
- return false;
288
- }
289
- case "any": return true;
290
- case "string": {
291
- if (typeOfValue !== def.type.designType) {
292
- this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
293
- return false;
294
- }
295
- return this.validateString(def, value);
296
- }
297
- case "number": {
298
- if (typeOfValue !== def.type.designType) {
299
- this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
300
- return false;
301
- }
302
- return this.validateNumber(def, value);
303
- }
304
- case "boolean": {
305
- if (typeOfValue !== def.type.designType) {
306
- this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
307
- return false;
308
- }
309
- return this.validateBoolean(def, value);
310
- }
311
- case "undefined": {
312
- if (value !== undefined) {
313
- this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
314
- return false;
315
- }
316
- return true;
317
- }
318
- case "null": {
319
- if (value !== null) {
320
- this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
321
- return false;
322
- }
323
- return true;
324
- }
325
- default: throw new Error(`Unknown type "${def.type.designType}"`);
326
- }
327
- }
328
- validateString(def, value) {
329
- const filled = def.metadata.get("meta.required");
330
- if (filled) {
331
- if (value.trim().length === 0) {
332
- const message = typeof filled === "object" && filled.message ? filled.message : `Must not be empty`;
333
- this.error(message);
334
- return false;
335
- }
336
- }
337
- const minLength = def.metadata.get("expect.minLength");
338
- if (minLength) {
339
- const length = typeof minLength === "number" ? minLength : minLength.length;
340
- if (value.length < length) {
341
- const message = typeof minLength === "object" && minLength.message ? minLength.message : `Expected minimum length of ${length} characters, got ${value.length} characters`;
342
- this.error(message);
343
- return false;
344
- }
345
- }
346
- const maxLength = def.metadata.get("expect.maxLength");
347
- if (maxLength) {
348
- const length = typeof maxLength === "number" ? maxLength : maxLength.length;
349
- if (value.length > length) {
350
- const message = typeof maxLength === "object" && maxLength.message ? maxLength.message : `Expected maximum length of ${length} characters, got ${value.length} characters`;
351
- this.error(message);
352
- return false;
353
- }
354
- }
355
- const patterns = def.metadata.get("expect.pattern");
356
- for (const { pattern, flags, message } of patterns || []) {
357
- if (!pattern) continue;
358
- const cacheKey = `${pattern}//${flags || ""}`;
359
- let regex = regexCache.get(cacheKey);
360
- if (!regex) {
361
- regex = new RegExp(pattern, flags);
362
- regexCache.set(cacheKey, regex);
363
- }
364
- if (!regex.test(value)) {
365
- this.error(message || `Value is expected to match pattern "${pattern}"`);
366
- return false;
367
- }
368
- }
369
- return true;
370
- }
371
- validateNumber(def, value) {
372
- const int = def.metadata.get("expect.int");
373
- if (int && value % 1 !== 0) {
374
- const message = typeof int === "object" && int.message ? int.message : `Expected integer, got ${value}`;
375
- this.error(message);
376
- return false;
377
- }
378
- const min = def.metadata.get("expect.min");
379
- if (min) {
380
- const minValue = typeof min === "number" ? min : min.minValue;
381
- if (value < minValue) {
382
- const message = typeof min === "object" && min.message ? min.message : `Expected minimum ${minValue}, got ${value}`;
383
- this.error(message);
384
- return false;
385
- }
386
- }
387
- const max = def.metadata.get("expect.max");
388
- if (max) {
389
- const maxValue = typeof max === "number" ? max : max.maxValue;
390
- if (value > maxValue) {
391
- const message = typeof max === "object" && max.message ? max.message : `Expected maximum ${maxValue}, got ${value}`;
392
- this.error(message);
393
- return false;
394
- }
395
- }
396
- return true;
397
- }
398
- validateBoolean(def, value) {
399
- const filled = def.metadata.get("meta.required");
400
- if (filled) {
401
- if (value !== true) {
402
- const message = typeof filled === "object" && filled.message ? filled.message : `Must be checked`;
403
- this.error(message);
404
- return false;
405
- }
406
- }
407
- return true;
408
- }
409
- constructor(def, opts) {
410
- _define_property(this, "def", void 0);
411
- _define_property(this, "opts", void 0);
412
- /** Validation errors collected during the last {@link validate} call. */ _define_property(this, "errors", void 0);
413
- _define_property(this, "stackErrors", void 0);
414
- _define_property(this, "stackPath", void 0);
415
- _define_property(this, "cachedPath", void 0);
416
- _define_property(this, "context", void 0);
417
- this.def = def;
418
- this.errors = [];
419
- this.stackErrors = [];
420
- this.stackPath = [];
421
- this.cachedPath = "";
422
- this.opts = {
423
- partial: false,
424
- unknownProps: "error",
425
- errorLimit: 10,
426
- ...opts,
427
- plugins: opts?.plugins || []
428
- };
429
- }
430
- };
431
- var ValidatorError = class extends Error {
432
- constructor(errors) {
433
- super(`${errors[0].path ? errors[0].path + ": " : ""}${errors[0].message}`), _define_property(this, "errors", void 0), _define_property(this, "name", void 0), this.errors = errors, this.name = "Validation Error";
434
- }
435
- };
436
-
437
- //#endregion
438
- //#region packages/typescript/src/annotated-type.ts
439
- const COMPLEX_KINDS = new Set([
440
- "union",
441
- "intersection",
442
- "tuple"
443
- ]);
444
- const NON_PRIMITIVE_KINDS = new Set(["array", "object"]);
445
- /** Shared validator method reused by all annotated type nodes. */ function validatorMethod(opts) {
446
- return new Validator(this, opts);
447
- }
448
- function createAnnotatedTypeNode(type, metadata, opts) {
449
- return {
450
- __is_atscript_annotated_type: true,
451
- type,
452
- metadata,
453
- validator: validatorMethod,
454
- id: opts?.id,
455
- optional: opts?.optional,
456
- ref: opts?.ref
457
- };
458
- }
459
- function isAnnotatedType(type) {
460
- return type && type.__is_atscript_annotated_type;
461
- }
462
- function annotate(metadata, key, value, asArray) {
463
- if (!metadata) return;
464
- if (asArray) if (metadata.has(key)) {
465
- const a = metadata.get(key);
466
- if (Array.isArray(a)) a.push(value);
467
- else metadata.set(key, [a, value]);
468
- } else metadata.set(key, [value]);
469
- else metadata.set(key, value);
470
- }
471
- function cloneRefProp(parentType, propName) {
472
- if (parentType.kind !== "object") return;
473
- const objType = parentType;
474
- const existing = objType.props.get(propName);
475
- if (!existing) return;
476
- const clonedType = cloneTypeDef(existing.type);
477
- objType.props.set(propName, createAnnotatedTypeNode(clonedType, new Map(existing.metadata), {
478
- id: existing.id,
479
- optional: existing.optional
480
- }));
481
- }
482
- function cloneTypeDef(type) {
483
- if (type.kind === "object") {
484
- const obj = type;
485
- const props = new Map();
486
- for (const [k, v] of obj.props) props.set(k, createAnnotatedTypeNode(v.type, new Map(v.metadata), {
487
- id: v.id,
488
- optional: v.optional
489
- }));
490
- return {
491
- kind: "object",
492
- props,
493
- propsPatterns: [...obj.propsPatterns],
494
- tags: new Set(obj.tags)
495
- };
496
- }
497
- if (type.kind === "array") {
498
- const arr = type;
499
- return {
500
- kind: "array",
501
- of: arr.of,
502
- tags: new Set(arr.tags)
503
- };
504
- }
505
- if (type.kind === "union" || type.kind === "intersection" || type.kind === "tuple") {
506
- const complex = type;
507
- return {
508
- kind: type.kind,
509
- items: [...complex.items],
510
- tags: new Set(complex.tags)
511
- };
512
- }
513
- return {
514
- ...type,
515
- tags: new Set(type.tags)
516
- };
517
- }
518
- function defineAnnotatedType(_kind, base) {
519
- const kind = _kind || "";
520
- const type = base?.type || {};
521
- type.kind = kind;
522
- if (COMPLEX_KINDS.has(kind)) type.items = [];
523
- if (kind === "object") {
524
- type.props = new Map();
525
- type.propsPatterns = [];
526
- }
527
- type.tags = new Set();
528
- const metadata = base?.metadata || new Map();
529
- const payload = {
530
- __is_atscript_annotated_type: true,
531
- metadata,
532
- type,
533
- validator: validatorMethod
534
- };
535
- base = base ? Object.assign(base, payload) : payload;
536
- const handle = {
537
- $type: base,
538
- $def: type,
539
- $metadata: metadata,
540
- tags(...tags) {
541
- for (const tag of tags) this.$def.tags.add(tag);
542
- return this;
543
- },
544
- designType(value) {
545
- this.$def.designType = value;
546
- return this;
547
- },
548
- value(value) {
549
- this.$def.value = value;
550
- return this;
551
- },
552
- of(value) {
553
- this.$def.of = value;
554
- return this;
555
- },
556
- item(value) {
557
- this.$def.items.push(value);
558
- return this;
559
- },
560
- prop(name, value) {
561
- this.$def.props.set(name, value);
562
- return this;
563
- },
564
- propPattern(pattern, def) {
565
- this.$def.propsPatterns.push({
566
- pattern,
567
- def
568
- });
569
- return this;
570
- },
571
- optional(value = true) {
572
- this.$type.optional = value;
573
- return this;
574
- },
575
- copyMetadata(fromMetadata, ignore) {
576
- for (const [key, value] of fromMetadata.entries()) if (!ignore || !ignore.has(key)) this.$metadata.set(key, value);
577
- return this;
578
- },
579
- refTo(type$1, chain) {
580
- if (isAnnotatedType(type$1)) {
581
- let newBase = type$1;
582
- const typeName = type$1.name || "Unknown";
583
- if (chain) for (let i = 0; i < chain.length; i++) {
584
- const c = chain[i];
585
- if (newBase.type.kind === "object" && newBase.type.props.has(c)) newBase = newBase.type.props.get(c);
586
- else {
587
- const keys = chain.slice(0, i + 1).map((k) => `["${k}"]`).join("");
588
- throw new Error(`Can't find prop ${typeName}${keys}`);
589
- }
590
- }
591
- this.$type = createAnnotatedTypeNode(newBase.type, metadata, {
592
- id: newBase.id,
593
- ref: chain && chain.length > 0 ? {
594
- type: () => type$1,
595
- field: chain.join(".")
596
- } : undefined
597
- });
598
- } else if (typeof type$1 === "function") {
599
- const lazyType = type$1;
600
- this.$type = createAnnotatedTypeNode({ kind: "" }, metadata, { ref: {
601
- type: lazyType,
602
- field: chain ? chain.join(".") : ""
603
- } });
604
- const node = this.$type;
605
- const placeholder = node.type;
606
- Object.defineProperty(node, "type", {
607
- get() {
608
- const t = lazyType();
609
- if (!isAnnotatedType(t)) {
610
- Object.defineProperty(node, "type", {
611
- value: placeholder,
612
- writable: false,
613
- configurable: true
614
- });
615
- return placeholder;
616
- }
617
- let target = t;
618
- if (chain) for (const c of chain) if (target.type.kind === "object" && target.type.props.has(c)) target = target.type.props.get(c);
619
- else return t.type;
620
- node.id = target.id || t.id;
621
- Object.defineProperty(node, "type", {
622
- value: target.type,
623
- writable: false,
624
- configurable: true
625
- });
626
- return target.type;
627
- },
628
- configurable: true
629
- });
630
- } else throw new Error(`${type$1} is not annotated type`);
631
- return this;
632
- },
633
- annotate(key, value, asArray) {
634
- annotate(this.$metadata, key, value, asArray);
635
- return this;
636
- },
637
- id(value) {
638
- this.$type.id = value;
639
- return this;
640
- }
641
- };
642
- return handle;
643
- }
644
- function isPhantomType(def) {
645
- return def.type.kind === "" && def.type.designType === "phantom";
646
- }
647
- function isAnnotatedTypeOfPrimitive(t) {
648
- if (NON_PRIMITIVE_KINDS.has(t.type.kind)) return false;
649
- if (!t.type.kind) return true;
650
- if (COMPLEX_KINDS.has(t.type.kind)) {
651
- for (const item of t.type.items) if (!isAnnotatedTypeOfPrimitive(item)) return false;
652
- return true;
653
- }
654
- return false;
655
- }
656
-
657
- //#endregion
658
- //#region packages/typescript/src/traverse.ts
659
- function forAnnotatedType(def, handlers) {
660
- switch (def.type.kind) {
661
- case "": {
662
- const typed = def;
663
- if (handlers.phantom && typed.type.designType === "phantom") return handlers.phantom(typed);
664
- return handlers.final(typed);
665
- }
666
- case "object": return handlers.object(def);
667
- case "array": return handlers.array(def);
668
- case "union": return handlers.union(def);
669
- case "intersection": return handlers.intersection(def);
670
- case "tuple": return handlers.tuple(def);
671
- default: throw new Error(`Unknown type kind "${def.type.kind}"`);
672
- }
673
- }
674
-
675
- //#endregion
676
- //#region packages/typescript/src/json-schema.ts
677
- /**
678
- * Detects a discriminator property across union items.
679
- *
680
- * Scans all items for object-typed members that share a common property
681
- * with distinct const/literal values. If exactly one such property exists,
682
- * it is returned as the discriminator.
683
- */ function detectDiscriminator(items) {
684
- if (items.length < 2) return null;
685
- for (const item of items) if (item.type.kind !== "object") return null;
686
- const firstObj = items[0].type;
687
- const candidates = [];
688
- for (const [propName, propType] of firstObj.props.entries()) if (propType.type.kind === "" && propType.type.value !== undefined) candidates.push(propName);
689
- let result = null;
690
- for (const candidate of candidates) {
691
- const values = new Set();
692
- const indexMapping = {};
693
- let valid = true;
694
- for (let i = 0; i < items.length; i++) {
695
- const obj = items[i].type;
696
- const prop = obj.props.get(candidate);
697
- if (!prop || prop.type.kind !== "" || prop.type.value === undefined) {
698
- valid = false;
699
- break;
700
- }
701
- const val = prop.type.value;
702
- if (values.has(val)) {
703
- valid = false;
704
- break;
705
- }
706
- values.add(val);
707
- indexMapping[String(val)] = i;
708
- }
709
- if (valid) {
710
- if (result) return null;
711
- result = {
712
- propertyName: candidate,
713
- indexMapping
714
- };
715
- }
716
- }
717
- return result;
718
- }
719
- function buildJsonSchema(type) {
720
- const defs = {};
721
- let hasDefs = false;
722
- const buildObject = (d) => {
723
- const properties = {};
724
- const required = [];
725
- for (const [key, val] of d.type.props.entries()) {
726
- if (isPhantomType(val)) continue;
727
- properties[key] = build$1(val);
728
- if (!val.optional) required.push(key);
729
- }
730
- const schema$1 = {
731
- type: "object",
732
- properties
733
- };
734
- if (required.length > 0) schema$1.required = required;
735
- return schema$1;
736
- };
737
- const build$1 = (def) => {
738
- if (def.id && def.type.kind === "object" && def !== type) {
739
- const name = def.id;
740
- if (!defs[name]) {
741
- hasDefs = true;
742
- defs[name] = {};
743
- defs[name] = buildObject(def);
744
- }
745
- return { $ref: `#/$defs/${name}` };
746
- }
747
- const meta = def.metadata;
748
- return forAnnotatedType(def, {
749
- phantom() {
750
- return {};
751
- },
752
- object(d) {
753
- return buildObject(d);
754
- },
755
- array(d) {
756
- const schema$1 = {
757
- type: "array",
758
- items: build$1(d.type.of)
759
- };
760
- const minLength = meta.get("expect.minLength");
761
- if (minLength) schema$1.minItems = typeof minLength === "number" ? minLength : minLength.length;
762
- const maxLength = meta.get("expect.maxLength");
763
- if (maxLength) schema$1.maxItems = typeof maxLength === "number" ? maxLength : maxLength.length;
764
- return schema$1;
765
- },
766
- union(d) {
767
- const disc = detectDiscriminator(d.type.items);
768
- if (disc) {
769
- const oneOf = d.type.items.map(build$1);
770
- const mapping = {};
771
- for (const [val, idx] of Object.entries(disc.indexMapping)) {
772
- const item = d.type.items[idx];
773
- mapping[val] = item.id && defs[item.id] ? `#/$defs/${item.id}` : `#/oneOf/${idx}`;
774
- }
775
- return {
776
- oneOf,
777
- discriminator: {
778
- propertyName: disc.propertyName,
779
- mapping
780
- }
781
- };
782
- }
783
- return { anyOf: d.type.items.map(build$1) };
784
- },
785
- intersection(d) {
786
- return { allOf: d.type.items.map(build$1) };
787
- },
788
- tuple(d) {
789
- return {
790
- type: "array",
791
- items: d.type.items.map(build$1),
792
- additionalItems: false
793
- };
794
- },
795
- final(d) {
796
- const schema$1 = {};
797
- if (d.type.value !== undefined) schema$1.const = d.type.value;
798
- if (d.type.designType && d.type.designType !== "any") {
799
- schema$1.type = d.type.designType === "undefined" ? "null" : d.type.designType;
800
- if (schema$1.type === "number" && meta.get("expect.int")) schema$1.type = "integer";
801
- }
802
- if (schema$1.type === "string") {
803
- if (meta.get("meta.required")) schema$1.minLength = 1;
804
- const minLength = meta.get("expect.minLength");
805
- if (minLength) schema$1.minLength = typeof minLength === "number" ? minLength : minLength.length;
806
- const maxLength = meta.get("expect.maxLength");
807
- if (maxLength) schema$1.maxLength = typeof maxLength === "number" ? maxLength : maxLength.length;
808
- const patterns = meta.get("expect.pattern");
809
- if (patterns?.length) if (patterns.length === 1) schema$1.pattern = patterns[0].pattern;
810
- else schema$1.allOf = (schema$1.allOf || []).concat(patterns.map((p) => ({ pattern: p.pattern })));
811
- }
812
- if (schema$1.type === "number" || schema$1.type === "integer") {
813
- const min = meta.get("expect.min");
814
- if (min) schema$1.minimum = typeof min === "number" ? min : min.minValue;
815
- const max = meta.get("expect.max");
816
- if (max) schema$1.maximum = typeof max === "number" ? max : max.maxValue;
817
- }
818
- return schema$1;
819
- }
820
- });
821
- };
822
- const schema = build$1(type);
823
- if (hasDefs) return {
824
- ...schema,
825
- $defs: defs
826
- };
827
- return schema;
828
- }
829
- function fromJsonSchema(schema) {
830
- const defsSource = schema.$defs || schema.definitions || {};
831
- const resolved = new Map();
832
- const convert = (s) => {
833
- if (!s || Object.keys(s).length === 0) return defineAnnotatedType().designType("any").$type;
834
- if (s.$ref) {
835
- const refName = s.$ref.replace(/^#\/(\$defs|definitions)\//, "");
836
- if (resolved.has(refName)) return resolved.get(refName);
837
- if (defsSource[refName]) {
838
- const placeholder = defineAnnotatedType().designType("any").$type;
839
- resolved.set(refName, placeholder);
840
- const type = convert(defsSource[refName]);
841
- resolved.set(refName, type);
842
- return type;
843
- }
844
- throw new Error(`Unresolvable $ref: ${s.$ref}`);
845
- }
846
- if ("const" in s) {
847
- const val = s.const;
848
- const dt = val === null ? "null" : typeof val;
849
- return defineAnnotatedType().designType(dt).value(val).$type;
850
- }
851
- if (s.enum) {
852
- const handle = defineAnnotatedType("union");
853
- for (const val of s.enum) {
854
- const dt = val === null ? "null" : typeof val;
855
- handle.item(defineAnnotatedType().designType(dt).value(val).$type);
856
- }
857
- return handle.$type;
858
- }
859
- if (s.anyOf) {
860
- const handle = defineAnnotatedType("union");
861
- for (const item of s.anyOf) handle.item(convert(item));
862
- return handle.$type;
863
- }
864
- if (s.oneOf) {
865
- const handle = defineAnnotatedType("union");
866
- for (const item of s.oneOf) handle.item(convert(item));
867
- return handle.$type;
868
- }
869
- if (s.allOf && !s.type) {
870
- const handle = defineAnnotatedType("intersection");
871
- for (const item of s.allOf) handle.item(convert(item));
872
- return handle.$type;
873
- }
874
- if (Array.isArray(s.type)) {
875
- const handle = defineAnnotatedType("union");
876
- for (const t of s.type) handle.item(convert({
877
- ...s,
878
- type: t
879
- }));
880
- return handle.$type;
881
- }
882
- if (s.type === "object") {
883
- const handle = defineAnnotatedType("object");
884
- const required = new Set(s.required || []);
885
- if (s.properties) for (const [key, propSchema] of Object.entries(s.properties)) {
886
- const propType = convert(propSchema);
887
- if (!required.has(key)) propType.optional = true;
888
- handle.prop(key, propType);
889
- }
890
- return handle.$type;
891
- }
892
- if (s.type === "array") {
893
- if (Array.isArray(s.items)) {
894
- const handle$1 = defineAnnotatedType("tuple");
895
- for (const item of s.items) handle$1.item(convert(item));
896
- return handle$1.$type;
897
- }
898
- const itemType = s.items ? convert(s.items) : defineAnnotatedType().designType("any").$type;
899
- const handle = defineAnnotatedType("array").of(itemType);
900
- if (typeof s.minItems === "number") handle.annotate("expect.minLength", { length: s.minItems });
901
- if (typeof s.maxItems === "number") handle.annotate("expect.maxLength", { length: s.maxItems });
902
- return handle.$type;
903
- }
904
- if (s.type === "string") {
905
- const handle = defineAnnotatedType().designType("string").tags("string");
906
- if (typeof s.minLength === "number") handle.annotate("expect.minLength", { length: s.minLength });
907
- if (typeof s.maxLength === "number") handle.annotate("expect.maxLength", { length: s.maxLength });
908
- if (s.pattern) handle.annotate("expect.pattern", { pattern: s.pattern }, true);
909
- if (s.allOf) {
910
- for (const item of s.allOf) if (item.pattern) handle.annotate("expect.pattern", { pattern: item.pattern }, true);
911
- }
912
- return handle.$type;
913
- }
914
- if (s.type === "integer") {
915
- const handle = defineAnnotatedType().designType("number").tags("number");
916
- handle.annotate("expect.int", true);
917
- if (typeof s.minimum === "number") handle.annotate("expect.min", { minValue: s.minimum });
918
- if (typeof s.maximum === "number") handle.annotate("expect.max", { maxValue: s.maximum });
919
- return handle.$type;
920
- }
921
- if (s.type === "number") {
922
- const handle = defineAnnotatedType().designType("number").tags("number");
923
- if (typeof s.minimum === "number") handle.annotate("expect.min", { minValue: s.minimum });
924
- if (typeof s.maximum === "number") handle.annotate("expect.max", { maxValue: s.maximum });
925
- return handle.$type;
926
- }
927
- if (s.type === "boolean") return defineAnnotatedType().designType("boolean").tags("boolean").$type;
928
- if (s.type === "null") return defineAnnotatedType().designType("null").tags("null").$type;
929
- return defineAnnotatedType().designType("any").$type;
930
- };
931
- return convert(schema);
932
- }
933
- function mergeJsonSchemas(types) {
934
- const mergedDefs = {};
935
- const schemas = {};
936
- for (const type of types) {
937
- const name = type.id;
938
- if (!name) throw new Error("mergeJsonSchemas: all types must have an id");
939
- const schema = buildJsonSchema(type);
940
- if (schema.$defs) {
941
- for (const [defName, defSchema] of Object.entries(schema.$defs)) if (!mergedDefs[defName]) mergedDefs[defName] = defSchema;
942
- const { $defs: _,...rest } = schema;
943
- schemas[name] = rest;
944
- } else schemas[name] = schema;
945
- }
946
- return {
947
- schemas,
948
- $defs: mergedDefs
949
- };
950
- }
951
-
952
- //#endregion
953
4
  //#region packages/typescript/src/default-value.ts
954
5
  /**
955
6
  * Attempts to resolve a value from the mode for the given annotated type.
@@ -964,7 +15,7 @@ function mergeJsonSchemas(types) {
964
15
  return undefined;
965
16
  }
966
17
  if (mode === "db") {
967
- const dbValue = prop.metadata.get("db.default.value");
18
+ const dbValue = prop.metadata.get("db.default");
968
19
  if (dbValue !== undefined) {
969
20
  const parsed$1 = parseRawValue(dbValue, prop);
970
21
  if (parsed$1 !== undefined && prop.validator({ unknownProps: "ignore" }).validate(parsed$1, true)) return { value: parsed$1 };
@@ -1010,13 +61,13 @@ function createDataFromAnnotatedType(type, opts) {
1010
61
  function build(def, path, mode) {
1011
62
  const resolved = resolveValue(def, path, mode);
1012
63
  if (resolved !== undefined) return resolved.value;
1013
- return forAnnotatedType(def, {
64
+ return require_json_schema.forAnnotatedType(def, {
1014
65
  phantom: () => undefined,
1015
66
  final: (d) => finalDefault(d),
1016
67
  object: (d) => {
1017
68
  const data = {};
1018
69
  for (const [key, prop] of d.type.props.entries()) {
1019
- if (isPhantomType(prop)) continue;
70
+ if (require_json_schema.isPhantomType(prop)) continue;
1020
71
  const childPath = path ? `${path}.${key}` : key;
1021
72
  if (prop.optional) {
1022
73
  if (mode === "example") data[key] = build(prop, childPath, mode);
@@ -1064,7 +115,7 @@ function flattenAnnotatedType(type, options) {
1064
115
  function addFieldToFlatMap(name, def) {
1065
116
  const existing = flatMap.get(name);
1066
117
  if (existing) {
1067
- const flatUnion = defineAnnotatedType("union").copyMetadata(existing.metadata).copyMetadata(def.metadata);
118
+ const flatUnion = require_json_schema.defineAnnotatedType("union").copyMetadata(existing.metadata).copyMetadata(def.metadata);
1068
119
  if (existing.__flat_union) existing.type.items.forEach((item) => flatUnion.item(item));
1069
120
  else flatUnion.item(existing);
1070
121
  flatUnion.item(def);
@@ -1074,11 +125,20 @@ else flatUnion.item(existing);
1074
125
  } else flatMap.set(name, def);
1075
126
  }
1076
127
  function flattenArray(def, name) {
128
+ const resolvedId = def.id;
129
+ if (resolvedId) {
130
+ if (visitedIds.has(resolvedId)) return;
131
+ visitedIds.add(resolvedId);
132
+ }
1077
133
  switch (def.type.kind) {
1078
134
  case "object": {
135
+ if (!resolvedId && def.id) {
136
+ if (visitedIds.has(def.id)) return;
137
+ visitedIds.add(def.id);
138
+ }
1079
139
  const items = Array.from(def.type.props.entries());
1080
140
  for (const [key, value] of items) {
1081
- if (skipPhantom && isPhantomType(value)) continue;
141
+ if (skipPhantom && require_json_schema.isPhantomType(value)) continue;
1082
142
  flattenType(value, name ? `${name}.${key}` : key, true);
1083
143
  }
1084
144
  break;
@@ -1097,18 +157,28 @@ else flatUnion.item(existing);
1097
157
  }
1098
158
  }
1099
159
  function flattenType(def, prefix = "", inComplexTypeOrArray = false) {
1100
- const typeId = def.id;
160
+ let typeId = def.id;
1101
161
  if (typeId && visitedIds.has(typeId)) {
1102
162
  addFieldToFlatMap(prefix || "", def);
1103
163
  if (prefix) options?.onField?.(prefix, def, def.metadata);
1104
164
  return;
1105
165
  }
1106
166
  if (typeId) visitedIds.add(typeId);
1107
- switch (def.type.kind) {
167
+ const kind = def.type.kind;
168
+ if (!typeId && def.id) {
169
+ typeId = def.id;
170
+ if (visitedIds.has(typeId)) {
171
+ addFieldToFlatMap(prefix || "", def);
172
+ if (prefix) options?.onField?.(prefix, def, def.metadata);
173
+ return;
174
+ }
175
+ visitedIds.add(typeId);
176
+ }
177
+ switch (kind) {
1108
178
  case "object": {
1109
179
  addFieldToFlatMap(prefix || "", def);
1110
180
  for (const [key, value] of def.type.props.entries()) {
1111
- if (skipPhantom && isPhantomType(value)) continue;
181
+ if (skipPhantom && require_json_schema.isPhantomType(value)) continue;
1112
182
  flattenType(value, prefix ? `${prefix}.${key}` : key, inComplexTypeOrArray);
1113
183
  }
1114
184
  break;
@@ -1116,12 +186,12 @@ else flatUnion.item(existing);
1116
186
  case "array": {
1117
187
  let typeArray = def;
1118
188
  if (!inComplexTypeOrArray) {
1119
- typeArray = defineAnnotatedType().refTo(def).copyMetadata(def.metadata).$type;
189
+ typeArray = require_json_schema.defineAnnotatedType().refTo(def).copyMetadata(def.metadata).$type;
1120
190
  if (def.optional) typeArray.optional = def.optional;
1121
191
  if (options?.topLevelArrayTag) typeArray.metadata.set(options.topLevelArrayTag, true);
1122
192
  }
1123
193
  addFieldToFlatMap(prefix || "", typeArray);
1124
- if (!isAnnotatedTypeOfPrimitive(typeArray.type.of)) flattenArray(typeArray.type.of, prefix);
194
+ if (!require_json_schema.isAnnotatedTypeOfPrimitive(typeArray.type.of)) flattenArray(typeArray.type.of, prefix);
1125
195
  break;
1126
196
  }
1127
197
  case "intersection":
@@ -1175,7 +245,7 @@ function serializeNode(def, path, options, visited) {
1175
245
  return result;
1176
246
  }
1177
247
  function serializeTypeDef(def, path, options, visited) {
1178
- return forAnnotatedType(def, {
248
+ return require_json_schema.forAnnotatedType(def, {
1179
249
  phantom(d) {
1180
250
  return {
1181
251
  kind: "",
@@ -1266,14 +336,14 @@ function deserializeAnnotatedType(data) {
1266
336
  function deserializeNode(data) {
1267
337
  const metadata = new Map(Object.entries(data.metadata));
1268
338
  const type = deserializeTypeDef(data.type);
1269
- const result = createAnnotatedTypeNode(type, metadata, {
339
+ const result = require_json_schema.createAnnotatedTypeNode(type, metadata, {
1270
340
  optional: data.optional || undefined,
1271
341
  id: data.id || undefined
1272
342
  });
1273
343
  return result;
1274
344
  }
1275
345
  function deserializeTypeDef(t) {
1276
- const tags = new Set(t.tags);
346
+ const tags = "tags" in t ? new Set(t.tags) : new Set();
1277
347
  switch (t.kind) {
1278
348
  case "": {
1279
349
  const result = {
@@ -1322,21 +392,21 @@ function deserializeTypeDef(t) {
1322
392
 
1323
393
  //#endregion
1324
394
  exports.SERIALIZE_VERSION = SERIALIZE_VERSION
1325
- exports.Validator = Validator
1326
- exports.ValidatorError = ValidatorError
1327
- exports.annotate = annotate
1328
- exports.buildJsonSchema = buildJsonSchema
1329
- exports.cloneRefProp = cloneRefProp
1330
- exports.createAnnotatedTypeNode = createAnnotatedTypeNode
395
+ exports.Validator = require_json_schema.Validator
396
+ exports.ValidatorError = require_json_schema.ValidatorError
397
+ exports.annotate = require_json_schema.annotate
398
+ exports.buildJsonSchema = require_json_schema.buildJsonSchema
399
+ exports.cloneRefProp = require_json_schema.cloneRefProp
400
+ exports.createAnnotatedTypeNode = require_json_schema.createAnnotatedTypeNode
1331
401
  exports.createDataFromAnnotatedType = createDataFromAnnotatedType
1332
- exports.defineAnnotatedType = defineAnnotatedType
402
+ exports.defineAnnotatedType = require_json_schema.defineAnnotatedType
1333
403
  exports.deserializeAnnotatedType = deserializeAnnotatedType
1334
404
  exports.flattenAnnotatedType = flattenAnnotatedType
1335
- exports.forAnnotatedType = forAnnotatedType
1336
- exports.fromJsonSchema = fromJsonSchema
1337
- exports.isAnnotatedType = isAnnotatedType
1338
- exports.isAnnotatedTypeOfPrimitive = isAnnotatedTypeOfPrimitive
1339
- exports.isPhantomType = isPhantomType
1340
- exports.mergeJsonSchemas = mergeJsonSchemas
405
+ exports.forAnnotatedType = require_json_schema.forAnnotatedType
406
+ exports.fromJsonSchema = require_json_schema.fromJsonSchema
407
+ exports.isAnnotatedType = require_json_schema.isAnnotatedType
408
+ exports.isAnnotatedTypeOfPrimitive = require_json_schema.isAnnotatedTypeOfPrimitive
409
+ exports.isPhantomType = require_json_schema.isPhantomType
410
+ exports.mergeJsonSchemas = require_json_schema.mergeJsonSchemas
1341
411
  exports.serializeAnnotatedType = serializeAnnotatedType
1342
412
  exports.throwFeatureDisabled = throwFeatureDisabled