@atscript/typescript 0.1.8 → 0.1.10

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/cli.cjs CHANGED
@@ -519,12 +519,14 @@ var Validator = class {
519
519
  * @param safe - If `true`, returns `false` on failure instead of throwing.
520
520
  * @returns `true` if the value matches the type definition.
521
521
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
522
- */ validate(value, safe) {
522
+ */ validate(value, safe, context) {
523
523
  this.push("");
524
524
  this.errors = [];
525
525
  this.stackErrors = [];
526
+ this.context = context;
526
527
  const passed = this.validateSafe(this.def, value);
527
528
  this.pop(!passed);
529
+ this.context = undefined;
528
530
  if (!passed) {
529
531
  if (safe) return false;
530
532
  this.throw();
@@ -814,6 +816,7 @@ else {
814
816
  /** Validation errors collected during the last {@link validate} call. */ _define_property$2(this, "errors", void 0);
815
817
  _define_property$2(this, "stackErrors", void 0);
816
818
  _define_property$2(this, "stackPath", void 0);
819
+ _define_property$2(this, "context", void 0);
817
820
  this.def = def;
818
821
  this.errors = [];
819
822
  this.stackErrors = [];
package/dist/index.cjs CHANGED
@@ -516,12 +516,14 @@ var Validator = class {
516
516
  * @param safe - If `true`, returns `false` on failure instead of throwing.
517
517
  * @returns `true` if the value matches the type definition.
518
518
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
519
- */ validate(value, safe) {
519
+ */ validate(value, safe, context) {
520
520
  this.push("");
521
521
  this.errors = [];
522
522
  this.stackErrors = [];
523
+ this.context = context;
523
524
  const passed = this.validateSafe(this.def, value);
524
525
  this.pop(!passed);
526
+ this.context = undefined;
525
527
  if (!passed) {
526
528
  if (safe) return false;
527
529
  this.throw();
@@ -811,6 +813,7 @@ else {
811
813
  /** Validation errors collected during the last {@link validate} call. */ _define_property$1(this, "errors", void 0);
812
814
  _define_property$1(this, "stackErrors", void 0);
813
815
  _define_property$1(this, "stackPath", void 0);
816
+ _define_property$1(this, "context", void 0);
814
817
  this.def = def;
815
818
  this.errors = [];
816
819
  this.stackErrors = [];
package/dist/index.mjs CHANGED
@@ -492,12 +492,14 @@ var Validator = class {
492
492
  * @param safe - If `true`, returns `false` on failure instead of throwing.
493
493
  * @returns `true` if the value matches the type definition.
494
494
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
495
- */ validate(value, safe) {
495
+ */ validate(value, safe, context) {
496
496
  this.push("");
497
497
  this.errors = [];
498
498
  this.stackErrors = [];
499
+ this.context = context;
499
500
  const passed = this.validateSafe(this.def, value);
500
501
  this.pop(!passed);
502
+ this.context = undefined;
501
503
  if (!passed) {
502
504
  if (safe) return false;
503
505
  this.throw();
@@ -787,6 +789,7 @@ else {
787
789
  /** Validation errors collected during the last {@link validate} call. */ _define_property$1(this, "errors", void 0);
788
790
  _define_property$1(this, "stackErrors", void 0);
789
791
  _define_property$1(this, "stackPath", void 0);
792
+ _define_property$1(this, "context", void 0);
790
793
  this.def = def;
791
794
  this.errors = [];
792
795
  this.stackErrors = [];
package/dist/utils.cjs CHANGED
@@ -72,12 +72,14 @@ var Validator = class {
72
72
  * @param safe - If `true`, returns `false` on failure instead of throwing.
73
73
  * @returns `true` if the value matches the type definition.
74
74
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
75
- */ validate(value, safe) {
75
+ */ validate(value, safe, context) {
76
76
  this.push("");
77
77
  this.errors = [];
78
78
  this.stackErrors = [];
79
+ this.context = context;
79
80
  const passed = this.validateSafe(this.def, value);
80
81
  this.pop(!passed);
82
+ this.context = undefined;
81
83
  if (!passed) {
82
84
  if (safe) return false;
83
85
  this.throw();
@@ -367,6 +369,7 @@ else {
367
369
  /** Validation errors collected during the last {@link validate} call. */ _define_property(this, "errors", void 0);
368
370
  _define_property(this, "stackErrors", void 0);
369
371
  _define_property(this, "stackPath", void 0);
372
+ _define_property(this, "context", void 0);
370
373
  this.def = def;
371
374
  this.errors = [];
372
375
  this.stackErrors = [];
@@ -690,6 +693,76 @@ function fromJsonSchema(schema) {
690
693
  return convert(schema);
691
694
  }
692
695
 
696
+ //#endregion
697
+ //#region packages/typescript/src/flatten.ts
698
+ function flattenAnnotatedType(type, options) {
699
+ const flatMap = new Map();
700
+ const skipPhantom = !!options?.excludePhantomTypes;
701
+ function addFieldToFlatMap(name, def) {
702
+ const existing = flatMap.get(name);
703
+ if (existing) {
704
+ const flatUnion = defineAnnotatedType("union").copyMetadata(existing.metadata).copyMetadata(def.metadata);
705
+ if (existing.__flat_union) existing.type.items.forEach((item) => flatUnion.item(item));
706
+ else flatUnion.item(existing);
707
+ flatUnion.item(def);
708
+ const unionType = flatUnion.$type;
709
+ unionType.__flat_union = true;
710
+ flatMap.set(name, flatUnion.$type);
711
+ } else flatMap.set(name, def);
712
+ }
713
+ function flattenArray(def, name) {
714
+ switch (def.type.kind) {
715
+ case "object": {
716
+ const items = Array.from(def.type.props.entries());
717
+ for (const [key, value] of items) {
718
+ if (skipPhantom && isPhantomType(value)) continue;
719
+ flattenType(value, name ? `${name}.${key}` : key, true);
720
+ }
721
+ break;
722
+ }
723
+ case "union":
724
+ case "intersection":
725
+ case "tuple":
726
+ for (const item of def.type.items) flattenArray(item, name);
727
+ break;
728
+ case "array":
729
+ flattenArray(def.type.of, name);
730
+ break;
731
+ default:
732
+ }
733
+ }
734
+ function flattenType(def, prefix = "", inComplexTypeOrArray = false) {
735
+ switch (def.type.kind) {
736
+ case "object":
737
+ addFieldToFlatMap(prefix || "", def);
738
+ for (const [key, value] of def.type.props.entries()) {
739
+ if (skipPhantom && isPhantomType(value)) continue;
740
+ flattenType(value, prefix ? `${prefix}.${key}` : key, inComplexTypeOrArray);
741
+ }
742
+ break;
743
+ case "array": {
744
+ let typeArray = def;
745
+ if (!inComplexTypeOrArray) {
746
+ typeArray = defineAnnotatedType().refTo(def).copyMetadata(def.metadata).$type;
747
+ if (options?.topLevelArrayTag) typeArray.metadata.set(options.topLevelArrayTag, true);
748
+ }
749
+ addFieldToFlatMap(prefix || "", typeArray);
750
+ if (!isAnnotatedTypeOfPrimitive(typeArray.type.of)) flattenArray(typeArray.type.of, prefix);
751
+ break;
752
+ }
753
+ case "intersection":
754
+ case "tuple":
755
+ case "union": for (const item of def.type.items) flattenType(item, prefix, true);
756
+ default:
757
+ addFieldToFlatMap(prefix || "", def);
758
+ break;
759
+ }
760
+ if (prefix) options?.onField?.(prefix, def, def.metadata);
761
+ }
762
+ flattenType(type);
763
+ return flatMap;
764
+ }
765
+
693
766
  //#endregion
694
767
  //#region packages/typescript/src/serialize.ts
695
768
  const SERIALIZE_VERSION = 1;
@@ -859,6 +932,7 @@ exports.annotate = annotate
859
932
  exports.buildJsonSchema = buildJsonSchema
860
933
  exports.defineAnnotatedType = defineAnnotatedType
861
934
  exports.deserializeAnnotatedType = deserializeAnnotatedType
935
+ exports.flattenAnnotatedType = flattenAnnotatedType
862
936
  exports.forAnnotatedType = forAnnotatedType
863
937
  exports.fromJsonSchema = fromJsonSchema
864
938
  exports.isAnnotatedType = isAnnotatedType
package/dist/utils.d.ts CHANGED
@@ -25,6 +25,7 @@ interface TValidatorPluginContext {
25
25
  validateAnnotatedType: Validator<any>['validateAnnotatedType'];
26
26
  error: Validator<any>['error'];
27
27
  path: Validator<any>['path'];
28
+ context: unknown;
28
29
  }
29
30
  /**
30
31
  * Validates values against an {@link TAtscriptAnnotatedType} definition.
@@ -59,6 +60,7 @@ declare class Validator<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedTyp
59
60
  errors: TError[];
60
61
  protected stackErrors: TError[][];
61
62
  protected stackPath: string[];
63
+ protected context: unknown;
62
64
  protected isLimitExceeded(): boolean;
63
65
  protected push(name: string): void;
64
66
  protected pop(saveErrors: boolean): TError[] | undefined;
@@ -76,7 +78,7 @@ declare class Validator<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedTyp
76
78
  * @returns `true` if the value matches the type definition.
77
79
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
78
80
  */
79
- validate<TT = DataType>(value: any, safe?: boolean): value is TT;
81
+ validate<TT = DataType>(value: any, safe?: boolean, context?: unknown): value is TT;
80
82
  protected validateSafe(def: TAtscriptAnnotatedType, value: any): boolean;
81
83
  protected get path(): string;
82
84
  protected validateAnnotatedType(def: TAtscriptAnnotatedType, value: any): boolean;
@@ -302,6 +304,47 @@ declare function forAnnotatedType<R>(def: TAtscriptAnnotatedType, handlers: {
302
304
  phantom?: (def: TAtscriptAnnotatedType<TAtscriptTypeFinal>) => R;
303
305
  }): R;
304
306
 
307
+ /**
308
+ * Options for controlling the flattening process.
309
+ */
310
+ interface TFlattenOptions {
311
+ /**
312
+ * Called for each field (with a non-empty path prefix) after it has been added to the flat map.
313
+ * Use this to inspect field type and metadata for domain-specific logic (e.g. index extraction).
314
+ */
315
+ onField?: (path: string, type: TAtscriptAnnotatedType, metadata: TMetadataMap<AtscriptMetadata>) => void;
316
+ /**
317
+ * When set, top-level array fields get this metadata key set to `true`.
318
+ * For example, `'mongo.__topLevelArray'` marks arrays that are direct collection fields.
319
+ * Omit to skip tagging.
320
+ */
321
+ topLevelArrayTag?: string;
322
+ /**
323
+ * Whether to exclude phantom types from the flat map.
324
+ * When `true`, phantom-typed properties are skipped during traversal.
325
+ * By default phantom types are included.
326
+ */
327
+ excludePhantomTypes?: boolean;
328
+ }
329
+ /**
330
+ * Flattens an annotated object type into a map of dot-separated paths to their annotated types.
331
+ *
332
+ * For an object like `{ address: { street: string, city: string } }`, the result contains:
333
+ * - `''` → the root object type
334
+ * - `'address'` → the address object type
335
+ * - `'address.street'` → string type
336
+ * - `'address.city'` → string type
337
+ *
338
+ * Arrays are recursed into (their element types are flattened with the same prefix).
339
+ * Unions/intersections/tuples are recursed into (each branch contributes to the same path,
340
+ * merging via synthetic union types when paths collide).
341
+ *
342
+ * @param type - The root annotated type (must be an object type).
343
+ * @param options - Optional hooks for domain-specific processing.
344
+ * @returns A map of dot-separated field paths to their annotated types.
345
+ */
346
+ declare function flattenAnnotatedType(type: TAtscriptAnnotatedType<TAtscriptTypeObject>, options?: TFlattenOptions): Map<string, TAtscriptAnnotatedType>;
347
+
305
348
  /** Current serialization format version. Bumped on breaking changes to the serialized shape. */
306
349
  declare const SERIALIZE_VERSION = 1;
307
350
  /** Top-level serialized annotated type. JSON-safe representation of a {@link TAtscriptAnnotatedType}. */
@@ -408,5 +451,5 @@ declare function serializeAnnotatedType(type: TAtscriptAnnotatedType, options?:
408
451
  */
409
452
  declare function deserializeAnnotatedType(data: TSerializedAnnotatedType): TAtscriptAnnotatedType;
410
453
 
411
- export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, serializeAnnotatedType };
412
- export type { InferDataType, TAnnotatedTypeHandle, TAtscriptAnnotatedType, TAtscriptAnnotatedTypeConstructor, TAtscriptTypeArray, TAtscriptTypeComplex, TAtscriptTypeDef, TAtscriptTypeFinal, TAtscriptTypeObject, TMetadataMap, TProcessAnnotationContext, TSerializeOptions, TSerializedAnnotatedType, TSerializedAnnotatedTypeInner, TSerializedTypeArray, TSerializedTypeComplex, TSerializedTypeDef, TSerializedTypeFinal, TSerializedTypeObject, TValidatorOptions, TValidatorPlugin, TValidatorPluginContext };
454
+ export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, flattenAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, serializeAnnotatedType };
455
+ export type { InferDataType, TAnnotatedTypeHandle, TAtscriptAnnotatedType, TAtscriptAnnotatedTypeConstructor, TAtscriptTypeArray, TAtscriptTypeComplex, TAtscriptTypeDef, TAtscriptTypeFinal, TAtscriptTypeObject, TFlattenOptions, TMetadataMap, TProcessAnnotationContext, TSerializeOptions, TSerializedAnnotatedType, TSerializedAnnotatedTypeInner, TSerializedTypeArray, TSerializedTypeComplex, TSerializedTypeDef, TSerializedTypeFinal, TSerializedTypeObject, TValidatorOptions, TValidatorPlugin, TValidatorPluginContext };
package/dist/utils.mjs CHANGED
@@ -71,12 +71,14 @@ var Validator = class {
71
71
  * @param safe - If `true`, returns `false` on failure instead of throwing.
72
72
  * @returns `true` if the value matches the type definition.
73
73
  * @throws {ValidatorError} When validation fails and `safe` is not `true`.
74
- */ validate(value, safe) {
74
+ */ validate(value, safe, context) {
75
75
  this.push("");
76
76
  this.errors = [];
77
77
  this.stackErrors = [];
78
+ this.context = context;
78
79
  const passed = this.validateSafe(this.def, value);
79
80
  this.pop(!passed);
81
+ this.context = undefined;
80
82
  if (!passed) {
81
83
  if (safe) return false;
82
84
  this.throw();
@@ -366,6 +368,7 @@ else {
366
368
  /** Validation errors collected during the last {@link validate} call. */ _define_property(this, "errors", void 0);
367
369
  _define_property(this, "stackErrors", void 0);
368
370
  _define_property(this, "stackPath", void 0);
371
+ _define_property(this, "context", void 0);
369
372
  this.def = def;
370
373
  this.errors = [];
371
374
  this.stackErrors = [];
@@ -689,6 +692,76 @@ function fromJsonSchema(schema) {
689
692
  return convert(schema);
690
693
  }
691
694
 
695
+ //#endregion
696
+ //#region packages/typescript/src/flatten.ts
697
+ function flattenAnnotatedType(type, options) {
698
+ const flatMap = new Map();
699
+ const skipPhantom = !!options?.excludePhantomTypes;
700
+ function addFieldToFlatMap(name, def) {
701
+ const existing = flatMap.get(name);
702
+ if (existing) {
703
+ const flatUnion = defineAnnotatedType("union").copyMetadata(existing.metadata).copyMetadata(def.metadata);
704
+ if (existing.__flat_union) existing.type.items.forEach((item) => flatUnion.item(item));
705
+ else flatUnion.item(existing);
706
+ flatUnion.item(def);
707
+ const unionType = flatUnion.$type;
708
+ unionType.__flat_union = true;
709
+ flatMap.set(name, flatUnion.$type);
710
+ } else flatMap.set(name, def);
711
+ }
712
+ function flattenArray(def, name) {
713
+ switch (def.type.kind) {
714
+ case "object": {
715
+ const items = Array.from(def.type.props.entries());
716
+ for (const [key, value] of items) {
717
+ if (skipPhantom && isPhantomType(value)) continue;
718
+ flattenType(value, name ? `${name}.${key}` : key, true);
719
+ }
720
+ break;
721
+ }
722
+ case "union":
723
+ case "intersection":
724
+ case "tuple":
725
+ for (const item of def.type.items) flattenArray(item, name);
726
+ break;
727
+ case "array":
728
+ flattenArray(def.type.of, name);
729
+ break;
730
+ default:
731
+ }
732
+ }
733
+ function flattenType(def, prefix = "", inComplexTypeOrArray = false) {
734
+ switch (def.type.kind) {
735
+ case "object":
736
+ addFieldToFlatMap(prefix || "", def);
737
+ for (const [key, value] of def.type.props.entries()) {
738
+ if (skipPhantom && isPhantomType(value)) continue;
739
+ flattenType(value, prefix ? `${prefix}.${key}` : key, inComplexTypeOrArray);
740
+ }
741
+ break;
742
+ case "array": {
743
+ let typeArray = def;
744
+ if (!inComplexTypeOrArray) {
745
+ typeArray = defineAnnotatedType().refTo(def).copyMetadata(def.metadata).$type;
746
+ if (options?.topLevelArrayTag) typeArray.metadata.set(options.topLevelArrayTag, true);
747
+ }
748
+ addFieldToFlatMap(prefix || "", typeArray);
749
+ if (!isAnnotatedTypeOfPrimitive(typeArray.type.of)) flattenArray(typeArray.type.of, prefix);
750
+ break;
751
+ }
752
+ case "intersection":
753
+ case "tuple":
754
+ case "union": for (const item of def.type.items) flattenType(item, prefix, true);
755
+ default:
756
+ addFieldToFlatMap(prefix || "", def);
757
+ break;
758
+ }
759
+ if (prefix) options?.onField?.(prefix, def, def.metadata);
760
+ }
761
+ flattenType(type);
762
+ return flatMap;
763
+ }
764
+
692
765
  //#endregion
693
766
  //#region packages/typescript/src/serialize.ts
694
767
  const SERIALIZE_VERSION = 1;
@@ -851,4 +924,4 @@ function deserializeTypeDef(t) {
851
924
  }
852
925
 
853
926
  //#endregion
854
- export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, serializeAnnotatedType };
927
+ export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, flattenAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, serializeAnnotatedType };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atscript/typescript",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "Atscript: typescript-gen support.",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",
@@ -70,7 +70,7 @@
70
70
  "homepage": "https://github.com/moostjs/atscript/tree/main/packages/typescript#readme",
71
71
  "license": "ISC",
72
72
  "peerDependencies": {
73
- "@atscript/core": "^0.1.8"
73
+ "@atscript/core": "^0.1.10"
74
74
  },
75
75
  "dependencies": {
76
76
  "@moostjs/event-cli": "^0.5.32",