metal-orm 1.1.8 → 1.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/README.md +769 -764
- package/dist/index.cjs +2352 -226
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +605 -40
- package/dist/index.d.ts +605 -40
- package/dist/index.js +2324 -226
- package/dist/index.js.map +1 -1
- package/package.json +22 -17
- package/src/bulk/bulk-context.ts +83 -0
- package/src/bulk/bulk-delete-executor.ts +89 -0
- package/src/bulk/bulk-executor.base.ts +73 -0
- package/src/bulk/bulk-insert-executor.ts +74 -0
- package/src/bulk/bulk-types.ts +70 -0
- package/src/bulk/bulk-update-executor.ts +192 -0
- package/src/bulk/bulk-upsert-executor.ts +95 -0
- package/src/bulk/bulk-utils.ts +91 -0
- package/src/bulk/index.ts +18 -0
- package/src/codegen/typescript.ts +30 -21
- package/src/core/ast/expression-builders.ts +107 -10
- package/src/core/ast/expression-nodes.ts +52 -22
- package/src/core/ast/expression-visitor.ts +23 -13
- package/src/core/dialect/abstract.ts +30 -17
- package/src/core/dialect/mysql/index.ts +20 -5
- package/src/core/execution/db-executor.ts +96 -64
- package/src/core/execution/executors/better-sqlite3-executor.ts +94 -0
- package/src/core/execution/executors/mssql-executor.ts +66 -34
- package/src/core/execution/executors/mysql-executor.ts +98 -66
- package/src/core/execution/executors/postgres-executor.ts +33 -11
- package/src/core/execution/executors/sqlite-executor.ts +86 -30
- package/src/decorators/bootstrap.ts +482 -398
- package/src/decorators/column-decorator.ts +87 -96
- package/src/decorators/decorator-metadata.ts +100 -24
- package/src/decorators/entity.ts +27 -24
- package/src/decorators/relations.ts +231 -149
- package/src/decorators/transformers/transformer-decorators.ts +26 -29
- package/src/decorators/validators/country-validators-decorators.ts +9 -15
- package/src/dto/apply-filter.ts +568 -551
- package/src/index.ts +16 -9
- package/src/orm/entity-hydration.ts +116 -72
- package/src/orm/entity-metadata.ts +347 -301
- package/src/orm/entity-relations.ts +264 -207
- package/src/orm/entity.ts +199 -199
- package/src/orm/execute.ts +13 -13
- package/src/orm/lazy-batch/morph-many.ts +70 -0
- package/src/orm/lazy-batch/morph-one.ts +69 -0
- package/src/orm/lazy-batch/morph-to.ts +59 -0
- package/src/orm/lazy-batch.ts +4 -1
- package/src/orm/orm-session.ts +170 -104
- package/src/orm/pooled-executor-factory.ts +99 -58
- package/src/orm/query-logger.ts +49 -40
- package/src/orm/relation-change-processor.ts +198 -96
- package/src/orm/relations/belongs-to.ts +143 -143
- package/src/orm/relations/has-many.ts +204 -204
- package/src/orm/relations/has-one.ts +174 -174
- package/src/orm/relations/many-to-many.ts +288 -288
- package/src/orm/relations/morph-many.ts +156 -0
- package/src/orm/relations/morph-one.ts +151 -0
- package/src/orm/relations/morph-to.ts +162 -0
- package/src/orm/save-graph.ts +116 -1
- package/src/query-builder/expression-table-mapper.ts +5 -0
- package/src/query-builder/hydration-manager.ts +345 -345
- package/src/query-builder/hydration-planner.ts +178 -148
- package/src/query-builder/relation-conditions.ts +171 -151
- package/src/query-builder/relation-cte-builder.ts +5 -1
- package/src/query-builder/relation-filter-utils.ts +9 -6
- package/src/query-builder/relation-include-strategies.ts +44 -2
- package/src/query-builder/relation-join-strategies.ts +8 -1
- package/src/query-builder/relation-service.ts +250 -241
- package/src/query-builder/select/cursor-pagination.ts +323 -0
- package/src/query-builder/select/select-operations.ts +110 -105
- package/src/query-builder/select.ts +42 -1
- package/src/query-builder/update-include.ts +4 -0
- package/src/schema/relation.ts +296 -188
- package/src/schema/types.ts +138 -123
- package/src/tree/tree-decorator.ts +127 -137
package/src/index.ts
CHANGED
|
@@ -9,13 +9,13 @@ export * from './schema/types.js';
|
|
|
9
9
|
export * from './query-builder/select.js';
|
|
10
10
|
export * from './query-builder/select-helpers.js';
|
|
11
11
|
export * from './query-builder/insert.js';
|
|
12
|
-
export * from './query-builder/update.js';
|
|
13
|
-
export * from './query-builder/delete.js';
|
|
14
|
-
export * from './query-builder/procedure-call.js';
|
|
15
|
-
export * from './query/index.js';
|
|
16
|
-
export * from './core/ast/expression.js';
|
|
17
|
-
export * from './core/ast/procedure.js';
|
|
18
|
-
export * from './core/ast/window-functions.js';
|
|
12
|
+
export * from './query-builder/update.js';
|
|
13
|
+
export * from './query-builder/delete.js';
|
|
14
|
+
export * from './query-builder/procedure-call.js';
|
|
15
|
+
export * from './query/index.js';
|
|
16
|
+
export * from './core/ast/expression.js';
|
|
17
|
+
export * from './core/ast/procedure.js';
|
|
18
|
+
export * from './core/ast/window-functions.js';
|
|
19
19
|
export * from './core/hydration/types.js';
|
|
20
20
|
export * from './core/dialect/mysql/index.js';
|
|
21
21
|
export * from './core/dialect/mssql/index.js';
|
|
@@ -43,8 +43,11 @@ export * from './orm/lazy-batch.js';
|
|
|
43
43
|
export * from './orm/relations/has-many.js';
|
|
44
44
|
export * from './orm/relations/belongs-to.js';
|
|
45
45
|
export * from './orm/relations/many-to-many.js';
|
|
46
|
-
export * from './orm/
|
|
47
|
-
export * from './orm/
|
|
46
|
+
export * from './orm/relations/morph-one.js';
|
|
47
|
+
export * from './orm/relations/morph-many.js';
|
|
48
|
+
export * from './orm/relations/morph-to.js';
|
|
49
|
+
export * from './orm/execute.js';
|
|
50
|
+
export * from './orm/execute-procedure.js';
|
|
48
51
|
export type { EntityContext } from './orm/entity-context.js';
|
|
49
52
|
export type { PrimaryKey as EntityPrimaryKey } from './orm/entity-context.js';
|
|
50
53
|
export * from './orm/execution-context.js';
|
|
@@ -64,6 +67,7 @@ export * from './core/execution/pooling/pool.js';
|
|
|
64
67
|
export * from './core/execution/executors/postgres-executor.js';
|
|
65
68
|
export * from './core/execution/executors/mysql-executor.js';
|
|
66
69
|
export * from './core/execution/executors/sqlite-executor.js';
|
|
70
|
+
export * from './core/execution/executors/better-sqlite3-executor.js';
|
|
67
71
|
export * from './core/execution/executors/mssql-executor.js';
|
|
68
72
|
|
|
69
73
|
// NEW: first-class pooling integration
|
|
@@ -77,3 +81,6 @@ export * from './tree/index.js';
|
|
|
77
81
|
|
|
78
82
|
// Cache module
|
|
79
83
|
export * from './cache/index.js';
|
|
84
|
+
|
|
85
|
+
// Bulk operations module
|
|
86
|
+
export * from './bulk/index.js';
|
|
@@ -1,72 +1,116 @@
|
|
|
1
|
-
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import { RelationKinds } from '../schema/relation.js';
|
|
3
|
-
import { findPrimaryKey } from '../query-builder/hydration-planner.js';
|
|
4
|
-
import { EntityMeta } from './entity-meta.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Type representing an array of database rows.
|
|
8
|
-
*/
|
|
9
|
-
type Rows = Record<string, unknown>[];
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Converts a value to a string key.
|
|
13
|
-
* @param value - The value to convert
|
|
14
|
-
* @returns String representation of the value
|
|
15
|
-
*/
|
|
16
|
-
const toKey = (value: unknown): string => (value === null || value === undefined ? '' : String(value));
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Populates the hydration cache with relation data from the database row.
|
|
20
|
-
* @template TTable - The table type
|
|
21
|
-
* @param entity - The entity instance
|
|
22
|
-
* @param row - The database row
|
|
23
|
-
* @param meta - The entity metadata
|
|
24
|
-
*/
|
|
25
|
-
export const populateHydrationCache = <TTable extends TableDef>(
|
|
26
|
-
entity: Record<string, unknown>,
|
|
27
|
-
row: Record<string, unknown>,
|
|
28
|
-
meta: EntityMeta<TTable>
|
|
29
|
-
): void => {
|
|
30
|
-
for (const relationName of Object.keys(meta.table.relations)) {
|
|
31
|
-
const relation = meta.table.relations[relationName];
|
|
32
|
-
const data = row[relationName];
|
|
33
|
-
if (relation.type === RelationKinds.HasOne) {
|
|
34
|
-
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
35
|
-
const rootValue = entity[localKey];
|
|
36
|
-
if (rootValue === undefined || rootValue === null) continue;
|
|
37
|
-
if (!data || typeof data !== 'object') continue;
|
|
38
|
-
const cache = new Map<string, Record<string, unknown>>();
|
|
39
|
-
cache.set(toKey(rootValue), data as Record<string, unknown>);
|
|
40
|
-
meta.relationHydration.set(relationName, cache);
|
|
41
|
-
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!Array.isArray(data)) continue;
|
|
46
|
-
|
|
47
|
-
if (relation.type === RelationKinds.HasMany || relation.type === RelationKinds.BelongsToMany) {
|
|
48
|
-
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
49
|
-
const rootValue = entity[localKey];
|
|
50
|
-
if (rootValue === undefined || rootValue === null) continue;
|
|
51
|
-
const cache = new Map<string, Rows>();
|
|
52
|
-
cache.set(toKey(rootValue), data as Rows);
|
|
53
|
-
meta.relationHydration.set(relationName, cache);
|
|
54
|
-
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (relation.type === RelationKinds.BelongsTo) {
|
|
59
|
-
const targetKey = relation.localKey || findPrimaryKey(relation.target);
|
|
60
|
-
const cache = new Map<string, Record<string, unknown>>();
|
|
61
|
-
for (const item of data) {
|
|
62
|
-
const pkValue = item[targetKey];
|
|
63
|
-
if (pkValue === undefined || pkValue === null) continue;
|
|
64
|
-
cache.set(toKey(pkValue), item);
|
|
65
|
-
}
|
|
66
|
-
if (cache.size) {
|
|
67
|
-
meta.relationHydration.set(relationName, cache);
|
|
68
|
-
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
1
|
+
import { TableDef } from '../schema/table.js';
|
|
2
|
+
import { RelationKinds, MorphToRelation } from '../schema/relation.js';
|
|
3
|
+
import { findPrimaryKey } from '../query-builder/hydration-planner.js';
|
|
4
|
+
import { EntityMeta } from './entity-meta.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Type representing an array of database rows.
|
|
8
|
+
*/
|
|
9
|
+
type Rows = Record<string, unknown>[];
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Converts a value to a string key.
|
|
13
|
+
* @param value - The value to convert
|
|
14
|
+
* @returns String representation of the value
|
|
15
|
+
*/
|
|
16
|
+
const toKey = (value: unknown): string => (value === null || value === undefined ? '' : String(value));
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Populates the hydration cache with relation data from the database row.
|
|
20
|
+
* @template TTable - The table type
|
|
21
|
+
* @param entity - The entity instance
|
|
22
|
+
* @param row - The database row
|
|
23
|
+
* @param meta - The entity metadata
|
|
24
|
+
*/
|
|
25
|
+
export const populateHydrationCache = <TTable extends TableDef>(
|
|
26
|
+
entity: Record<string, unknown>,
|
|
27
|
+
row: Record<string, unknown>,
|
|
28
|
+
meta: EntityMeta<TTable>
|
|
29
|
+
): void => {
|
|
30
|
+
for (const relationName of Object.keys(meta.table.relations)) {
|
|
31
|
+
const relation = meta.table.relations[relationName];
|
|
32
|
+
const data = row[relationName];
|
|
33
|
+
if (relation.type === RelationKinds.HasOne) {
|
|
34
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
35
|
+
const rootValue = entity[localKey];
|
|
36
|
+
if (rootValue === undefined || rootValue === null) continue;
|
|
37
|
+
if (!data || typeof data !== 'object') continue;
|
|
38
|
+
const cache = new Map<string, Record<string, unknown>>();
|
|
39
|
+
cache.set(toKey(rootValue), data as Record<string, unknown>);
|
|
40
|
+
meta.relationHydration.set(relationName, cache);
|
|
41
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!Array.isArray(data)) continue;
|
|
46
|
+
|
|
47
|
+
if (relation.type === RelationKinds.HasMany || relation.type === RelationKinds.BelongsToMany) {
|
|
48
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
49
|
+
const rootValue = entity[localKey];
|
|
50
|
+
if (rootValue === undefined || rootValue === null) continue;
|
|
51
|
+
const cache = new Map<string, Rows>();
|
|
52
|
+
cache.set(toKey(rootValue), data as Rows);
|
|
53
|
+
meta.relationHydration.set(relationName, cache);
|
|
54
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (relation.type === RelationKinds.BelongsTo) {
|
|
59
|
+
const targetKey = relation.localKey || findPrimaryKey(relation.target);
|
|
60
|
+
const cache = new Map<string, Record<string, unknown>>();
|
|
61
|
+
for (const item of data) {
|
|
62
|
+
const pkValue = item[targetKey];
|
|
63
|
+
if (pkValue === undefined || pkValue === null) continue;
|
|
64
|
+
cache.set(toKey(pkValue), item);
|
|
65
|
+
}
|
|
66
|
+
if (cache.size) {
|
|
67
|
+
meta.relationHydration.set(relationName, cache);
|
|
68
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Second pass for morph relations (data may not be arrays)
|
|
74
|
+
for (const relationName of Object.keys(meta.table.relations)) {
|
|
75
|
+
const relation = meta.table.relations[relationName];
|
|
76
|
+
const data = row[relationName];
|
|
77
|
+
|
|
78
|
+
if (relation.type === RelationKinds.MorphOne) {
|
|
79
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
80
|
+
const rootValue = entity[localKey];
|
|
81
|
+
if (rootValue === undefined || rootValue === null) continue;
|
|
82
|
+
if (!data || typeof data !== 'object') continue;
|
|
83
|
+
const cache = new Map<string, Record<string, unknown>>();
|
|
84
|
+
cache.set(toKey(rootValue), data as Record<string, unknown>);
|
|
85
|
+
meta.relationHydration.set(relationName, cache);
|
|
86
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (relation.type === RelationKinds.MorphMany) {
|
|
91
|
+
if (!Array.isArray(data)) continue;
|
|
92
|
+
const localKey = relation.localKey || findPrimaryKey(meta.table);
|
|
93
|
+
const rootValue = entity[localKey];
|
|
94
|
+
if (rootValue === undefined || rootValue === null) continue;
|
|
95
|
+
const cache = new Map<string, Rows>();
|
|
96
|
+
cache.set(toKey(rootValue), data as Rows);
|
|
97
|
+
meta.relationHydration.set(relationName, cache);
|
|
98
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (relation.type === RelationKinds.MorphTo) {
|
|
103
|
+
if (!data || typeof data !== 'object') continue;
|
|
104
|
+
const morphTo = relation as MorphToRelation;
|
|
105
|
+
const typeValue = entity[morphTo.typeField];
|
|
106
|
+
const idValue = entity[morphTo.idField];
|
|
107
|
+
if (!typeValue || idValue === undefined || idValue === null) continue;
|
|
108
|
+
const compositeKey = `${toKey(typeValue)}:${toKey(idValue)}`;
|
|
109
|
+
const cache = new Map<string, Record<string, unknown>>();
|
|
110
|
+
cache.set(compositeKey, data as Record<string, unknown>);
|
|
111
|
+
meta.relationHydration.set(relationName, cache);
|
|
112
|
+
meta.relationCache.set(relationName, Promise.resolve(cache));
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|