metal-orm 1.0.40 → 1.0.42

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 (45) hide show
  1. package/README.md +53 -14
  2. package/dist/index.cjs +1298 -126
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +676 -30
  5. package/dist/index.d.ts +676 -30
  6. package/dist/index.js +1293 -126
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/codegen/typescript.ts +6 -2
  10. package/src/core/ast/expression-builders.ts +25 -4
  11. package/src/core/ast/expression-nodes.ts +3 -1
  12. package/src/core/ast/expression.ts +2 -2
  13. package/src/core/ast/query.ts +24 -2
  14. package/src/core/dialect/abstract.ts +6 -2
  15. package/src/core/dialect/base/join-compiler.ts +9 -12
  16. package/src/core/dialect/base/sql-dialect.ts +98 -17
  17. package/src/core/dialect/mssql/index.ts +30 -62
  18. package/src/core/dialect/sqlite/index.ts +39 -34
  19. package/src/core/execution/db-executor.ts +46 -6
  20. package/src/core/execution/executors/mssql-executor.ts +39 -22
  21. package/src/core/execution/executors/mysql-executor.ts +23 -6
  22. package/src/core/execution/executors/sqlite-executor.ts +29 -3
  23. package/src/core/execution/pooling/pool-types.ts +30 -0
  24. package/src/core/execution/pooling/pool.ts +268 -0
  25. package/src/decorators/bootstrap.ts +7 -7
  26. package/src/index.ts +6 -0
  27. package/src/orm/domain-event-bus.ts +49 -0
  28. package/src/orm/entity-metadata.ts +9 -9
  29. package/src/orm/entity.ts +58 -0
  30. package/src/orm/orm-session.ts +465 -270
  31. package/src/orm/orm.ts +61 -11
  32. package/src/orm/pooled-executor-factory.ts +131 -0
  33. package/src/orm/query-logger.ts +6 -12
  34. package/src/orm/relation-change-processor.ts +75 -0
  35. package/src/orm/relations/many-to-many.ts +4 -2
  36. package/src/orm/save-graph.ts +303 -0
  37. package/src/orm/transaction-runner.ts +3 -3
  38. package/src/orm/unit-of-work.ts +128 -0
  39. package/src/query-builder/delete-query-state.ts +67 -38
  40. package/src/query-builder/delete.ts +37 -1
  41. package/src/query-builder/insert-query-state.ts +131 -61
  42. package/src/query-builder/insert.ts +27 -1
  43. package/src/query-builder/update-query-state.ts +114 -77
  44. package/src/query-builder/update.ts +38 -1
  45. package/src/schema/table.ts +210 -115
@@ -1,18 +1,44 @@
1
1
  import type { DomainEvent, HasDomainEvents, TrackedEntity } from './runtime-types.js';
2
2
 
3
+ /**
4
+ * Extracts domain events of a specific type.
5
+ * @template E - The domain event type
6
+ * @template TType - The specific event type
7
+ */
3
8
  type EventOfType<E extends DomainEvent, TType extends E['type']> =
4
9
  Extract<E, { type: TType }>;
5
10
 
11
+ /**
12
+ * Domain event handler function.
13
+ * @template E - The domain event type
14
+ * @template Context - The context type
15
+ * @param event - The domain event
16
+ * @param ctx - The context
17
+ */
6
18
  export type DomainEventHandler<E extends DomainEvent, Context> =
7
19
  (event: E, ctx: Context) => Promise<void> | void;
8
20
 
21
+ /**
22
+ * Initial handlers for domain events.
23
+ * @template E - The domain event type
24
+ * @template Context - The context type
25
+ */
9
26
  export type InitialHandlers<E extends DomainEvent, Context> = {
10
27
  [K in E['type']]?: DomainEventHandler<EventOfType<E, K>, Context>[];
11
28
  };
12
29
 
30
+ /**
31
+ * Domain event bus for managing and dispatching domain events.
32
+ * @template E - The domain event type
33
+ * @template Context - The context type
34
+ */
13
35
  export class DomainEventBus<E extends DomainEvent, Context> {
14
36
  private readonly handlers = new Map<E['type'], DomainEventHandler<E, Context>[]>();
15
37
 
38
+ /**
39
+ * Creates a new DomainEventBus instance.
40
+ * @param initialHandlers - Optional initial event handlers
41
+ */
16
42
  constructor(initialHandlers?: InitialHandlers<E, Context>) {
17
43
  if (initialHandlers) {
18
44
  for (const key in initialHandlers) {
@@ -23,6 +49,12 @@ export class DomainEventBus<E extends DomainEvent, Context> {
23
49
  }
24
50
  }
25
51
 
52
+ /**
53
+ * Registers an event handler for a specific event type.
54
+ * @template TType - The event type
55
+ * @param type - The event type
56
+ * @param handler - The event handler
57
+ */
26
58
  on<TType extends E['type']>(
27
59
  type: TType,
28
60
  handler: DomainEventHandler<EventOfType<E, TType>, Context>
@@ -33,6 +65,12 @@ export class DomainEventBus<E extends DomainEvent, Context> {
33
65
  this.handlers.set(key, existing);
34
66
  }
35
67
 
68
+ /**
69
+ * Registers an event handler for a specific event type (alias for on).
70
+ * @template TType - The event type
71
+ * @param type - The event type
72
+ * @param handler - The event handler
73
+ */
36
74
  register<TType extends E['type']>(
37
75
  type: TType,
38
76
  handler: DomainEventHandler<EventOfType<E, TType>, Context>
@@ -40,6 +78,11 @@ export class DomainEventBus<E extends DomainEvent, Context> {
40
78
  this.on(type, handler);
41
79
  }
42
80
 
81
+ /**
82
+ * Dispatches domain events for tracked entities.
83
+ * @param trackedEntities - Iterable of tracked entities
84
+ * @param ctx - The context to pass to handlers
85
+ */
43
86
  async dispatch(trackedEntities: Iterable<TrackedEntity>, ctx: Context): Promise<void> {
44
87
  for (const tracked of trackedEntities) {
45
88
  const entity = tracked.entity as HasDomainEvents<E>;
@@ -59,6 +102,12 @@ export class DomainEventBus<E extends DomainEvent, Context> {
59
102
  }
60
103
  }
61
104
 
105
+ /**
106
+ * Adds a domain event to an entity.
107
+ * @template E - The domain event type
108
+ * @param entity - The entity to add the event to
109
+ * @param event - The domain event to add
110
+ */
62
111
  export const addDomainEvent = <E extends DomainEvent>(
63
112
  entity: HasDomainEvents<E>,
64
113
  event: E
@@ -2,8 +2,8 @@ import { ColumnType, ColumnDef } from '../schema/column.js';
2
2
  import { defineTable, TableDef, TableHooks } from '../schema/table.js';
3
3
  import { CascadeMode, RelationKinds } from '../schema/relation.js';
4
4
 
5
- export type EntityConstructor = new (...args: any[]) => any;
6
- export type EntityOrTableTarget = EntityConstructor | TableDef;
5
+ export type EntityConstructor<T = object> = new (...args: any[]) => T;
6
+ export type EntityOrTableTarget = EntityConstructor<any> | TableDef;
7
7
  export type EntityOrTableTargetResolver = EntityOrTableTarget | (() => EntityOrTableTarget);
8
8
 
9
9
  export type ColumnDefLike<T extends ColumnDef = ColumnDef> = Omit<T, 'name' | 'table'>;
@@ -57,7 +57,7 @@ export type RelationMetadata =
57
57
  | BelongsToManyRelationMetadata;
58
58
 
59
59
  export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> = Record<string, ColumnDefLike>> {
60
- target: EntityConstructor;
60
+ target: EntityConstructor<any>;
61
61
  tableName: string;
62
62
  columns: TColumns;
63
63
  relations: Record<string, RelationMetadata>;
@@ -65,13 +65,13 @@ export interface EntityMetadata<TColumns extends Record<string, ColumnDefLike> =
65
65
  table?: TableDef<MaterializeColumns<TColumns>>;
66
66
  }
67
67
 
68
- const metadataMap = new Map<EntityConstructor, EntityMetadata>();
68
+ const metadataMap = new Map<EntityConstructor<any>, EntityMetadata>();
69
69
 
70
70
  export const registerEntityMetadata = (meta: EntityMetadata): void => {
71
71
  metadataMap.set(meta.target, meta);
72
72
  };
73
73
 
74
- export const ensureEntityMetadata = (target: EntityConstructor): EntityMetadata => {
74
+ export const ensureEntityMetadata = (target: EntityConstructor<any>): EntityMetadata => {
75
75
  let meta = metadataMap.get(target);
76
76
  if (!meta) {
77
77
  meta = {
@@ -85,7 +85,7 @@ export const ensureEntityMetadata = (target: EntityConstructor): EntityMetadata
85
85
  return meta;
86
86
  };
87
87
 
88
- export const getEntityMetadata = (target: EntityConstructor): EntityMetadata | undefined => {
88
+ export const getEntityMetadata = (target: EntityConstructor<any>): EntityMetadata | undefined => {
89
89
  return metadataMap.get(target);
90
90
  };
91
91
 
@@ -98,7 +98,7 @@ export const clearEntityMetadata = (): void => {
98
98
  };
99
99
 
100
100
  export const addColumnMetadata = (
101
- target: EntityConstructor,
101
+ target: EntityConstructor<any>,
102
102
  propertyKey: string,
103
103
  column: ColumnDefLike
104
104
  ): void => {
@@ -107,7 +107,7 @@ export const addColumnMetadata = (
107
107
  };
108
108
 
109
109
  export const addRelationMetadata = (
110
- target: EntityConstructor,
110
+ target: EntityConstructor<any>,
111
111
  propertyKey: string,
112
112
  relation: RelationMetadata
113
113
  ): void => {
@@ -116,7 +116,7 @@ export const addRelationMetadata = (
116
116
  };
117
117
 
118
118
  export const setEntityTableName = (
119
- target: EntityConstructor,
119
+ target: EntityConstructor<any>,
120
120
  tableName: string,
121
121
  hooks?: TableHooks
122
122
  ): void => {
package/src/orm/entity.ts CHANGED
@@ -10,8 +10,19 @@ import { HasManyRelation, HasOneRelation, BelongsToRelation, BelongsToManyRelati
10
10
  import { loadHasManyRelation, loadHasOneRelation, loadBelongsToRelation, loadBelongsToManyRelation } from './lazy-batch.js';
11
11
  import { findPrimaryKey } from '../query-builder/hydration-planner.js';
12
12
 
13
+ /**
14
+ * Type representing an array of database rows.
15
+ */
13
16
  type Rows = Record<string, any>[];
14
17
 
18
+ /**
19
+ * Caches relation loader results across entities of the same type.
20
+ * @template T - The cache type
21
+ * @param meta - The entity metadata
22
+ * @param relationName - The relation name
23
+ * @param factory - The factory function to create the cache
24
+ * @returns Promise with the cached relation data
25
+ */
15
26
  const relationLoaderCache = <T extends Map<string, any>>(
16
27
  meta: EntityMeta<any>,
17
28
  relationName: string,
@@ -41,6 +52,16 @@ const relationLoaderCache = <T extends Map<string, any>>(
41
52
  return promise;
42
53
  };
43
54
 
55
+ /**
56
+ * Creates an entity proxy with lazy loading capabilities.
57
+ * @template TTable - The table type
58
+ * @template TLazy - The lazy relation keys
59
+ * @param ctx - The entity context
60
+ * @param table - The table definition
61
+ * @param row - The database row
62
+ * @param lazyRelations - Optional lazy relations
63
+ * @returns The entity instance
64
+ */
44
65
  export const createEntityProxy = <
45
66
  TTable extends TableDef,
46
67
  TLazy extends keyof RelationMap<TTable> = keyof RelationMap<TTable>
@@ -104,6 +125,16 @@ export const createEntityProxy = <
104
125
  return proxy;
105
126
  };
106
127
 
128
+ /**
129
+ * Creates an entity instance from a database row.
130
+ * @template TTable - The table type
131
+ * @template TResult - The result type
132
+ * @param ctx - The entity context
133
+ * @param table - The table definition
134
+ * @param row - The database row
135
+ * @param lazyRelations - Optional lazy relations
136
+ * @returns The entity instance
137
+ */
107
138
  export const createEntityFromRow = <
108
139
  TTable extends TableDef,
109
140
  TResult extends EntityInstance<TTable> = EntityInstance<TTable>
@@ -130,8 +161,20 @@ export const createEntityFromRow = <
130
161
  return entity as TResult;
131
162
  };
132
163
 
164
+ /**
165
+ * Converts a value to a string key.
166
+ * @param value - The value to convert
167
+ * @returns String representation of the value
168
+ */
133
169
  const toKey = (value: unknown): string => (value === null || value === undefined ? '' : String(value));
134
170
 
171
+ /**
172
+ * Populates the hydration cache with relation data from the database row.
173
+ * @template TTable - The table type
174
+ * @param entity - The entity instance
175
+ * @param row - The database row
176
+ * @param meta - The entity metadata
177
+ */
135
178
  const populateHydrationCache = <TTable extends TableDef>(
136
179
  entity: any,
137
180
  row: Record<string, any>,
@@ -181,6 +224,13 @@ const populateHydrationCache = <TTable extends TableDef>(
181
224
  }
182
225
  };
183
226
 
227
+ /**
228
+ * Gets a relation wrapper for an entity.
229
+ * @param meta - The entity metadata
230
+ * @param relationName - The relation name
231
+ * @param owner - The owner entity
232
+ * @returns The relation wrapper or undefined
233
+ */
184
234
  const getRelationWrapper = (
185
235
  meta: EntityMeta<any>,
186
236
  relationName: string,
@@ -201,6 +251,14 @@ const getRelationWrapper = (
201
251
  return wrapper;
202
252
  };
203
253
 
254
+ /**
255
+ * Instantiates the appropriate relation wrapper based on relation type.
256
+ * @param meta - The entity metadata
257
+ * @param relationName - The relation name
258
+ * @param relation - The relation definition
259
+ * @param owner - The owner entity
260
+ * @returns The relation wrapper or undefined
261
+ */
204
262
  const instantiateWrapper = (
205
263
  meta: EntityMeta<any>,
206
264
  relationName: string,