@atscript/typescript 0.1.17 → 0.1.18

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/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { isArray, isConst, isGroup, isInterface, isPrimitive, isRef, isStructure } from "@atscript/core";
2
1
  import path from "path";
2
+ import { DEFAULT_FORMAT, isArray, isConst, isGroup, isInterface, isPrimitive, isRef, isStructure } from "@atscript/core";
3
3
 
4
4
  //#region packages/typescript/src/codegen/code-printer.ts
5
5
  function _define_property$4(obj, key, value) {
@@ -84,7 +84,7 @@ else if (this.currentLine.length > 0) this.lines.push(this.currentLine);
84
84
  return this;
85
85
  }
86
86
  doPop(withNewLine) {
87
- if (!this.blockStack.length) throw new Error("No block to pop (stack is empty).");
87
+ if (this.blockStack.length === 0) throw new Error("No block to pop (stack is empty).");
88
88
  const closing = this.blockStack.pop();
89
89
  this.unindent();
90
90
  if (withNewLine) this.writeln(closing);
@@ -283,7 +283,7 @@ var TypeRenderer = class TypeRenderer extends BaseRenderer {
283
283
  propsDefs.add(renderedDef);
284
284
  renderedDef.split("\n").forEach((l) => this.writeln(l));
285
285
  }
286
- if (patterns.length) {
286
+ if (patterns.length > 0) {
287
287
  this.write(`[key: string]: `);
288
288
  if (patterns.length > 0) {
289
289
  for (const prop of patterns) propsDefs.add(this.renderTypeDefString(prop.getDefinition()));
@@ -561,7 +561,7 @@ var Validator = class {
561
561
  }
562
562
  let i = 0;
563
563
  for (const item of def.type.items) {
564
- this.push(`[${i}]`);
564
+ this.push(String(i));
565
565
  if (!this.validateSafe(item, value[i])) {
566
566
  this.pop(true);
567
567
  return false;
@@ -597,7 +597,7 @@ var Validator = class {
597
597
  let i = 0;
598
598
  let passed = true;
599
599
  for (const item of value) {
600
- this.push(`[${i}]`);
600
+ this.push(String(i));
601
601
  if (!this.validateSafe(def.type.of, item)) {
602
602
  passed = false;
603
603
  this.pop(true);
@@ -649,7 +649,7 @@ else {
649
649
  pattern,
650
650
  def: propDef
651
651
  });
652
- if (matched.length) {
652
+ if (matched.length > 0) {
653
653
  let keyPassed = false;
654
654
  for (const { def: def$1 } of matched) if (this.validateSafe(def$1, value[key])) {
655
655
  this.pop(false);
@@ -676,7 +676,7 @@ else {
676
676
  return passed;
677
677
  }
678
678
  validatePrimitive(def, value) {
679
- if (typeof def.type.value !== "undefined") {
679
+ if (def.type.value !== undefined) {
680
680
  if (value !== def.type.value) {
681
681
  this.error(`Expected ${def.type.value}, got ${value}`);
682
682
  return false;
@@ -685,40 +685,46 @@ else {
685
685
  }
686
686
  const typeOfValue = Array.isArray(value) ? "array" : typeof value;
687
687
  switch (def.type.designType) {
688
- case "never":
688
+ case "never": {
689
689
  this.error(`This type is impossible, must be an internal problem`);
690
690
  return false;
691
+ }
691
692
  case "any": return true;
692
- case "string":
693
+ case "string": {
693
694
  if (typeOfValue !== def.type.designType) {
694
695
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
695
696
  return false;
696
697
  }
697
698
  return this.validateString(def, value);
698
- case "number":
699
+ }
700
+ case "number": {
699
701
  if (typeOfValue !== def.type.designType) {
700
702
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
701
703
  return false;
702
704
  }
703
705
  return this.validateNumber(def, value);
704
- case "boolean":
706
+ }
707
+ case "boolean": {
705
708
  if (typeOfValue !== def.type.designType) {
706
709
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
707
710
  return false;
708
711
  }
709
712
  return this.validateBoolean(def, value);
710
- case "undefined":
713
+ }
714
+ case "undefined": {
711
715
  if (value !== undefined) {
712
716
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
713
717
  return false;
714
718
  }
715
719
  return true;
716
- case "null":
720
+ }
721
+ case "null": {
717
722
  if (value !== null) {
718
723
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
719
724
  return false;
720
725
  }
721
726
  return true;
727
+ }
722
728
  default: throw new Error(`Unknown type "${def.type.designType}"`);
723
729
  }
724
730
  }
@@ -973,7 +979,7 @@ function buildJsonSchema(type) {
973
979
  type: "object",
974
980
  properties
975
981
  };
976
- if (required.length) schema.required = required;
982
+ if (required.length > 0) schema.required = required;
977
983
  return schema;
978
984
  },
979
985
  array(d) {
@@ -1236,34 +1242,39 @@ else handle.prop(prop.id, propHandle.$type);
1236
1242
  annotations?.forEach((a) => {
1237
1243
  switch (a.name) {
1238
1244
  case "expect.minLength":
1239
- case "expect.maxLength":
1245
+ case "expect.maxLength": {
1240
1246
  if (a.args[0]) handle.annotate(a.name, {
1241
1247
  length: Number(a.args[0].text),
1242
1248
  message: a.args[1]?.text
1243
1249
  });
1244
1250
  break;
1245
- case "expect.min":
1251
+ }
1252
+ case "expect.min": {
1246
1253
  if (a.args[0]) handle.annotate(a.name, {
1247
1254
  minValue: Number(a.args[0].text),
1248
1255
  message: a.args[1]?.text
1249
1256
  });
1250
1257
  break;
1251
- case "expect.max":
1258
+ }
1259
+ case "expect.max": {
1252
1260
  if (a.args[0]) handle.annotate(a.name, {
1253
1261
  maxValue: Number(a.args[0].text),
1254
1262
  message: a.args[1]?.text
1255
1263
  });
1256
1264
  break;
1257
- case "expect.pattern":
1265
+ }
1266
+ case "expect.pattern": {
1258
1267
  handle.annotate(a.name, {
1259
1268
  pattern: a.args[0]?.text || "",
1260
1269
  flags: a.args[1]?.text,
1261
1270
  message: a.args[2]?.text
1262
1271
  }, true);
1263
1272
  break;
1264
- case "expect.int":
1273
+ }
1274
+ case "expect.int": {
1265
1275
  handle.annotate(a.name, true);
1266
1276
  break;
1277
+ }
1267
1278
  default:
1268
1279
  }
1269
1280
  });
@@ -1278,8 +1289,11 @@ else handle.prop(prop.id, propHandle.$type);
1278
1289
  const ref = node;
1279
1290
  const decl = this.doc.unwindType(ref.id, ref.chain)?.def;
1280
1291
  if (isPrimitive(decl)) {
1281
- this.annotateType(decl, name);
1282
- return this;
1292
+ const ownerDecl = this.doc.getDeclarationOwnerNode(ref.id);
1293
+ if (!ownerDecl?.node || ownerDecl.node.entity !== "type" && ownerDecl.node.entity !== "interface") {
1294
+ this.annotateType(decl, name);
1295
+ return this;
1296
+ }
1283
1297
  }
1284
1298
  const chain = ref.hasChain ? `, [${ref.chain.map((c) => `"${escapeQuotes(c.text)}"`).join(", ")}]` : "";
1285
1299
  this.writeln(`$(${name ? `"", ${name}` : ""})`).indent().writeln(`.refTo(${ref.id}${chain})`);
@@ -1321,7 +1335,7 @@ else handle.prop(prop.id, propHandle.$type);
1321
1335
  return this;
1322
1336
  }
1323
1337
  default: {
1324
- console.log("!!!!!!! UNKNOWN ", node.entity);
1338
+ console.log("!!!!!!! UNKNOWN", node.entity);
1325
1339
  return this;
1326
1340
  }
1327
1341
  }
@@ -1346,7 +1360,7 @@ else handle.prop(prop.id, propHandle.$type);
1346
1360
  case "final": return this.writeln(`$(${d()}).designType("${def.value === "void" ? "undefined" : def.value}")`);
1347
1361
  case "union":
1348
1362
  case "intersection":
1349
- case "tuple":
1363
+ case "tuple": {
1350
1364
  this.writeln(`$(${d(def.kind)})`);
1351
1365
  this.indent();
1352
1366
  for (const itemDef of def.items) {
@@ -1359,7 +1373,8 @@ else handle.prop(prop.id, propHandle.$type);
1359
1373
  }
1360
1374
  this.unindent();
1361
1375
  return;
1362
- case "array":
1376
+ }
1377
+ case "array": {
1363
1378
  this.writeln(`$(${d("array")})`);
1364
1379
  this.indent();
1365
1380
  this.write(".of(");
@@ -1370,7 +1385,8 @@ else handle.prop(prop.id, propHandle.$type);
1370
1385
  this.writeln(`)`);
1371
1386
  this.unindent();
1372
1387
  return;
1373
- case "object":
1388
+ }
1389
+ case "object": {
1374
1390
  this.writeln(`$(${d("object")})`);
1375
1391
  this.indent();
1376
1392
  for (const [key, propDef] of Object.entries(def.props)) {
@@ -1397,6 +1413,7 @@ else handle.prop(prop.id, propHandle.$type);
1397
1413
  }
1398
1414
  this.unindent();
1399
1415
  return;
1416
+ }
1400
1417
  default: return this.writeln(`$(${d()}).designType("any")`);
1401
1418
  }
1402
1419
  }
@@ -1443,6 +1460,10 @@ else handle.prop(prop.id, propHandle.$type);
1443
1460
  if (!refNode.hasChain) {
1444
1461
  const resolved = this.doc.unwindType(refNode.id, refNode.chain)?.def;
1445
1462
  if (resolved && !isPrimitive(resolved)) annotations = node.annotations ?? [];
1463
+ else if (resolved && isPrimitive(resolved)) {
1464
+ const ownerDecl = this.doc.getDeclarationOwnerNode(refNode.id);
1465
+ if (ownerDecl?.node && (ownerDecl.node.entity === "type" || ownerDecl.node.entity === "interface")) annotations = node.annotations ?? [];
1466
+ }
1446
1467
  }
1447
1468
  }
1448
1469
  if (annotations === undefined) annotations = this.doc.evalAnnotationsForNode(node);
@@ -1496,7 +1517,7 @@ else targetValue = "true";
1496
1517
  }
1497
1518
  } else {
1498
1519
  multiple = node.countAnnotations(an.name) > 1 || an.args.length > 1;
1499
- if (an.args.length) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
1520
+ if (an.args.length > 0) targetValue = an.args[0].type === "text" ? `"${escapeQuotes(an.args[0].text)}"` : an.args[0].text;
1500
1521
  }
1501
1522
  return {
1502
1523
  value: targetValue,
@@ -1558,7 +1579,7 @@ else targetValue = "true";
1558
1579
  * Returns multiple paths when a property appears in multiple union branches.
1559
1580
  */ buildMutatingAccessors(targetName, targetDef, parts) {
1560
1581
  let accessors = [{
1561
- prefix: targetName + ".type",
1582
+ prefix: `${targetName}.type`,
1562
1583
  def: targetDef
1563
1584
  }];
1564
1585
  for (let i = 0; i < parts.length; i++) {
@@ -1566,17 +1587,17 @@ else targetValue = "true";
1566
1587
  for (const { prefix, def } of accessors) {
1567
1588
  const results = this.buildPropPaths(def, parts[i]);
1568
1589
  if (results.length > 0) for (const result of results) if (i < parts.length - 1) nextAccessors.push({
1569
- prefix: prefix + result.path + "?.type",
1590
+ prefix: `${prefix}${result.path}?.type`,
1570
1591
  def: result.propDef
1571
1592
  });
1572
1593
  else nextAccessors.push({
1573
- prefix: prefix + result.path + "?",
1594
+ prefix: `${prefix}${result.path}?`,
1574
1595
  def: result.propDef
1575
1596
  });
1576
1597
  else {
1577
- const suffix = `.props.get("${escapeQuotes(parts[i])}")` + (i < parts.length - 1 ? "?.type" : "?");
1598
+ const suffix = `.props.get("${escapeQuotes(parts[i])}")${i < parts.length - 1 ? "?.type" : "?"}`;
1578
1599
  nextAccessors.push({
1579
- prefix: prefix + suffix,
1600
+ prefix: `${prefix}${suffix}`,
1580
1601
  def: undefined
1581
1602
  });
1582
1603
  }
@@ -1631,9 +1652,9 @@ function resolveJsonSchemaMode(opts) {
1631
1652
  }
1632
1653
  const tsPlugin = (opts) => {
1633
1654
  return {
1634
- name: "typesccript",
1655
+ name: "typescript",
1635
1656
  render(doc, format) {
1636
- if (format === "dts") return [{
1657
+ if (format === "dts" || format === DEFAULT_FORMAT) return [{
1637
1658
  fileName: `${doc.name}.d.ts`,
1638
1659
  content: new TypeRenderer(doc, opts).render()
1639
1660
  }];
@@ -1643,19 +1664,19 @@ const tsPlugin = (opts) => {
1643
1664
  }];
1644
1665
  },
1645
1666
  async buildEnd(output, format, repo) {
1646
- if (format === "dts") {
1667
+ if (format === "dts" || format === DEFAULT_FORMAT) {
1647
1668
  const annotations = await repo.getUsedAnnotations();
1648
1669
  const tags = await repo.getPrimitivesTags() || new Set();
1649
- let rendered = [];
1670
+ const rendered = [];
1650
1671
  for (const [key, val] of Object.entries(annotations)) {
1651
1672
  const multiple = val.multiple;
1652
- let typeLine = Array.from(val.types).map((t) => {
1673
+ const typeLine = Array.from(val.types).map((t) => {
1653
1674
  if (t.type === "object") return `{ ${Object.entries(t.props).map(([k, v]) => `${wrapProp(k)}${v.optional ? "?" : ""}: ${v.type}`).join(", ")} }`;
1654
1675
  else return t.optional ? `${t.type} | true` : t.type;
1655
1676
  }).join(" | ");
1656
1677
  rendered.push(`${wrapProp(key)}: ${multiple ? "(" : ""}${typeLine}${multiple ? ")[]" : ""}`);
1657
1678
  }
1658
- let renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
1679
+ const renderedTags = Array.from(tags).map((f) => `"${escapeQuotes(f)}"`).join(" | ");
1659
1680
  output.push({
1660
1681
  content: "// prettier-ignore-start\n/* eslint-disable */\n/* oxlint-disable */\n/**\n * 🪄 This file was generated by Atscript\n * It is generated based on annotations used in this project\n * Do not edit this file!\n *\n * Use `npx asc -f dts` command to re-generate this file\n */\nexport {}\n\ndeclare global {\n interface AtscriptMetadata {\n " + rendered.join("\n ") + "\n }\n" + " type AtscriptPrimitiveTags = " + renderedTags + "\n" + "}\n" + "// prettier-ignore-end",
1661
1682
  fileName: "atscript.d.ts",
package/dist/utils.cjs CHANGED
@@ -140,7 +140,7 @@ var Validator = class {
140
140
  }
141
141
  let i = 0;
142
142
  for (const item of def.type.items) {
143
- this.push(`[${i}]`);
143
+ this.push(String(i));
144
144
  if (!this.validateSafe(item, value[i])) {
145
145
  this.pop(true);
146
146
  return false;
@@ -176,7 +176,7 @@ var Validator = class {
176
176
  let i = 0;
177
177
  let passed = true;
178
178
  for (const item of value) {
179
- this.push(`[${i}]`);
179
+ this.push(String(i));
180
180
  if (!this.validateSafe(def.type.of, item)) {
181
181
  passed = false;
182
182
  this.pop(true);
@@ -228,7 +228,7 @@ else {
228
228
  pattern,
229
229
  def: propDef
230
230
  });
231
- if (matched.length) {
231
+ if (matched.length > 0) {
232
232
  let keyPassed = false;
233
233
  for (const { def: def$1 } of matched) if (this.validateSafe(def$1, value[key])) {
234
234
  this.pop(false);
@@ -255,7 +255,7 @@ else {
255
255
  return passed;
256
256
  }
257
257
  validatePrimitive(def, value) {
258
- if (typeof def.type.value !== "undefined") {
258
+ if (def.type.value !== undefined) {
259
259
  if (value !== def.type.value) {
260
260
  this.error(`Expected ${def.type.value}, got ${value}`);
261
261
  return false;
@@ -264,40 +264,46 @@ else {
264
264
  }
265
265
  const typeOfValue = Array.isArray(value) ? "array" : typeof value;
266
266
  switch (def.type.designType) {
267
- case "never":
267
+ case "never": {
268
268
  this.error(`This type is impossible, must be an internal problem`);
269
269
  return false;
270
+ }
270
271
  case "any": return true;
271
- case "string":
272
+ case "string": {
272
273
  if (typeOfValue !== def.type.designType) {
273
274
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
274
275
  return false;
275
276
  }
276
277
  return this.validateString(def, value);
277
- case "number":
278
+ }
279
+ case "number": {
278
280
  if (typeOfValue !== def.type.designType) {
279
281
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
280
282
  return false;
281
283
  }
282
284
  return this.validateNumber(def, value);
283
- case "boolean":
285
+ }
286
+ case "boolean": {
284
287
  if (typeOfValue !== def.type.designType) {
285
288
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
286
289
  return false;
287
290
  }
288
291
  return this.validateBoolean(def, value);
289
- case "undefined":
292
+ }
293
+ case "undefined": {
290
294
  if (value !== undefined) {
291
295
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
292
296
  return false;
293
297
  }
294
298
  return true;
295
- case "null":
299
+ }
300
+ case "null": {
296
301
  if (value !== null) {
297
302
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
298
303
  return false;
299
304
  }
300
305
  return true;
306
+ }
301
307
  default: throw new Error(`Unknown type "${def.type.designType}"`);
302
308
  }
303
309
  }
@@ -565,7 +571,7 @@ function buildJsonSchema(type) {
565
571
  type: "object",
566
572
  properties
567
573
  };
568
- if (required.length) schema.required = required;
574
+ if (required.length > 0) schema.required = required;
569
575
  return schema;
570
576
  },
571
577
  array(d) {
@@ -742,28 +748,32 @@ else flatUnion.item(existing);
742
748
  }
743
749
  case "union":
744
750
  case "intersection":
745
- case "tuple":
751
+ case "tuple": {
746
752
  for (const item of def.type.items) flattenArray(item, name);
747
753
  break;
748
- case "array":
754
+ }
755
+ case "array": {
749
756
  flattenArray(def.type.of, name);
750
757
  break;
758
+ }
751
759
  default:
752
760
  }
753
761
  }
754
762
  function flattenType(def, prefix = "", inComplexTypeOrArray = false) {
755
763
  switch (def.type.kind) {
756
- case "object":
764
+ case "object": {
757
765
  addFieldToFlatMap(prefix || "", def);
758
766
  for (const [key, value] of def.type.props.entries()) {
759
767
  if (skipPhantom && isPhantomType(value)) continue;
760
768
  flattenType(value, prefix ? `${prefix}.${key}` : key, inComplexTypeOrArray);
761
769
  }
762
770
  break;
771
+ }
763
772
  case "array": {
764
773
  let typeArray = def;
765
774
  if (!inComplexTypeOrArray) {
766
775
  typeArray = defineAnnotatedType().refTo(def).copyMetadata(def.metadata).$type;
776
+ if (def.optional) typeArray.optional = def.optional;
767
777
  if (options?.topLevelArrayTag) typeArray.metadata.set(options.topLevelArrayTag, true);
768
778
  }
769
779
  addFieldToFlatMap(prefix || "", typeArray);
@@ -772,10 +782,19 @@ else flatUnion.item(existing);
772
782
  }
773
783
  case "intersection":
774
784
  case "tuple":
775
- case "union": for (const item of def.type.items) flattenType(item, prefix, true);
776
- default:
785
+ case "union": {
786
+ for (const item of def.type.items) flattenType(item, prefix, true);
777
787
  addFieldToFlatMap(prefix || "", def);
788
+ if (def.optional) {
789
+ const entry = flatMap.get(prefix || "");
790
+ if (entry) entry.optional = def.optional;
791
+ }
778
792
  break;
793
+ }
794
+ default: {
795
+ addFieldToFlatMap(prefix || "", def);
796
+ break;
797
+ }
779
798
  }
780
799
  if (prefix) options?.onField?.(prefix, def, def.metadata);
781
800
  }
package/dist/utils.d.ts CHANGED
@@ -119,10 +119,10 @@ interface TAtscriptTypeArray<DataType = unknown[]> {
119
119
  interface TAtscriptTypeObject<K extends string = string, DataType = Record<K, unknown>> {
120
120
  kind: 'object';
121
121
  props: Map<K, TAtscriptAnnotatedType>;
122
- propsPatterns: {
122
+ propsPatterns: Array<{
123
123
  pattern: RegExp;
124
124
  def: TAtscriptAnnotatedType;
125
- }[];
125
+ }>;
126
126
  tags: Set<AtscriptPrimitiveTags>;
127
127
  /** @internal phantom — carries the DataType at the type level, never set at runtime */
128
128
  __dataType?: DataType;
@@ -176,7 +176,7 @@ declare function isAnnotatedType(type: any): type is TAtscriptAnnotatedType;
176
176
  * Standalone annotate function that handles both replace and append (array) strategies.
177
177
  * Used by the handle's .annotate() method and by generated mutation statements.
178
178
  */
179
- declare function annotate<K extends keyof AtscriptMetadata>(metadata: TMetadataMap<AtscriptMetadata> | undefined, key: K, value: AtscriptMetadata[K] extends (infer E)[] ? E : AtscriptMetadata[K], asArray?: boolean): void;
179
+ declare function annotate<K extends keyof AtscriptMetadata>(metadata: TMetadataMap<AtscriptMetadata> | undefined, key: K, value: AtscriptMetadata[K] extends Array<infer E> ? E : AtscriptMetadata[K], asArray?: boolean): void;
180
180
  type TKind = '' | 'array' | 'object' | 'union' | 'intersection' | 'tuple';
181
181
  /**
182
182
  * Creates a builder handle for constructing a {@link TAtscriptAnnotatedType} at runtime.
@@ -368,13 +368,13 @@ interface TSerializedTypeFinal {
368
368
  interface TSerializedTypeObject {
369
369
  kind: 'object';
370
370
  props: Record<string, TSerializedAnnotatedTypeInner>;
371
- propsPatterns: {
371
+ propsPatterns: Array<{
372
372
  pattern: {
373
373
  source: string;
374
374
  flags: string;
375
375
  };
376
376
  def: TSerializedAnnotatedTypeInner;
377
- }[];
377
+ }>;
378
378
  tags: string[];
379
379
  }
380
380
  interface TSerializedTypeArray {
package/dist/utils.mjs CHANGED
@@ -139,7 +139,7 @@ var Validator = class {
139
139
  }
140
140
  let i = 0;
141
141
  for (const item of def.type.items) {
142
- this.push(`[${i}]`);
142
+ this.push(String(i));
143
143
  if (!this.validateSafe(item, value[i])) {
144
144
  this.pop(true);
145
145
  return false;
@@ -175,7 +175,7 @@ var Validator = class {
175
175
  let i = 0;
176
176
  let passed = true;
177
177
  for (const item of value) {
178
- this.push(`[${i}]`);
178
+ this.push(String(i));
179
179
  if (!this.validateSafe(def.type.of, item)) {
180
180
  passed = false;
181
181
  this.pop(true);
@@ -227,7 +227,7 @@ else {
227
227
  pattern,
228
228
  def: propDef
229
229
  });
230
- if (matched.length) {
230
+ if (matched.length > 0) {
231
231
  let keyPassed = false;
232
232
  for (const { def: def$1 } of matched) if (this.validateSafe(def$1, value[key])) {
233
233
  this.pop(false);
@@ -254,7 +254,7 @@ else {
254
254
  return passed;
255
255
  }
256
256
  validatePrimitive(def, value) {
257
- if (typeof def.type.value !== "undefined") {
257
+ if (def.type.value !== undefined) {
258
258
  if (value !== def.type.value) {
259
259
  this.error(`Expected ${def.type.value}, got ${value}`);
260
260
  return false;
@@ -263,40 +263,46 @@ else {
263
263
  }
264
264
  const typeOfValue = Array.isArray(value) ? "array" : typeof value;
265
265
  switch (def.type.designType) {
266
- case "never":
266
+ case "never": {
267
267
  this.error(`This type is impossible, must be an internal problem`);
268
268
  return false;
269
+ }
269
270
  case "any": return true;
270
- case "string":
271
+ case "string": {
271
272
  if (typeOfValue !== def.type.designType) {
272
273
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
273
274
  return false;
274
275
  }
275
276
  return this.validateString(def, value);
276
- case "number":
277
+ }
278
+ case "number": {
277
279
  if (typeOfValue !== def.type.designType) {
278
280
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
279
281
  return false;
280
282
  }
281
283
  return this.validateNumber(def, value);
282
- case "boolean":
284
+ }
285
+ case "boolean": {
283
286
  if (typeOfValue !== def.type.designType) {
284
287
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
285
288
  return false;
286
289
  }
287
290
  return this.validateBoolean(def, value);
288
- case "undefined":
291
+ }
292
+ case "undefined": {
289
293
  if (value !== undefined) {
290
294
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
291
295
  return false;
292
296
  }
293
297
  return true;
294
- case "null":
298
+ }
299
+ case "null": {
295
300
  if (value !== null) {
296
301
  this.error(`Expected ${def.type.designType}, got ${typeOfValue}`);
297
302
  return false;
298
303
  }
299
304
  return true;
305
+ }
300
306
  default: throw new Error(`Unknown type "${def.type.designType}"`);
301
307
  }
302
308
  }
@@ -564,7 +570,7 @@ function buildJsonSchema(type) {
564
570
  type: "object",
565
571
  properties
566
572
  };
567
- if (required.length) schema.required = required;
573
+ if (required.length > 0) schema.required = required;
568
574
  return schema;
569
575
  },
570
576
  array(d) {
@@ -741,28 +747,32 @@ else flatUnion.item(existing);
741
747
  }
742
748
  case "union":
743
749
  case "intersection":
744
- case "tuple":
750
+ case "tuple": {
745
751
  for (const item of def.type.items) flattenArray(item, name);
746
752
  break;
747
- case "array":
753
+ }
754
+ case "array": {
748
755
  flattenArray(def.type.of, name);
749
756
  break;
757
+ }
750
758
  default:
751
759
  }
752
760
  }
753
761
  function flattenType(def, prefix = "", inComplexTypeOrArray = false) {
754
762
  switch (def.type.kind) {
755
- case "object":
763
+ case "object": {
756
764
  addFieldToFlatMap(prefix || "", def);
757
765
  for (const [key, value] of def.type.props.entries()) {
758
766
  if (skipPhantom && isPhantomType(value)) continue;
759
767
  flattenType(value, prefix ? `${prefix}.${key}` : key, inComplexTypeOrArray);
760
768
  }
761
769
  break;
770
+ }
762
771
  case "array": {
763
772
  let typeArray = def;
764
773
  if (!inComplexTypeOrArray) {
765
774
  typeArray = defineAnnotatedType().refTo(def).copyMetadata(def.metadata).$type;
775
+ if (def.optional) typeArray.optional = def.optional;
766
776
  if (options?.topLevelArrayTag) typeArray.metadata.set(options.topLevelArrayTag, true);
767
777
  }
768
778
  addFieldToFlatMap(prefix || "", typeArray);
@@ -771,10 +781,19 @@ else flatUnion.item(existing);
771
781
  }
772
782
  case "intersection":
773
783
  case "tuple":
774
- case "union": for (const item of def.type.items) flattenType(item, prefix, true);
775
- default:
784
+ case "union": {
785
+ for (const item of def.type.items) flattenType(item, prefix, true);
776
786
  addFieldToFlatMap(prefix || "", def);
787
+ if (def.optional) {
788
+ const entry = flatMap.get(prefix || "");
789
+ if (entry) entry.optional = def.optional;
790
+ }
777
791
  break;
792
+ }
793
+ default: {
794
+ addFieldToFlatMap(prefix || "", def);
795
+ break;
796
+ }
778
797
  }
779
798
  if (prefix) options?.onField?.(prefix, def, def.metadata);
780
799
  }