@atscript/typescript 0.1.7 → 0.1.9

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
@@ -690,6 +690,76 @@ function fromJsonSchema(schema) {
690
690
  return convert(schema);
691
691
  }
692
692
 
693
+ //#endregion
694
+ //#region packages/typescript/src/flatten.ts
695
+ function flattenAnnotatedType(type, options) {
696
+ const flatMap = new Map();
697
+ const skipPhantom = !!options?.excludePhantomTypes;
698
+ function addFieldToFlatMap(name, def) {
699
+ const existing = flatMap.get(name);
700
+ if (existing) {
701
+ const flatUnion = defineAnnotatedType("union").copyMetadata(existing.metadata).copyMetadata(def.metadata);
702
+ if (existing.__flat_union) existing.type.items.forEach((item) => flatUnion.item(item));
703
+ else flatUnion.item(existing);
704
+ flatUnion.item(def);
705
+ const unionType = flatUnion.$type;
706
+ unionType.__flat_union = true;
707
+ flatMap.set(name, flatUnion.$type);
708
+ } else flatMap.set(name, def);
709
+ }
710
+ function flattenArray(def, name) {
711
+ switch (def.type.kind) {
712
+ case "object": {
713
+ const items = Array.from(def.type.props.entries());
714
+ for (const [key, value] of items) {
715
+ if (skipPhantom && isPhantomType(value)) continue;
716
+ flattenType(value, name ? `${name}.${key}` : key, true);
717
+ }
718
+ break;
719
+ }
720
+ case "union":
721
+ case "intersection":
722
+ case "tuple":
723
+ for (const item of def.type.items) flattenArray(item, name);
724
+ break;
725
+ case "array":
726
+ flattenArray(def.type.of, name);
727
+ break;
728
+ default:
729
+ }
730
+ }
731
+ function flattenType(def, prefix = "", inComplexTypeOrArray = false) {
732
+ switch (def.type.kind) {
733
+ case "object":
734
+ addFieldToFlatMap(prefix || "", def);
735
+ for (const [key, value] of def.type.props.entries()) {
736
+ if (skipPhantom && isPhantomType(value)) continue;
737
+ flattenType(value, prefix ? `${prefix}.${key}` : key, inComplexTypeOrArray);
738
+ }
739
+ break;
740
+ case "array": {
741
+ let typeArray = def;
742
+ if (!inComplexTypeOrArray) {
743
+ typeArray = defineAnnotatedType().refTo(def).copyMetadata(def.metadata).$type;
744
+ if (options?.topLevelArrayTag) typeArray.metadata.set(options.topLevelArrayTag, true);
745
+ }
746
+ addFieldToFlatMap(prefix || "", typeArray);
747
+ if (!isAnnotatedTypeOfPrimitive(typeArray.type.of)) flattenArray(typeArray.type.of, prefix);
748
+ break;
749
+ }
750
+ case "intersection":
751
+ case "tuple":
752
+ case "union": for (const item of def.type.items) flattenType(item, prefix, true);
753
+ default:
754
+ addFieldToFlatMap(prefix || "", def);
755
+ break;
756
+ }
757
+ if (prefix) options?.onField?.(prefix, def, def.metadata);
758
+ }
759
+ flattenType(type);
760
+ return flatMap;
761
+ }
762
+
693
763
  //#endregion
694
764
  //#region packages/typescript/src/serialize.ts
695
765
  const SERIALIZE_VERSION = 1;
@@ -726,10 +796,7 @@ function serializeTypeDef(def, path, options) {
726
796
  },
727
797
  object(d) {
728
798
  const props = {};
729
- for (const [key, val] of d.type.props.entries()) {
730
- if (isPhantomType(val)) continue;
731
- props[key] = serializeNode(val, [...path, key], options);
732
- }
799
+ for (const [key, val] of d.type.props.entries()) props[key] = serializeNode(val, [...path, key], options);
733
800
  const propsPatterns = d.type.propsPatterns.map((pp) => ({
734
801
  pattern: {
735
802
  source: pp.pattern.source,
@@ -862,6 +929,7 @@ exports.annotate = annotate
862
929
  exports.buildJsonSchema = buildJsonSchema
863
930
  exports.defineAnnotatedType = defineAnnotatedType
864
931
  exports.deserializeAnnotatedType = deserializeAnnotatedType
932
+ exports.flattenAnnotatedType = flattenAnnotatedType
865
933
  exports.forAnnotatedType = forAnnotatedType
866
934
  exports.fromJsonSchema = fromJsonSchema
867
935
  exports.isAnnotatedType = isAnnotatedType
package/dist/utils.d.ts CHANGED
@@ -302,6 +302,47 @@ declare function forAnnotatedType<R>(def: TAtscriptAnnotatedType, handlers: {
302
302
  phantom?: (def: TAtscriptAnnotatedType<TAtscriptTypeFinal>) => R;
303
303
  }): R;
304
304
 
305
+ /**
306
+ * Options for controlling the flattening process.
307
+ */
308
+ interface TFlattenOptions {
309
+ /**
310
+ * Called for each field (with a non-empty path prefix) after it has been added to the flat map.
311
+ * Use this to inspect field type and metadata for domain-specific logic (e.g. index extraction).
312
+ */
313
+ onField?: (path: string, type: TAtscriptAnnotatedType, metadata: TMetadataMap<AtscriptMetadata>) => void;
314
+ /**
315
+ * When set, top-level array fields get this metadata key set to `true`.
316
+ * For example, `'mongo.__topLevelArray'` marks arrays that are direct collection fields.
317
+ * Omit to skip tagging.
318
+ */
319
+ topLevelArrayTag?: string;
320
+ /**
321
+ * Whether to exclude phantom types from the flat map.
322
+ * When `true`, phantom-typed properties are skipped during traversal.
323
+ * By default phantom types are included.
324
+ */
325
+ excludePhantomTypes?: boolean;
326
+ }
327
+ /**
328
+ * Flattens an annotated object type into a map of dot-separated paths to their annotated types.
329
+ *
330
+ * For an object like `{ address: { street: string, city: string } }`, the result contains:
331
+ * - `''` → the root object type
332
+ * - `'address'` → the address object type
333
+ * - `'address.street'` → string type
334
+ * - `'address.city'` → string type
335
+ *
336
+ * Arrays are recursed into (their element types are flattened with the same prefix).
337
+ * Unions/intersections/tuples are recursed into (each branch contributes to the same path,
338
+ * merging via synthetic union types when paths collide).
339
+ *
340
+ * @param type - The root annotated type (must be an object type).
341
+ * @param options - Optional hooks for domain-specific processing.
342
+ * @returns A map of dot-separated field paths to their annotated types.
343
+ */
344
+ declare function flattenAnnotatedType(type: TAtscriptAnnotatedType<TAtscriptTypeObject>, options?: TFlattenOptions): Map<string, TAtscriptAnnotatedType>;
345
+
305
346
  /** Current serialization format version. Bumped on breaking changes to the serialized shape. */
306
347
  declare const SERIALIZE_VERSION = 1;
307
348
  /** Top-level serialized annotated type. JSON-safe representation of a {@link TAtscriptAnnotatedType}. */
@@ -408,5 +449,5 @@ declare function serializeAnnotatedType(type: TAtscriptAnnotatedType, options?:
408
449
  */
409
450
  declare function deserializeAnnotatedType(data: TSerializedAnnotatedType): TAtscriptAnnotatedType;
410
451
 
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 };
452
+ export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, flattenAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, serializeAnnotatedType };
453
+ 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
@@ -689,6 +689,76 @@ function fromJsonSchema(schema) {
689
689
  return convert(schema);
690
690
  }
691
691
 
692
+ //#endregion
693
+ //#region packages/typescript/src/flatten.ts
694
+ function flattenAnnotatedType(type, options) {
695
+ const flatMap = new Map();
696
+ const skipPhantom = !!options?.excludePhantomTypes;
697
+ function addFieldToFlatMap(name, def) {
698
+ const existing = flatMap.get(name);
699
+ if (existing) {
700
+ const flatUnion = defineAnnotatedType("union").copyMetadata(existing.metadata).copyMetadata(def.metadata);
701
+ if (existing.__flat_union) existing.type.items.forEach((item) => flatUnion.item(item));
702
+ else flatUnion.item(existing);
703
+ flatUnion.item(def);
704
+ const unionType = flatUnion.$type;
705
+ unionType.__flat_union = true;
706
+ flatMap.set(name, flatUnion.$type);
707
+ } else flatMap.set(name, def);
708
+ }
709
+ function flattenArray(def, name) {
710
+ switch (def.type.kind) {
711
+ case "object": {
712
+ const items = Array.from(def.type.props.entries());
713
+ for (const [key, value] of items) {
714
+ if (skipPhantom && isPhantomType(value)) continue;
715
+ flattenType(value, name ? `${name}.${key}` : key, true);
716
+ }
717
+ break;
718
+ }
719
+ case "union":
720
+ case "intersection":
721
+ case "tuple":
722
+ for (const item of def.type.items) flattenArray(item, name);
723
+ break;
724
+ case "array":
725
+ flattenArray(def.type.of, name);
726
+ break;
727
+ default:
728
+ }
729
+ }
730
+ function flattenType(def, prefix = "", inComplexTypeOrArray = false) {
731
+ switch (def.type.kind) {
732
+ case "object":
733
+ addFieldToFlatMap(prefix || "", def);
734
+ for (const [key, value] of def.type.props.entries()) {
735
+ if (skipPhantom && isPhantomType(value)) continue;
736
+ flattenType(value, prefix ? `${prefix}.${key}` : key, inComplexTypeOrArray);
737
+ }
738
+ break;
739
+ case "array": {
740
+ let typeArray = def;
741
+ if (!inComplexTypeOrArray) {
742
+ typeArray = defineAnnotatedType().refTo(def).copyMetadata(def.metadata).$type;
743
+ if (options?.topLevelArrayTag) typeArray.metadata.set(options.topLevelArrayTag, true);
744
+ }
745
+ addFieldToFlatMap(prefix || "", typeArray);
746
+ if (!isAnnotatedTypeOfPrimitive(typeArray.type.of)) flattenArray(typeArray.type.of, prefix);
747
+ break;
748
+ }
749
+ case "intersection":
750
+ case "tuple":
751
+ case "union": for (const item of def.type.items) flattenType(item, prefix, true);
752
+ default:
753
+ addFieldToFlatMap(prefix || "", def);
754
+ break;
755
+ }
756
+ if (prefix) options?.onField?.(prefix, def, def.metadata);
757
+ }
758
+ flattenType(type);
759
+ return flatMap;
760
+ }
761
+
692
762
  //#endregion
693
763
  //#region packages/typescript/src/serialize.ts
694
764
  const SERIALIZE_VERSION = 1;
@@ -725,10 +795,7 @@ function serializeTypeDef(def, path, options) {
725
795
  },
726
796
  object(d) {
727
797
  const props = {};
728
- for (const [key, val] of d.type.props.entries()) {
729
- if (isPhantomType(val)) continue;
730
- props[key] = serializeNode(val, [...path, key], options);
731
- }
798
+ for (const [key, val] of d.type.props.entries()) props[key] = serializeNode(val, [...path, key], options);
732
799
  const propsPatterns = d.type.propsPatterns.map((pp) => ({
733
800
  pattern: {
734
801
  source: pp.pattern.source,
@@ -854,4 +921,4 @@ function deserializeTypeDef(t) {
854
921
  }
855
922
 
856
923
  //#endregion
857
- export { SERIALIZE_VERSION, Validator, ValidatorError, annotate, buildJsonSchema, defineAnnotatedType, deserializeAnnotatedType, forAnnotatedType, fromJsonSchema, isAnnotatedType, isAnnotatedTypeOfPrimitive, isPhantomType, serializeAnnotatedType };
924
+ 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.7",
3
+ "version": "0.1.9",
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.7"
73
+ "@atscript/core": "^0.1.9"
74
74
  },
75
75
  "dependencies": {
76
76
  "@moostjs/event-cli": "^0.5.32",