orange-orm 4.7.10-beta.0 → 4.7.10-beta.2

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/src/map2.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- //map2.d.ts
1
+ //map2.d.ts - Refactored Active Record Methods
2
2
  import type { PGliteOptions } from './pglite.d.ts';
3
3
  import type { ConnectionConfiguration } from 'tedious';
4
4
  import type { D1Database } from '@cloudflare/workers-types';
@@ -98,8 +98,6 @@ export type ColumnFilterType<Val, ColumnType = any> = {
98
98
  in(values: (Val | null | undefined)[]): Filter;
99
99
  between(from: Val | null | undefined, to: Val | null | undefined): Filter;
100
100
  notIn(values: (Val | null | undefined)[]): Filter;
101
- // isNull(): Filter;
102
- // isNotNull(): Filter;
103
101
  } & (ColumnType extends 'string' ? StringOnlyMethods : {});
104
102
 
105
103
  export type JsonArray = Array<JsonValue>;
@@ -209,14 +207,18 @@ type ValidColumnFilterTypes<M extends Record<string, TableDefinition<M>>, K exte
209
207
 
210
208
  // Column selection refs without filter methods - only for getting values/references
211
209
  type ColumnSelectionRefs<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
212
- // Required columns (notNull = true)
213
- [C in keyof M[K]['columns'] as IsRequired<M[K]['columns'][C]> extends true ? C : never]: ColumnTypeToTS<M[K]['columns'][C]>;
214
- } & {
215
- // Optional columns (nullable)
216
- [C in keyof M[K]['columns'] as IsRequired<M[K]['columns'][C]> extends true ? never : C]?: ColumnTypeToTS<M[K]['columns'][C]> | null | undefined;
210
+ [C in keyof M[K]['columns']]: M[K]['columns'][C];
217
211
  };
218
212
 
219
213
 
214
+ // type ColumnSelectionRefs<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
215
+ // // Required columns (notNull = true)
216
+ // [C in keyof M[K]['columns'] as IsRequired<M[K]['columns'][C]> extends true ? C : never]: ColumnTypeToTS<M[K]['columns'][C]>;
217
+ // } & {
218
+ // // Optional columns (nullable)
219
+ // [C in keyof M[K]['columns'] as IsRequired<M[K]['columns'][C]> extends true ? never : C]?: ColumnTypeToTS<M[K]['columns'][C]> | null | undefined;
220
+ // };
221
+
220
222
  // Relation selection refs without filter methods - supports deep nesting
221
223
  // In selectors, all relation types just provide access to the target table structure
222
224
  // But WITHOUT aggregate functions (only available at root level)
@@ -378,9 +380,6 @@ type RequiredColumnKeys<M extends Record<string, TableDefinition<M>>, K extends
378
380
  type OptionalColumnKeys<M extends Record<string, TableDefinition<M>>, K extends keyof M, FS extends Record<string, any>> =
379
381
  Exclude<SelectedColumns<M, K, FS>, RequiredColumnKeys<M, K, FS>>;
380
382
 
381
- // Helper type to check if a value is actually a column reference from the row object
382
- // This is a bit of a hack - we check if the type has the structure of a ColumnFilterType
383
- // but without the filter methods (which is what ColumnSelectionRefs provides)
384
383
  type IsActualColumnReference<T, M extends Record<string, TableDefinition<M>>, K extends keyof M> =
385
384
  T extends ColumnTypeToTS<infer CT>
386
385
  ? CT extends ORMColumnDefinition | ORMJsonColumnDefinition
@@ -388,7 +387,6 @@ type IsActualColumnReference<T, M extends Record<string, TableDefinition<M>>, K
388
387
  : false
389
388
  : false;
390
389
 
391
- // Alternative approach: Check if the type matches what we'd get from accessing ColumnSelectionRefs
392
390
  type IsFromColumnSelectionRefs<M extends Record<string, TableDefinition<M>>, K extends keyof M, T = any> =
393
391
  T extends ColumnSelectionRefs<M, K>[keyof ColumnSelectionRefs<M, K>] ? true :
394
392
  T extends (M[K] extends { relations: infer R }
@@ -401,24 +399,19 @@ type IsFromColumnSelectionRefs<M extends Record<string, TableDefinition<M>>, K e
401
399
  T extends number ? true : // Allow aggregate function return type (number)
402
400
  false;
403
401
 
404
- // Helper type to infer the TypeScript type from selector return values
405
- // Only allows types that come from actual column selections or aggregate functions
406
402
  type InferSelectorReturnType<T, M extends Record<string, TableDefinition<M>>, K extends keyof M> =
407
403
  IsFromColumnSelectionRefs<M, K, T> extends true ? T : never;
408
404
 
409
- // ADD helper to check if return type is an aggregate function:
410
405
  type IsAggregateFunction<T> = T extends BaseAggregateFunction ? true : false;
411
406
 
412
407
  type IsRequiredAggregate<T> = T extends BaseAggregateFunction & { __functionType: infer FType }
413
408
  ? FType extends 'count' | 'sum' | 'avg' ? true : false
414
409
  : false;
415
410
 
416
- // Helper to check if it's a min/max function that should preserve column type
417
411
  type IsMinMaxAggregate<T> = T extends AggregateMinMaxFunction<any> & { __functionType: infer FType }
418
412
  ? FType extends 'max' | 'min' ? true : false
419
413
  : false;
420
414
 
421
- // Helper to extract the column type from min/max aggregate
422
415
  type ExtractMinMaxColumnType<T> = T extends AggregateMinMaxFunction<infer ColType>
423
416
  ? ColumnDefinitionToTS<ColType>
424
417
  : never;
@@ -556,7 +549,9 @@ type UpdateChangesRow<M extends Record<string, TableDefinition<M>>, K extends ke
556
549
  : ColumnTypeToTS<M[K]['columns'][C]> | null | undefined;
557
550
  };
558
551
 
559
- // Active record methods for top-level entities
552
+ // REFACTORED: Separate Active Record Methods for Individual Rows vs Arrays
553
+
554
+ // Active record methods for individual rows
560
555
  type ActiveRecordMethods<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
561
556
  saveChanges(): Promise<void>;
562
557
  saveChanges(concurrency: ConcurrencyConfig<M>[K]): Promise<void>;
@@ -568,18 +563,78 @@ type ActiveRecordMethods<M extends Record<string, TableDefinition<M>>, K extends
568
563
  delete<strategy extends FetchStrategy<M, K>>(strategy: strategy): Promise<void>;
569
564
  };
570
565
 
571
- // Helper type to add active record methods to selection results
566
+ // Active record methods for arrays of rows
567
+ type ArrayActiveRecordMethods<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
568
+ saveChanges(): Promise<void>;
569
+ saveChanges(concurrency: ConcurrencyConfig<M>[K]): Promise<void>;
570
+ acceptChanges(): void;
571
+ clearChanges(): void;
572
+ refresh(): Promise<void>;
573
+ refresh<strategy extends FetchStrategy<M, K>>(strategy: strategy): Promise<Array<DeepExpand<Selection<M, K, strategy>>>>;
574
+ delete(): Promise<void>;
575
+ delete<strategy extends FetchStrategy<M, K>>(strategy: strategy): Promise<void>;
576
+ };
577
+
578
+ // Helper type to add individual active record methods to selection results
572
579
  type WithActiveRecord<T, M extends Record<string, TableDefinition<M>>, K extends keyof M> =
573
580
  T & ActiveRecordMethods<M, K>;
574
581
 
582
+ // Helper type to add array active record methods to arrays without adding them to individual items
583
+ type WithArrayActiveRecord<T extends Array<any>, M extends Record<string, TableDefinition<M>>, K extends keyof M> =
584
+ T & ArrayActiveRecordMethods<M, K>;
585
+
586
+ // Separate CustomSelectorProperties for aggregate (allows column name overlap)
587
+ type AggregateCustomSelectorProperties<M extends Record<string, TableDefinition<M>>, K extends keyof M, FS extends Record<string, any>> = {
588
+ // Required properties (count, sum, avg) - no question mark, no null/undefined
589
+ [P in keyof FS as
590
+ P extends ReservedFetchStrategyProps ? never :
591
+ P extends (M[K] extends { relations: infer R } ? keyof R : never) ? never :
592
+ FS[P] extends (row: any) => any ?
593
+ (FS[P] extends (row: RootSelectionRefs<M, K>) => infer ReturnType
594
+ ? IsRequiredAggregate<ReturnType> extends true
595
+ ? P // Required aggregates
596
+ : never
597
+ : never)
598
+ : never
599
+ ]: FS[P] extends (row: RootSelectionRefs<M, K>) => infer ReturnType
600
+ ? number // Required aggregate functions (count, sum, avg) return required number
601
+ : never;
602
+ } & {
603
+ // Optional properties (max, min, plain columns) - with question mark AND null/undefined
604
+ [P in keyof FS as
605
+ P extends ReservedFetchStrategyProps ? never :
606
+ P extends (M[K] extends { relations: infer R } ? keyof R : never) ? never :
607
+ FS[P] extends (row: any) => any ?
608
+ (FS[P] extends (row: RootSelectionRefs<M, K>) => infer ReturnType
609
+ ? IsRequiredAggregate<ReturnType> extends true
610
+ ? never // Required aggregates are not optional
611
+ : P // Everything else is optional
612
+ : never)
613
+ : never
614
+ ]?: FS[P] extends (row: RootSelectionRefs<M, K>) => infer ReturnType
615
+ ? IsMinMaxAggregate<ReturnType> extends true
616
+ ? ExtractMinMaxColumnType<ReturnType> | null | undefined
617
+ : IsAggregateFunction<ReturnType> extends true
618
+ ? number | null | undefined
619
+ : ReturnType extends ORMColumnDefinition | ORMJsonColumnDefinition
620
+ ? ColumnDefinitionToTS<ReturnType> | null | undefined
621
+ : never
622
+ : never;
623
+ };
624
+
575
625
  export type TableClient<M extends Record<string, TableDefinition<M>>, K extends keyof M> = {
576
- getAll(): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K>>>;
577
- getAll<strategy extends FetchStrategy<M, K>>(strategy: strategy): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>>;
578
- getMany(filter: RawFilter | Array<PrimaryKeyObject<M, K>>): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K>>>;
579
- getMany<strategy extends FetchStrategy<M, K>>(filter: RawFilter | Array<PrimaryKeyObject<M, K>>, strategy: strategy): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>>;
626
+ // Array methods - return arrays with array-level active record methods, but individual items are plain
627
+ getAll(): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, {}>>>, M, K>>;
628
+ getAll<strategy extends FetchStrategy<M, K>>(strategy: strategy): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
629
+ getMany(filter: RawFilter | Array<PrimaryKeyObject<M, K>>): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, {}>>>, M, K>>;
630
+ getMany<strategy extends FetchStrategy<M, K>>(filter: RawFilter | Array<PrimaryKeyObject<M, K>>, strategy: strategy): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
631
+
632
+ // Aggregate methods - return plain objects (no active record methods)
633
+ aggregate<strategy extends AggregateStrategy<M, K>>(strategy: strategy): Promise<Array<DeepExpand<AggregateCustomSelectorProperties<M, K, strategy>>>>;
580
634
 
581
- aggregate<strategy extends AggregateStrategy<M, K>>(strategy: strategy): Promise<Array<DeepExpand<CustomSelectorProperties<M, K, strategy>>>>;
582
635
 
636
+
637
+ // Single item methods - return individual objects with individual active record methods
583
638
  getOne<strategy extends FetchStrategy<M, K>>(
584
639
  filter: RawFilter | Array<PrimaryKeyObject<M, K>>
585
640
  ): Promise<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>;
@@ -597,6 +652,7 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
597
652
  ...args: [...PrimaryKeyArgs<M, K>]
598
653
  ): Promise<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K>>;
599
654
 
655
+ // Bulk update methods
600
656
  update(
601
657
  row: Partial<{
602
658
  [C in keyof M[K]['columns']]: IsRequired<M[K]['columns'][C]> extends true
@@ -606,10 +662,6 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
606
662
  opts: { where: (row: RootTableRefs<M, K>) => RawFilter }
607
663
  ): Promise<void>;
608
664
 
609
- count(filter: RawFilter | Array<PrimaryKeyObject<M, K>>,): Promise<number>;
610
- delete(filter: RawFilter | Array<PrimaryKeyObject<M, K>>,): Promise<void>;
611
- deleteCascade(filter: RawFilter | Array<PrimaryKeyObject<M, K>>,): Promise<void>;
612
-
613
665
  update<strategy extends FetchStrategy<M, K>>(
614
666
  row: Partial<{
615
667
  [C in keyof M[K]['columns']]: IsRequired<M[K]['columns'][C]> extends true
@@ -618,8 +670,14 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
618
670
  }>,
619
671
  opts: { where: (row: RootTableRefs<M, K>) => RawFilter },
620
672
  strategy: strategy
621
- ): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>>;
673
+ ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
674
+
675
+ // Count and delete methods (no active record methods needed)
676
+ count(filter: RawFilter | Array<PrimaryKeyObject<M, K>>,): Promise<number>;
677
+ delete(filter: RawFilter | Array<PrimaryKeyObject<M, K>>,): Promise<void>;
678
+ deleteCascade(filter: RawFilter | Array<PrimaryKeyObject<M, K>>,): Promise<void>;
622
679
 
680
+ // Replace methods - can return single or array with appropriate active record methods
623
681
  replace(
624
682
  row: Array<UpdateChangesRow<M, K>>
625
683
  ): Promise<void>;
@@ -632,8 +690,9 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
632
690
  replace<strategy extends FetchStrategy<M, K>>(
633
691
  rows: Array<UpdateChangesRow<M, K>>,
634
692
  strategy: strategy
635
- ): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>>;
693
+ ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
636
694
 
695
+ // UpdateChanges methods - can return single or array with appropriate active record methods
637
696
  updateChanges(
638
697
  row: UpdateChangesRow<M, K>,
639
698
  originalRow: UpdateChangesRow<M, K>
@@ -642,7 +701,7 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
642
701
  updateChanges(
643
702
  rows: Array<UpdateChangesRow<M, K>>,
644
703
  originalRows: Array<UpdateChangesRow<M, K>>
645
- ): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K>>>;
704
+ ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, {}>>>, M, K>>;
646
705
 
647
706
  updateChanges<strategy extends FetchStrategy<M, K>>(
648
707
  row: UpdateChangesRow<M, K>,
@@ -654,8 +713,9 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
654
713
  rows: Array<UpdateChangesRow<M, K>>,
655
714
  originalRows: Array<UpdateChangesRow<M, K>>,
656
715
  strategy: strategy
657
- ): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>>;
716
+ ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
658
717
 
718
+ // Insert methods - no active record methods for insertAndForget, appropriate methods for others
659
719
  insertAndForget(
660
720
  row: InsertRow<M, K>
661
721
  ): Promise<void>;
@@ -670,7 +730,7 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
670
730
 
671
731
  insert(
672
732
  rows: Array<InsertRow<M, K>>
673
- ): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K>>>;
733
+ ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, {}>>>, M, K>>;
674
734
 
675
735
  insert<strategy extends FetchStrategy<M, K>>(
676
736
  row: InsertRow<M, K>,
@@ -680,15 +740,16 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
680
740
  insert<strategy extends FetchStrategy<M, K>>(
681
741
  rows: Array<InsertRow<M, K>>,
682
742
  strategy: strategy
683
- ): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>>;
743
+ ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
684
744
 
745
+ // Proxify methods - can return single or array with appropriate active record methods
685
746
  proxify(
686
747
  row: UpdateChangesRow<M, K>
687
748
  ): Promise<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K>>;
688
749
 
689
750
  proxify(
690
751
  rows: Array<UpdateChangesRow<M, K>>
691
- ): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, {}>>, M, K>>>;
752
+ ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, {}>>>, M, K>>;
692
753
 
693
754
  proxify<strategy extends FetchStrategy<M, K>>(
694
755
  row: UpdateChangesRow<M, K>,
@@ -698,14 +759,16 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
698
759
  proxify<strategy extends FetchStrategy<M, K>>(
699
760
  rows: Array<UpdateChangesRow<M, K>>,
700
761
  strategy: strategy
701
- ): Promise<Array<WithActiveRecord<DeepExpand<Selection<M, K, strategy>>, M, K>>>;
762
+ ): Promise<WithArrayActiveRecord<Array<DeepExpand<Selection<M, K, strategy>>>, M, K>>;
702
763
 
703
- patch<strategy extends FetchStrategy<M, K>>(
764
+ // Patch method
765
+ patch<strategy extends FetchStrategy<M, K>>(
704
766
  patches: JsonPatch,
705
767
  strategy: strategy,
706
768
  concurrency?: ConcurrencyConfig<M>[K]
707
769
  ): Promise<void>;
708
770
 
771
+ // TypeScript type helpers
709
772
  tsType(): DeepExpand<Selection<M, K, {}>>;
710
773
 
711
774
  tsType<strategy extends FetchStrategy<M, K>>(
@@ -713,6 +776,8 @@ export type TableClient<M extends Record<string, TableDefinition<M>>, K extends
713
776
  ): DeepExpand<Selection<M, K, strategy>>;
714
777
  };
715
778
 
779
+ // Rest of the type definitions remain the same...
780
+
716
781
  export type ConcurrencyStrategy = 'optimistic' | 'overwrite' | 'skipOnConflict';
717
782
 
718
783
  export interface ColumnConcurrency {
@@ -740,15 +805,6 @@ export type DbOptions<M extends Record<string, TableDefinition<M>>> =
740
805
  db?: Pool | ((connectors: Connectors) => Pool | Promise<Pool>);
741
806
  };
742
807
 
743
-
744
- // type NegotiateDbInstance<T, C> = C extends WithDb
745
- // ? DbConnectable<SchemaFromMappedDb<MappedDb<T>>>
746
- // : MappedDb<T>;
747
-
748
- // type WithDb = {
749
- // db: Pool | ((connectors: Connectors) => Pool | Promise<Pool>)
750
- // };
751
-
752
808
  export type DbConcurrency<M extends Record<string, TableDefinition<M>>> =
753
809
  ConcurrencyConfig<M>
754
810
  & ColumnConcurrency;
@@ -817,13 +873,12 @@ export type DBClient<M extends Record<string, TableDefinition<M>>> = {
817
873
  transaction(
818
874
  fn: (db: DBClient<M>) => Promise<unknown>
819
875
  ): Promise<void>;
820
- // saveChanges(arraysOrRow: { saveChanges(): Promise<void> }): Promise<void>;
821
876
  express(): import('express').RequestHandler;
822
877
  express(config: ExpressConfig<M>): import('express').RequestHandler;
823
878
  readonly metaData: DbConcurrency<M>;
824
879
 
825
880
  interceptors: WithInterceptors;
826
- } & WithInterceptors;
881
+ } & WithInterceptors & DbConnectable<M>;
827
882
 
828
883
  type ExpressConfig<M extends Record<string, TableDefinition<M>>> = {
829
884
  [TableName in keyof M]?: ExpressTableConfig<M>;
package/src/cyclic.d.ts DELETED
@@ -1,132 +0,0 @@
1
- // Type definitions using a type mapping approach
2
- type EntityMap = {
3
- Order: {
4
- id: string;
5
- date: Date;
6
- total: number;
7
- };
8
- Line: {
9
- id: string;
10
- quantity: number;
11
- price: number;
12
- };
13
- Package: {
14
- id: string;
15
- trackingNumber: string;
16
- weight: number;
17
- };
18
- Customer: {
19
- id: string;
20
- name: string;
21
- email: string;
22
- };
23
- };
24
-
25
- // Enhanced relation mapping that includes cardinality information
26
- type RelationMap = {
27
- Order: {
28
- lines: { type: 'Line'; isArray: true };
29
- customer: { type: 'Customer'; isArray: false };
30
- };
31
- Line: {
32
- packages: { type: 'Package'; isArray: true };
33
- order: { type: 'Order'; isArray: false };
34
- };
35
- Customer: {
36
- orders: { type: 'Order'; isArray: true };
37
- };
38
- Package: {};
39
- };
40
-
41
- // Helper type to extract the entity type from a relation
42
- type RelationEntityType<R> = R extends { type: infer T extends keyof EntityMap } ? T : never;
43
-
44
- // Helper type to determine if a relation is an array
45
- type IsArray<R> = R extends { isArray: infer A extends boolean } ? A : false;
46
-
47
- // Generic deep type resolver
48
- type Depth = [never, 0, 1, 2, 3, 4, 5];
49
-
50
- // RecursiveType generic with improved depth handling
51
- type RecursiveType<
52
- T extends keyof EntityMap,
53
- D extends number = 5
54
- > = {
55
- // Always include base properties
56
- [K in keyof EntityMap[T]]: EntityMap[T][K];
57
- } & (D extends 0
58
- ? // At max depth, only include base properties (which are already included above)
59
- {}
60
- : // Otherwise include relations with appropriate depth reduction
61
- {
62
- [K in keyof RelationMap[T]]: IsArray<RelationMap[T][K]> extends true
63
- ? RecursiveType<
64
- RelationEntityType<RelationMap[T][K]>,
65
- Depth[D]
66
- >[]
67
- : RecursiveType<
68
- RelationEntityType<RelationMap[T][K]>,
69
- Depth[D]
70
- >;
71
- });
72
-
73
- // Generate the entity types with relationships resolved to the specified depth
74
- type Order = RecursiveType<'Order', 6>;
75
-
76
- type Line = RecursiveType<'Line'>;
77
- type Package = RecursiveType<'Package'>;
78
- type Customer = RecursiveType<'Customer'>;
79
-
80
- // Example usage
81
- function processOrder(order: Order, line: Line) {
82
- // Can access nested properties up to depth 5
83
- // const trackingNumber = order.customer.orders[0].lines[0].order.lines[0].packages[0].
84
- // const orderId = order.customer.orders[0].customer.orders[0].lines[0].
85
- line.order.customer.orders[0].lines[0].packages[0].
86
-
87
- console.log(trackingNumber, orderId);
88
- }
89
-
90
- // Allow custom depth control per entity type
91
- type OrderWithDepth1 = RecursiveType<'Order', 4>;
92
-
93
- // Example with custom depth
94
- function processOrderWithLimitedDepth(order: OrderWithDepth1) {
95
- // This would work (depth 1)
96
-
97
- console.log(order.customer.id); // Can access base properties at max depth
98
- console.log(order.customer.name); // Can access base properties at max depth
99
-
100
- // This would error - beyond depth 1
101
- // console.log(order.customer.orders[0].id);
102
- }
103
-
104
- // Example of creating an instance with this type system
105
- const sampleOrder: Order = {
106
- id: "ORD-123",
107
- date: new Date(),
108
- total: 299.99,
109
- customer: {
110
- id: "CUST-456",
111
- name: "John Doe",
112
- email: "john@example.com",
113
- orders: [
114
- /* would be recursive orders */
115
- ]
116
- },
117
- lines: [
118
- {
119
- id: "LINE-789",
120
- quantity: 2,
121
- price: 149.99,
122
- order: /* circular reference */,
123
- packages: [
124
- {
125
- id: "PKG-101",
126
- trackingNumber: "TRK123456789",
127
- weight: 1.5
128
- }
129
- ]
130
- }
131
- ]
132
- };