metal-orm 1.1.10 → 1.1.16
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 +758 -769
- package/dist/index.cjs +106 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -5
- package/dist/index.d.ts +5 -5
- package/dist/index.js +106 -43
- package/dist/index.js.map +1 -1
- package/package.json +100 -96
- package/scripts/generate-entities/render.mjs +21 -12
- package/scripts/generate-entities/schema.mjs +209 -195
- package/scripts/generate-entities/tree-detection.mjs +159 -153
- package/scripts/inflection/pt-br.mjs +468 -468
- package/scripts/run-eslint.mjs +33 -34
- package/scripts/show-sql-seed.sql +102 -0
- package/scripts/show-sql.mjs +321 -325
- package/src/bulk/bulk-delete-executor.ts +3 -5
- package/src/bulk/bulk-insert-executor.ts +7 -7
- package/src/bulk/bulk-update-executor.ts +2 -2
- package/src/bulk/bulk-upsert-executor.ts +5 -7
- package/src/codegen/naming-strategy.ts +54 -54
- package/src/codegen/typescript.ts +482 -482
- package/src/core/ast/adapters.ts +1 -1
- package/src/core/ast/builders.ts +123 -123
- package/src/core/ast/expression-builders.ts +745 -745
- package/src/core/ast/expression-nodes.ts +304 -304
- package/src/core/ast/expression-visitor.ts +212 -212
- package/src/core/ast/expression.ts +20 -20
- package/src/core/ast/helpers.ts +14 -14
- package/src/core/ast/join.ts +18 -18
- package/src/core/ast/query.ts +200 -200
- package/src/core/ddl/dialects/base-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/mssql-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/mysql-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/postgres-schema-dialect.ts +1 -1
- package/src/core/ddl/dialects/render-reference.test.ts +70 -70
- package/src/core/ddl/dialects/sqlite-schema-dialect.ts +1 -1
- package/src/core/ddl/introspect/catalogs/index.ts +5 -5
- package/src/core/ddl/introspect/catalogs/postgres.ts +146 -146
- package/src/core/ddl/introspect/context.ts +15 -15
- package/src/core/ddl/introspect/functions/postgres.ts +35 -35
- package/src/core/ddl/introspect/mysql.ts +113 -36
- package/src/core/ddl/introspect/registry.ts +40 -40
- package/src/core/ddl/introspect/run-select.ts +35 -35
- package/src/core/ddl/introspect/utils.ts +56 -56
- package/src/core/ddl/naming-strategy.ts +16 -16
- package/src/core/ddl/schema-dialect.ts +56 -56
- package/src/core/ddl/schema-diff.ts +234 -234
- package/src/core/ddl/schema-generator.ts +1 -1
- package/src/core/ddl/schema-introspect.ts +25 -25
- package/src/core/ddl/sql-writing.ts +171 -171
- package/src/core/dialect/abstract.ts +541 -541
- package/src/core/dialect/base/cte-compiler.ts +33 -33
- package/src/core/dialect/base/function-table-formatter.ts +103 -103
- package/src/core/dialect/base/groupby-compiler.ts +21 -21
- package/src/core/dialect/base/join-compiler.ts +25 -25
- package/src/core/dialect/base/orderby-compiler.ts +35 -35
- package/src/core/dialect/base/pagination-strategy.ts +32 -32
- package/src/core/dialect/base/returning-strategy.ts +57 -57
- package/src/core/dialect/base/sql-dialect.ts +294 -294
- package/src/core/dialect/dialect-factory.ts +91 -91
- package/src/core/dialect/mssql/functions.ts +120 -120
- package/src/core/dialect/mssql/index.ts +317 -317
- package/src/core/dialect/mysql/functions.ts +103 -103
- package/src/core/dialect/mysql/index.ts +105 -105
- package/src/core/dialect/postgres/functions.ts +108 -108
- package/src/core/dialect/postgres/index.ts +91 -91
- package/src/core/dialect/sqlite/functions.ts +129 -129
- package/src/core/dialect/sqlite/index.ts +67 -67
- package/src/core/driver/database-driver.ts +19 -19
- package/src/core/driver/mssql-driver.ts +23 -23
- package/src/core/driver/mysql-driver.ts +23 -23
- package/src/core/driver/postgres-driver.ts +23 -23
- package/src/core/driver/sqlite-driver.ts +23 -23
- package/src/core/execution/db-executor.ts +92 -92
- package/src/core/execution/executors/better-sqlite3-executor.ts +94 -94
- package/src/core/execution/executors/mssql-executor.ts +184 -184
- package/src/core/execution/executors/mysql-executor.ts +88 -88
- package/src/core/execution/executors/postgres-executor.ts +26 -26
- package/src/core/execution/executors/sqlite-executor.ts +42 -42
- package/src/core/execution/pooling/pool-types.ts +30 -30
- package/src/core/execution/pooling/pool.ts +275 -275
- package/src/core/functions/array.ts +35 -35
- package/src/core/functions/control-flow.ts +79 -79
- package/src/core/functions/datetime.ts +237 -237
- package/src/core/functions/json.ts +70 -70
- package/src/core/functions/numeric.ts +297 -297
- package/src/core/functions/text.ts +334 -334
- package/src/core/functions/types.ts +33 -33
- package/src/core/hydration/types.ts +51 -51
- package/src/core/sql/sql-operator-config.ts +39 -39
- package/src/core/sql/sql.ts +152 -152
- package/src/decorators/column-decorator.ts +87 -87
- package/src/decorators/decorator-metadata.ts +143 -143
- package/src/decorators/entity.ts +93 -93
- package/src/decorators/index.ts +39 -39
- package/src/decorators/relations.ts +231 -231
- package/src/decorators/transformers/built-in/string-transformers.ts +231 -231
- package/src/decorators/transformers/transformer-decorators.ts +134 -134
- package/src/decorators/transformers/transformer-executor.ts +171 -171
- package/src/decorators/transformers/transformer-metadata.ts +73 -73
- package/src/decorators/validators/built-in/br-cep-validator.ts +55 -55
- package/src/decorators/validators/built-in/br-cnpj-validator.ts +105 -105
- package/src/decorators/validators/built-in/br-cpf-validator.ts +103 -103
- package/src/decorators/validators/country-validator-registry.ts +64 -64
- package/src/decorators/validators/country-validators-decorators.ts +203 -203
- package/src/decorators/validators/country-validators.ts +105 -105
- package/src/decorators/validators/validator-metadata.ts +59 -59
- package/src/dto/dto-types.ts +226 -226
- package/src/dto/filter-types.ts +141 -141
- package/src/dto/index.ts +95 -95
- package/src/dto/openapi/generators/base.ts +29 -29
- package/src/dto/openapi/generators/column.ts +37 -37
- package/src/dto/openapi/generators/dto.ts +91 -91
- package/src/dto/openapi/generators/filter.ts +75 -75
- package/src/dto/openapi/generators/nested-dto.ts +618 -618
- package/src/dto/openapi/generators/pagination.ts +111 -111
- package/src/dto/openapi/generators/relation-filter.ts +228 -228
- package/src/dto/openapi/index.ts +12 -12
- package/src/dto/openapi/types.ts +101 -101
- package/src/dto/openapi/utilities.ts +95 -95
- package/src/dto/pagination-utils.ts +150 -150
- package/src/dto/transform.ts +197 -197
- package/src/index.ts +86 -86
- package/src/orm/als.ts +58 -58
- package/src/orm/domain-event-bus.ts +119 -119
- package/src/orm/entity-context.ts +86 -86
- package/src/orm/entity-materializer.ts +159 -159
- package/src/orm/entity-meta.ts +97 -97
- package/src/orm/entity-registry.ts +39 -39
- package/src/orm/entity-relation-cache.ts +39 -39
- package/src/orm/execute.ts +194 -194
- package/src/orm/execution-context.ts +18 -18
- package/src/orm/hydration-context.ts +26 -26
- package/src/orm/hydration.ts +112 -112
- package/src/orm/identity-map.ts +61 -61
- package/src/orm/interceptor-pipeline.ts +16 -16
- package/src/orm/lazy-batch/belongs-to-many.ts +119 -119
- package/src/orm/lazy-batch/belongs-to.ts +108 -108
- package/src/orm/lazy-batch/has-many.ts +69 -69
- package/src/orm/lazy-batch/has-one.ts +68 -68
- package/src/orm/lazy-batch/shared.ts +125 -125
- package/src/orm/orm-session.ts +620 -620
- package/src/orm/orm.ts +34 -34
- package/src/orm/pooled-executor-factory.ts +121 -121
- package/src/orm/query-logger.ts +40 -40
- package/src/orm/relation-change-processor.ts +420 -420
- 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 -156
- package/src/orm/relations/morph-one.ts +151 -151
- package/src/orm/relations/morph-to.ts +162 -162
- package/src/orm/runtime-types.ts +92 -92
- package/src/orm/save-graph.ts +561 -561
- package/src/orm/transaction-runner.ts +24 -24
- package/src/orm/unit-of-work.ts +426 -426
- package/src/query/index.ts +69 -69
- package/src/query/target.ts +46 -46
- package/src/query-builder/column-selector.ts +81 -81
- package/src/query-builder/delete.ts +141 -141
- package/src/query-builder/insert-query-state.ts +149 -149
- package/src/query-builder/insert.ts +117 -117
- package/src/query-builder/query-ast-service.ts +287 -287
- package/src/query-builder/query-resolution.ts +78 -78
- package/src/query-builder/raw-column-parser.ts +38 -38
- package/src/query-builder/relation-filter-utils.ts +153 -153
- package/src/query-builder/relation-join-planner.ts +10 -10
- package/src/query-builder/relation-manager.ts +87 -87
- package/src/query-builder/relation-projection-helper.ts +102 -102
- package/src/query-builder/relation-types.ts +9 -9
- package/src/query-builder/relation-utils.ts +15 -15
- package/src/query-builder/select/cte-facet.ts +40 -40
- package/src/query-builder/select/from-facet.ts +80 -80
- package/src/query-builder/select/join-facet.ts +62 -62
- package/src/query-builder/select/predicate-facet.ts +104 -104
- package/src/query-builder/select/projection-facet.ts +70 -70
- package/src/query-builder/select/relation-facet.ts +81 -81
- package/src/query-builder/select/setop-facet.ts +36 -36
- package/src/query-builder/select-helpers.ts +1 -1
- package/src/query-builder/select-query-builder-deps.ts +130 -130
- package/src/query-builder/select-query-state.ts +207 -207
- package/src/query-builder/update.ts +151 -151
- package/src/schema/column-types.ts +322 -322
- package/src/schema/table-guards.ts +37 -37
- package/src/schema/table.ts +281 -281
- package/src/tree/index.ts +13 -13
- package/src/tree/nested-set-strategy.ts +545 -545
- package/src/tree/tree-decorator.ts +397 -397
- package/src/tree/tree-manager.ts +754 -754
- package/src/tree/tree-query.ts +427 -427
- package/src/tree/tree-types.ts +299 -299
|
@@ -1,162 +1,162 @@
|
|
|
1
|
-
import { BelongsToReferenceApi } from '../../schema/types.js';
|
|
2
|
-
import { EntityContext } from '../entity-context.js';
|
|
3
|
-
import { RelationKey } from '../runtime-types.js';
|
|
4
|
-
import { MorphToRelation } from '../../schema/relation.js';
|
|
5
|
-
import { TableDef } from '../../schema/table.js';
|
|
6
|
-
import { EntityMeta, getHydrationRecord, hasEntityMeta } from '../entity-meta.js';
|
|
7
|
-
|
|
8
|
-
type Row = Record<string, unknown>;
|
|
9
|
-
|
|
10
|
-
const toKey = (value: unknown): string => (value === null || value === undefined ? '' : String(value));
|
|
11
|
-
|
|
12
|
-
const hideInternal = (obj: object, keys: string[]): void => {
|
|
13
|
-
for (const key of keys) {
|
|
14
|
-
Object.defineProperty(obj, key, {
|
|
15
|
-
value: obj[key],
|
|
16
|
-
writable: false,
|
|
17
|
-
configurable: false,
|
|
18
|
-
enumerable: false
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const hideWritable = (obj: object, keys: string[]): void => {
|
|
24
|
-
for (const key of keys) {
|
|
25
|
-
const value = obj[key as keyof typeof obj];
|
|
26
|
-
Object.defineProperty(obj, key, {
|
|
27
|
-
value,
|
|
28
|
-
writable: true,
|
|
29
|
-
configurable: true,
|
|
30
|
-
enumerable: false
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export class DefaultMorphToReference<TParent extends object> implements BelongsToReferenceApi<TParent> {
|
|
36
|
-
private loaded = false;
|
|
37
|
-
private current: TParent | null = null;
|
|
38
|
-
|
|
39
|
-
constructor(
|
|
40
|
-
private readonly ctx: EntityContext,
|
|
41
|
-
private readonly meta: EntityMeta<TableDef>,
|
|
42
|
-
private readonly root: unknown,
|
|
43
|
-
private readonly relationName: string,
|
|
44
|
-
private readonly relation: MorphToRelation,
|
|
45
|
-
private readonly rootTable: TableDef,
|
|
46
|
-
private readonly loader: () => Promise<Map<string, Row>>,
|
|
47
|
-
private readonly createEntity: (table: TableDef, row: Row) => TParent,
|
|
48
|
-
private readonly resolveTargetTable: (typeValue: string) => TableDef | undefined
|
|
49
|
-
) {
|
|
50
|
-
hideInternal(this, [
|
|
51
|
-
'ctx', 'meta', 'root', 'relationName', 'relation',
|
|
52
|
-
'rootTable', 'loader', 'createEntity', 'resolveTargetTable'
|
|
53
|
-
]);
|
|
54
|
-
hideWritable(this, ['loaded', 'current']);
|
|
55
|
-
this.populateFromHydrationCache();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async load(): Promise<TParent | null> {
|
|
59
|
-
if (this.loaded) return this.current;
|
|
60
|
-
const rootObj = this.root as Row;
|
|
61
|
-
const typeValue = rootObj[this.relation.typeField];
|
|
62
|
-
const idValue = rootObj[this.relation.idField];
|
|
63
|
-
if (!typeValue || idValue === undefined || idValue === null) {
|
|
64
|
-
this.loaded = true;
|
|
65
|
-
return this.current;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const map = await this.loader();
|
|
69
|
-
const compositeKey = `${toKey(typeValue)}:${toKey(idValue)}`;
|
|
70
|
-
const row = map.get(compositeKey);
|
|
71
|
-
if (row) {
|
|
72
|
-
const targetTable = this.resolveTargetTable(toKey(typeValue));
|
|
73
|
-
if (targetTable) {
|
|
74
|
-
this.current = this.createEntity(targetTable, row);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
this.loaded = true;
|
|
78
|
-
return this.current;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
get(): TParent | null {
|
|
82
|
-
return this.current;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
set(data: Partial<TParent> | TParent | null): TParent | null {
|
|
86
|
-
if (data === null) {
|
|
87
|
-
return this.detachCurrent();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const entity = hasEntityMeta(data) ? (data as TParent) : (data as TParent);
|
|
91
|
-
if (this.current && this.current !== entity) {
|
|
92
|
-
this.ctx.registerRelationChange(
|
|
93
|
-
this.root,
|
|
94
|
-
this.relationKey,
|
|
95
|
-
this.rootTable,
|
|
96
|
-
this.relationName,
|
|
97
|
-
this.relation,
|
|
98
|
-
{ kind: 'remove', entity: this.current }
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
this.current = entity;
|
|
103
|
-
this.loaded = true;
|
|
104
|
-
|
|
105
|
-
this.ctx.registerRelationChange(
|
|
106
|
-
this.root,
|
|
107
|
-
this.relationKey,
|
|
108
|
-
this.rootTable,
|
|
109
|
-
this.relationName,
|
|
110
|
-
this.relation,
|
|
111
|
-
{ kind: 'attach', entity }
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
return entity;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
toJSON(): unknown {
|
|
118
|
-
if (!this.current) return null;
|
|
119
|
-
const entityWithToJSON = this.current as { toJSON?: () => unknown };
|
|
120
|
-
return typeof entityWithToJSON.toJSON === 'function'
|
|
121
|
-
? entityWithToJSON.toJSON()
|
|
122
|
-
: this.current;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
private detachCurrent(): TParent | null {
|
|
126
|
-
const previous = this.current;
|
|
127
|
-
if (!previous) return null;
|
|
128
|
-
this.current = null;
|
|
129
|
-
this.loaded = true;
|
|
130
|
-
const rootObj = this.root as Row;
|
|
131
|
-
rootObj[this.relation.typeField] = null;
|
|
132
|
-
rootObj[this.relation.idField] = null;
|
|
133
|
-
this.ctx.registerRelationChange(
|
|
134
|
-
this.root,
|
|
135
|
-
this.relationKey,
|
|
136
|
-
this.rootTable,
|
|
137
|
-
this.relationName,
|
|
138
|
-
this.relation,
|
|
139
|
-
{ kind: 'remove', entity: previous }
|
|
140
|
-
);
|
|
141
|
-
return null;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private get relationKey(): RelationKey {
|
|
145
|
-
return `${this.rootTable.name}.${this.relationName}`;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
private populateFromHydrationCache(): void {
|
|
149
|
-
const rootObj = this.root as Row;
|
|
150
|
-
const typeValue = rootObj[this.relation.typeField];
|
|
151
|
-
const idValue = rootObj[this.relation.idField];
|
|
152
|
-
if (!typeValue || idValue === undefined || idValue === null) return;
|
|
153
|
-
const compositeKey = `${toKey(typeValue)}:${toKey(idValue)}`;
|
|
154
|
-
const row = getHydrationRecord(this.meta, this.relationName, compositeKey);
|
|
155
|
-
if (!row) return;
|
|
156
|
-
const targetTable = this.resolveTargetTable(toKey(typeValue));
|
|
157
|
-
if (targetTable) {
|
|
158
|
-
this.current = this.createEntity(targetTable, row);
|
|
159
|
-
this.loaded = true;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
1
|
+
import { BelongsToReferenceApi } from '../../schema/types.js';
|
|
2
|
+
import { EntityContext } from '../entity-context.js';
|
|
3
|
+
import { RelationKey } from '../runtime-types.js';
|
|
4
|
+
import { MorphToRelation } from '../../schema/relation.js';
|
|
5
|
+
import { TableDef } from '../../schema/table.js';
|
|
6
|
+
import { EntityMeta, getHydrationRecord, hasEntityMeta } from '../entity-meta.js';
|
|
7
|
+
|
|
8
|
+
type Row = Record<string, unknown>;
|
|
9
|
+
|
|
10
|
+
const toKey = (value: unknown): string => (value === null || value === undefined ? '' : String(value));
|
|
11
|
+
|
|
12
|
+
const hideInternal = (obj: object, keys: string[]): void => {
|
|
13
|
+
for (const key of keys) {
|
|
14
|
+
Object.defineProperty(obj, key, {
|
|
15
|
+
value: obj[key],
|
|
16
|
+
writable: false,
|
|
17
|
+
configurable: false,
|
|
18
|
+
enumerable: false
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const hideWritable = (obj: object, keys: string[]): void => {
|
|
24
|
+
for (const key of keys) {
|
|
25
|
+
const value = obj[key as keyof typeof obj];
|
|
26
|
+
Object.defineProperty(obj, key, {
|
|
27
|
+
value,
|
|
28
|
+
writable: true,
|
|
29
|
+
configurable: true,
|
|
30
|
+
enumerable: false
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export class DefaultMorphToReference<TParent extends object> implements BelongsToReferenceApi<TParent> {
|
|
36
|
+
private loaded = false;
|
|
37
|
+
private current: TParent | null = null;
|
|
38
|
+
|
|
39
|
+
constructor(
|
|
40
|
+
private readonly ctx: EntityContext,
|
|
41
|
+
private readonly meta: EntityMeta<TableDef>,
|
|
42
|
+
private readonly root: unknown,
|
|
43
|
+
private readonly relationName: string,
|
|
44
|
+
private readonly relation: MorphToRelation,
|
|
45
|
+
private readonly rootTable: TableDef,
|
|
46
|
+
private readonly loader: () => Promise<Map<string, Row>>,
|
|
47
|
+
private readonly createEntity: (table: TableDef, row: Row) => TParent,
|
|
48
|
+
private readonly resolveTargetTable: (typeValue: string) => TableDef | undefined
|
|
49
|
+
) {
|
|
50
|
+
hideInternal(this, [
|
|
51
|
+
'ctx', 'meta', 'root', 'relationName', 'relation',
|
|
52
|
+
'rootTable', 'loader', 'createEntity', 'resolveTargetTable'
|
|
53
|
+
]);
|
|
54
|
+
hideWritable(this, ['loaded', 'current']);
|
|
55
|
+
this.populateFromHydrationCache();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async load(): Promise<TParent | null> {
|
|
59
|
+
if (this.loaded) return this.current;
|
|
60
|
+
const rootObj = this.root as Row;
|
|
61
|
+
const typeValue = rootObj[this.relation.typeField];
|
|
62
|
+
const idValue = rootObj[this.relation.idField];
|
|
63
|
+
if (!typeValue || idValue === undefined || idValue === null) {
|
|
64
|
+
this.loaded = true;
|
|
65
|
+
return this.current;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const map = await this.loader();
|
|
69
|
+
const compositeKey = `${toKey(typeValue)}:${toKey(idValue)}`;
|
|
70
|
+
const row = map.get(compositeKey);
|
|
71
|
+
if (row) {
|
|
72
|
+
const targetTable = this.resolveTargetTable(toKey(typeValue));
|
|
73
|
+
if (targetTable) {
|
|
74
|
+
this.current = this.createEntity(targetTable, row);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
this.loaded = true;
|
|
78
|
+
return this.current;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
get(): TParent | null {
|
|
82
|
+
return this.current;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
set(data: Partial<TParent> | TParent | null): TParent | null {
|
|
86
|
+
if (data === null) {
|
|
87
|
+
return this.detachCurrent();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const entity = hasEntityMeta(data) ? (data as TParent) : (data as TParent);
|
|
91
|
+
if (this.current && this.current !== entity) {
|
|
92
|
+
this.ctx.registerRelationChange(
|
|
93
|
+
this.root,
|
|
94
|
+
this.relationKey,
|
|
95
|
+
this.rootTable,
|
|
96
|
+
this.relationName,
|
|
97
|
+
this.relation,
|
|
98
|
+
{ kind: 'remove', entity: this.current }
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.current = entity;
|
|
103
|
+
this.loaded = true;
|
|
104
|
+
|
|
105
|
+
this.ctx.registerRelationChange(
|
|
106
|
+
this.root,
|
|
107
|
+
this.relationKey,
|
|
108
|
+
this.rootTable,
|
|
109
|
+
this.relationName,
|
|
110
|
+
this.relation,
|
|
111
|
+
{ kind: 'attach', entity }
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return entity;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
toJSON(): unknown {
|
|
118
|
+
if (!this.current) return null;
|
|
119
|
+
const entityWithToJSON = this.current as { toJSON?: () => unknown };
|
|
120
|
+
return typeof entityWithToJSON.toJSON === 'function'
|
|
121
|
+
? entityWithToJSON.toJSON()
|
|
122
|
+
: this.current;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private detachCurrent(): TParent | null {
|
|
126
|
+
const previous = this.current;
|
|
127
|
+
if (!previous) return null;
|
|
128
|
+
this.current = null;
|
|
129
|
+
this.loaded = true;
|
|
130
|
+
const rootObj = this.root as Row;
|
|
131
|
+
rootObj[this.relation.typeField] = null;
|
|
132
|
+
rootObj[this.relation.idField] = null;
|
|
133
|
+
this.ctx.registerRelationChange(
|
|
134
|
+
this.root,
|
|
135
|
+
this.relationKey,
|
|
136
|
+
this.rootTable,
|
|
137
|
+
this.relationName,
|
|
138
|
+
this.relation,
|
|
139
|
+
{ kind: 'remove', entity: previous }
|
|
140
|
+
);
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private get relationKey(): RelationKey {
|
|
145
|
+
return `${this.rootTable.name}.${this.relationName}`;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private populateFromHydrationCache(): void {
|
|
149
|
+
const rootObj = this.root as Row;
|
|
150
|
+
const typeValue = rootObj[this.relation.typeField];
|
|
151
|
+
const idValue = rootObj[this.relation.idField];
|
|
152
|
+
if (!typeValue || idValue === undefined || idValue === null) return;
|
|
153
|
+
const compositeKey = `${toKey(typeValue)}:${toKey(idValue)}`;
|
|
154
|
+
const row = getHydrationRecord(this.meta, this.relationName, compositeKey);
|
|
155
|
+
if (!row) return;
|
|
156
|
+
const targetTable = this.resolveTargetTable(toKey(typeValue));
|
|
157
|
+
if (targetTable) {
|
|
158
|
+
this.current = this.createEntity(targetTable, row);
|
|
159
|
+
this.loaded = true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
package/src/orm/runtime-types.ts
CHANGED
|
@@ -1,98 +1,98 @@
|
|
|
1
|
-
import { RelationDef } from '../schema/relation.js';
|
|
2
|
-
import { TableDef } from '../schema/table.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Entity status enum representing the lifecycle state of an entity
|
|
6
|
-
*/
|
|
7
|
-
export enum EntityStatus {
|
|
8
|
-
/** Entity is newly created and not yet persisted */
|
|
9
|
-
New = 'new',
|
|
10
|
-
/** Entity is managed by the ORM and synchronized with the database */
|
|
11
|
-
Managed = 'managed',
|
|
12
|
-
/** Entity has been modified but not yet persisted */
|
|
13
|
-
Dirty = 'dirty',
|
|
14
|
-
/** Entity has been marked for removal */
|
|
15
|
-
Removed = 'removed',
|
|
16
|
-
/** Entity is detached from the ORM context */
|
|
17
|
-
Detached = 'detached'
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Represents an entity being tracked by the ORM
|
|
22
|
-
*/
|
|
23
|
-
export interface TrackedEntity {
|
|
24
|
-
/** The table definition this entity belongs to */
|
|
25
|
-
table: TableDef;
|
|
26
|
-
/** The actual entity instance */
|
|
27
|
-
entity: object;
|
|
28
|
-
/** Primary key value of the entity */
|
|
29
|
-
pk: string | number | null;
|
|
30
|
-
/** Current status of the entity */
|
|
31
|
-
status: EntityStatus;
|
|
32
|
-
/** Original values of the entity when it was loaded */
|
|
33
|
-
original: Record<string, unknown> | null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Type representing a key for relation navigation
|
|
38
|
-
*/
|
|
39
|
-
export type RelationKey = string;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Represents a change operation on a relation
|
|
43
|
-
* @typeParam T - Type of the related entity
|
|
44
|
-
*/
|
|
1
|
+
import { RelationDef } from '../schema/relation.js';
|
|
2
|
+
import { TableDef } from '../schema/table.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Entity status enum representing the lifecycle state of an entity
|
|
6
|
+
*/
|
|
7
|
+
export enum EntityStatus {
|
|
8
|
+
/** Entity is newly created and not yet persisted */
|
|
9
|
+
New = 'new',
|
|
10
|
+
/** Entity is managed by the ORM and synchronized with the database */
|
|
11
|
+
Managed = 'managed',
|
|
12
|
+
/** Entity has been modified but not yet persisted */
|
|
13
|
+
Dirty = 'dirty',
|
|
14
|
+
/** Entity has been marked for removal */
|
|
15
|
+
Removed = 'removed',
|
|
16
|
+
/** Entity is detached from the ORM context */
|
|
17
|
+
Detached = 'detached'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Represents an entity being tracked by the ORM
|
|
22
|
+
*/
|
|
23
|
+
export interface TrackedEntity {
|
|
24
|
+
/** The table definition this entity belongs to */
|
|
25
|
+
table: TableDef;
|
|
26
|
+
/** The actual entity instance */
|
|
27
|
+
entity: object;
|
|
28
|
+
/** Primary key value of the entity */
|
|
29
|
+
pk: string | number | null;
|
|
30
|
+
/** Current status of the entity */
|
|
31
|
+
status: EntityStatus;
|
|
32
|
+
/** Original values of the entity when it was loaded */
|
|
33
|
+
original: Record<string, unknown> | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Type representing a key for relation navigation
|
|
38
|
+
*/
|
|
39
|
+
export type RelationKey = string;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Represents a change operation on a relation
|
|
43
|
+
* @typeParam T - Type of the related entity
|
|
44
|
+
*/
|
|
45
45
|
export type RelationChange<T> =
|
|
46
46
|
| { kind: 'add'; entity: T; pivot?: Record<string, unknown> }
|
|
47
47
|
| { kind: 'attach'; entity: T; pivot?: Record<string, unknown> }
|
|
48
48
|
| { kind: 'update'; entity: T; pivot: Record<string, unknown> }
|
|
49
49
|
| { kind: 'remove'; entity: T; pivot?: Record<string, unknown> }
|
|
50
50
|
| { kind: 'detach'; entity: T; pivot?: Record<string, unknown> };
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Represents a relation change entry in the unit of work
|
|
54
|
-
*/
|
|
55
|
-
export interface RelationChangeEntry {
|
|
56
|
-
/** Root entity that owns the relation */
|
|
57
|
-
root: unknown;
|
|
58
|
-
/** Key of the relation being changed */
|
|
59
|
-
relationKey: RelationKey;
|
|
60
|
-
/** Table definition of the root entity */
|
|
61
|
-
rootTable: TableDef;
|
|
62
|
-
/** Name of the relation */
|
|
63
|
-
relationName: string;
|
|
64
|
-
/** Relation definition */
|
|
65
|
-
relation: RelationDef;
|
|
66
|
-
/** The change being applied */
|
|
67
|
-
change: RelationChange<unknown>;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Represents a domain event that can be emitted by entities
|
|
72
|
-
* @typeParam TType - Type of the event (string literal)
|
|
73
|
-
*/
|
|
74
|
-
export interface DomainEvent<TType extends string = string> {
|
|
75
|
-
/** Type identifier for the event */
|
|
76
|
-
readonly type: TType;
|
|
77
|
-
/** Timestamp when the event occurred */
|
|
78
|
-
readonly occurredAt?: Date;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Type representing any domain event
|
|
83
|
-
*/
|
|
84
|
-
export type AnyDomainEvent = DomainEvent<string>;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Type representing ORM-specific domain events
|
|
88
|
-
*/
|
|
89
|
-
export type OrmDomainEvent = AnyDomainEvent;
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Interface for entities that can emit domain events
|
|
93
|
-
* @typeParam E - Type of domain events this entity can emit
|
|
94
|
-
*/
|
|
95
|
-
export interface HasDomainEvents<E extends DomainEvent = AnyDomainEvent> {
|
|
96
|
-
/** Array of domain events emitted by this entity */
|
|
97
|
-
domainEvents?: E[];
|
|
98
|
-
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Represents a relation change entry in the unit of work
|
|
54
|
+
*/
|
|
55
|
+
export interface RelationChangeEntry {
|
|
56
|
+
/** Root entity that owns the relation */
|
|
57
|
+
root: unknown;
|
|
58
|
+
/** Key of the relation being changed */
|
|
59
|
+
relationKey: RelationKey;
|
|
60
|
+
/** Table definition of the root entity */
|
|
61
|
+
rootTable: TableDef;
|
|
62
|
+
/** Name of the relation */
|
|
63
|
+
relationName: string;
|
|
64
|
+
/** Relation definition */
|
|
65
|
+
relation: RelationDef;
|
|
66
|
+
/** The change being applied */
|
|
67
|
+
change: RelationChange<unknown>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Represents a domain event that can be emitted by entities
|
|
72
|
+
* @typeParam TType - Type of the event (string literal)
|
|
73
|
+
*/
|
|
74
|
+
export interface DomainEvent<TType extends string = string> {
|
|
75
|
+
/** Type identifier for the event */
|
|
76
|
+
readonly type: TType;
|
|
77
|
+
/** Timestamp when the event occurred */
|
|
78
|
+
readonly occurredAt?: Date;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Type representing any domain event
|
|
83
|
+
*/
|
|
84
|
+
export type AnyDomainEvent = DomainEvent<string>;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Type representing ORM-specific domain events
|
|
88
|
+
*/
|
|
89
|
+
export type OrmDomainEvent = AnyDomainEvent;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Interface for entities that can emit domain events
|
|
93
|
+
* @typeParam E - Type of domain events this entity can emit
|
|
94
|
+
*/
|
|
95
|
+
export interface HasDomainEvents<E extends DomainEvent = AnyDomainEvent> {
|
|
96
|
+
/** Array of domain events emitted by this entity */
|
|
97
|
+
domainEvents?: E[];
|
|
98
|
+
}
|