metal-orm 1.0.58 → 1.0.60

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.
Files changed (41) hide show
  1. package/README.md +34 -31
  2. package/dist/index.cjs +1583 -901
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +400 -129
  5. package/dist/index.d.ts +400 -129
  6. package/dist/index.js +1575 -901
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/core/ddl/schema-generator.ts +44 -1
  10. package/src/decorators/bootstrap.ts +183 -146
  11. package/src/decorators/column-decorator.ts +8 -49
  12. package/src/decorators/decorator-metadata.ts +10 -46
  13. package/src/decorators/entity.ts +30 -40
  14. package/src/decorators/relations.ts +30 -56
  15. package/src/index.ts +7 -7
  16. package/src/orm/entity-hydration.ts +72 -0
  17. package/src/orm/entity-meta.ts +13 -11
  18. package/src/orm/entity-metadata.ts +240 -238
  19. package/src/orm/entity-relation-cache.ts +39 -0
  20. package/src/orm/entity-relations.ts +207 -0
  21. package/src/orm/entity.ts +124 -410
  22. package/src/orm/execute.ts +4 -4
  23. package/src/orm/lazy-batch/belongs-to-many.ts +134 -0
  24. package/src/orm/lazy-batch/belongs-to.ts +108 -0
  25. package/src/orm/lazy-batch/has-many.ts +69 -0
  26. package/src/orm/lazy-batch/has-one.ts +68 -0
  27. package/src/orm/lazy-batch/shared.ts +125 -0
  28. package/src/orm/lazy-batch.ts +4 -492
  29. package/src/orm/relations/many-to-many.ts +2 -1
  30. package/src/query-builder/relation-cte-builder.ts +63 -0
  31. package/src/query-builder/relation-filter-utils.ts +159 -0
  32. package/src/query-builder/relation-include-strategies.ts +177 -0
  33. package/src/query-builder/relation-join-planner.ts +80 -0
  34. package/src/query-builder/relation-service.ts +119 -479
  35. package/src/query-builder/relation-types.ts +41 -10
  36. package/src/query-builder/select/projection-facet.ts +23 -23
  37. package/src/query-builder/select/select-operations.ts +145 -0
  38. package/src/query-builder/select.ts +329 -221
  39. package/src/schema/relation.ts +22 -18
  40. package/src/schema/table.ts +22 -9
  41. package/src/schema/types.ts +14 -12
@@ -57,12 +57,15 @@ export interface BelongsToRelation<TTarget extends TableDef = TableDef> {
57
57
  /**
58
58
  * Many-to-many relationship definition with rich pivot metadata
59
59
  */
60
- export interface BelongsToManyRelation<TTarget extends TableDef = TableDef> {
61
- type: typeof RelationKinds.BelongsToMany;
62
- target: TTarget;
63
- pivotTable: TableDef;
64
- pivotForeignKeyToRoot: string;
65
- pivotForeignKeyToTarget: string;
60
+ export interface BelongsToManyRelation<
61
+ TTarget extends TableDef = TableDef,
62
+ TPivot extends TableDef = TableDef
63
+ > {
64
+ type: typeof RelationKinds.BelongsToMany;
65
+ target: TTarget;
66
+ pivotTable: TPivot;
67
+ pivotForeignKeyToRoot: string;
68
+ pivotForeignKeyToTarget: string;
66
69
  localKey?: string;
67
70
  targetKey?: string;
68
71
  pivotPrimaryKey?: string;
@@ -156,24 +159,25 @@ export const belongsTo = <TTarget extends TableDef>(
156
159
  * @param options - Pivot metadata configuration
157
160
  * @returns BelongsToManyRelation definition
158
161
  */
159
- export const belongsToMany = <
160
- TTarget extends TableDef
161
- >(
162
- target: TTarget,
163
- pivotTable: TableDef,
164
- options: {
165
- pivotForeignKeyToRoot: string;
166
- pivotForeignKeyToTarget: string;
162
+ export const belongsToMany = <
163
+ TTarget extends TableDef,
164
+ TPivot extends TableDef = TableDef
165
+ >(
166
+ target: TTarget,
167
+ pivotTable: TPivot,
168
+ options: {
169
+ pivotForeignKeyToRoot: string;
170
+ pivotForeignKeyToTarget: string;
167
171
  localKey?: string;
168
172
  targetKey?: string;
169
173
  pivotPrimaryKey?: string;
170
174
  defaultPivotColumns?: string[];
171
175
  cascade?: CascadeMode;
172
176
  }
173
- ): BelongsToManyRelation<TTarget> => ({
174
- type: RelationKinds.BelongsToMany,
175
- target,
176
- pivotTable,
177
+ ): BelongsToManyRelation<TTarget, TPivot> => ({
178
+ type: RelationKinds.BelongsToMany,
179
+ target,
180
+ pivotTable,
177
181
  pivotForeignKeyToRoot: options.pivotForeignKeyToRoot,
178
182
  pivotForeignKeyToTarget: options.pivotForeignKeyToTarget,
179
183
  localKey: options.localKey,
@@ -85,13 +85,13 @@ export interface TableDef<T extends Record<string, ColumnDef> = Record<string, C
85
85
  * });
86
86
  * ```
87
87
  */
88
- export const defineTable = <T extends Record<string, ColumnDef>>(
89
- name: string,
90
- columns: T,
91
- relations: Record<string, RelationDef> = {},
92
- hooks?: TableHooks,
93
- options: TableOptions = {}
94
- ): TableDef<T> => {
88
+ export const defineTable = <T extends Record<string, ColumnDef>>(
89
+ name: string,
90
+ columns: T,
91
+ relations: Record<string, RelationDef> = {},
92
+ hooks?: TableHooks,
93
+ options: TableOptions = {}
94
+ ): TableDef<T> => {
95
95
  // Runtime mutability to assign names to column definitions for convenience
96
96
  const colsWithNames = Object.entries(columns).reduce((acc, [key, def]) => {
97
97
  const colDef = { ...def, name: key, table: name };
@@ -112,8 +112,21 @@ export const defineTable = <T extends Record<string, ColumnDef>>(
112
112
  engine: options.engine,
113
113
  charset: options.charset,
114
114
  collation: options.collation
115
- };
116
- };
115
+ };
116
+ };
117
+
118
+ /**
119
+ * Assigns relations to a table definition while preserving literal typing.
120
+ */
121
+ export function setRelations<
122
+ TTable extends TableDef,
123
+ TRelations extends Record<string, RelationDef>
124
+ >(
125
+ table: TTable,
126
+ relations: TRelations
127
+ ): asserts table is TTable & { relations: TRelations } {
128
+ table.relations = relations;
129
+ }
117
130
 
118
131
  type DirectColumnKeys<T extends TableDef> =
119
132
  Exclude<keyof T["columns"] & string, keyof T | "$">;
@@ -12,12 +12,12 @@ import {
12
12
  /**
13
13
  * Resolves a relation definition to its target table type.
14
14
  */
15
- export type RelationTargetTable<TRel extends RelationDef> =
16
- TRel extends HasManyRelation<infer TTarget> ? TTarget :
17
- TRel extends HasOneRelation<infer TTarget> ? TTarget :
18
- TRel extends BelongsToRelation<infer TTarget> ? TTarget :
19
- TRel extends BelongsToManyRelation<infer TTarget> ? TTarget :
20
- never;
15
+ export type RelationTargetTable<TRel extends RelationDef> =
16
+ TRel extends HasManyRelation<infer TTarget> ? TTarget :
17
+ TRel extends HasOneRelation<infer TTarget> ? TTarget :
18
+ TRel extends BelongsToRelation<infer TTarget> ? TTarget :
19
+ TRel extends BelongsToManyRelation<infer TTarget, TableDef> ? TTarget :
20
+ never;
21
21
 
22
22
  type NormalizedColumnType<T extends ColumnDef> = Lowercase<T['type'] & string>;
23
23
 
@@ -47,7 +47,7 @@ type RelationResult<T extends RelationDef> =
47
47
  T extends HasManyRelation<infer TTarget> ? InferRow<TTarget>[] :
48
48
  T extends HasOneRelation<infer TTarget> ? InferRow<TTarget> | null :
49
49
  T extends BelongsToRelation<infer TTarget> ? InferRow<TTarget> | null :
50
- T extends BelongsToManyRelation<infer TTarget> ? (InferRow<TTarget> & { _pivot?: Record<string, unknown> })[] :
50
+ T extends BelongsToManyRelation<infer TTarget, TableDef> ? (InferRow<TTarget> & { _pivot?: Record<string, unknown> })[] :
51
51
  never;
52
52
 
53
53
  /**
@@ -63,9 +63,9 @@ type RelationWrapper<TRel extends RelationDef> =
63
63
  : TRel extends HasOneRelation<infer TTarget>
64
64
  ? HasOneReference<EntityInstance<TTarget>>
65
65
  : TRel extends BelongsToManyRelation<infer TTarget>
66
- ? ManyToManyCollection<EntityInstance<TTarget> & { _pivot?: Record<string, unknown> }>
67
- & ReadonlyArray<EntityInstance<TTarget> & { _pivot?: Record<string, unknown> }>
68
- : TRel extends BelongsToRelation<infer TTarget>
66
+ ? ManyToManyCollection<EntityInstance<TTarget> & { _pivot?: Record<string, unknown> }>
67
+ & ReadonlyArray<EntityInstance<TTarget> & { _pivot?: Record<string, unknown> }>
68
+ : TRel extends BelongsToRelation<infer TTarget>
69
69
  ? BelongsToReference<EntityInstance<TTarget>>
70
70
  : never;
71
71
 
@@ -96,7 +96,7 @@ export interface HasOneReferenceApi<TChild extends object = object> {
96
96
 
97
97
  export type HasOneReference<TChild extends object = object> = HasOneReferenceApi<TChild> & Partial<TChild>;
98
98
 
99
- export interface ManyToManyCollection<TTarget> {
99
+ export interface ManyToManyCollection<TTarget, TPivot extends object | undefined = undefined> {
100
100
  length: number;
101
101
  [Symbol.iterator](): Iterator<TTarget>;
102
102
  load(): Promise<TTarget[]>;
@@ -104,7 +104,9 @@ export interface ManyToManyCollection<TTarget> {
104
104
  attach(target: TTarget | number | string): void;
105
105
  detach(target: TTarget | number | string): void;
106
106
  syncByIds(ids: (number | string)[]): Promise<void>;
107
- }
107
+ /** @internal Type-level marker for the related pivot entity */
108
+ readonly __pivotType?: TPivot;
109
+ }
108
110
 
109
111
  export type EntityInstance<
110
112
  TTable extends TableDef,