metal-orm 1.0.33 → 1.0.34
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 +7 -5
- package/dist/index.cjs +295 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2585 -98
- package/dist/index.d.ts +2585 -98
- package/dist/index.js +285 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -6
- package/scripts/generate-entities.mjs +1 -1
- package/src/index.ts +1 -0
- package/src/orm/entity.ts +5 -5
- package/src/orm/execute.ts +4 -4
- package/src/orm/orm-session.ts +229 -229
- package/src/query-builder/select.ts +885 -886
- package/src/schema/types.ts +39 -39
- package/dist/decorators/index.cjs +0 -4968
- package/dist/decorators/index.cjs.map +0 -1
- package/dist/decorators/index.d.cts +0 -70
- package/dist/decorators/index.d.ts +0 -70
- package/dist/decorators/index.js +0 -4933
- package/dist/decorators/index.js.map +0 -1
- package/dist/select-BuMpVcVt.d.cts +0 -2424
- package/dist/select-BuMpVcVt.d.ts +0 -2424
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metal-orm",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.34",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"engines": {
|
|
@@ -14,11 +14,6 @@
|
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
15
|
"import": "./dist/index.js",
|
|
16
16
|
"require": "./dist/index.cjs"
|
|
17
|
-
},
|
|
18
|
-
"./decorators": {
|
|
19
|
-
"types": "./dist/decorators/index.d.ts",
|
|
20
|
-
"import": "./dist/decorators/index.js",
|
|
21
|
-
"require": "./dist/decorators/index.cjs"
|
|
22
17
|
}
|
|
23
18
|
},
|
|
24
19
|
"files": [
|
|
@@ -438,7 +438,7 @@ const renderEntityFile = (schema, options) => {
|
|
|
438
438
|
];
|
|
439
439
|
const decoratorImports = decoratorOrder.filter(name => decoratorSet.has(name));
|
|
440
440
|
if (decoratorImports.length) {
|
|
441
|
-
imports.push(`import { ${decoratorImports.join(', ')} } from 'metal-orm
|
|
441
|
+
imports.push(`import { ${decoratorImports.join(', ')} } from 'metal-orm';`);
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
const ormTypes = [];
|
package/src/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ export * from './orm/hydration-context.js';
|
|
|
38
38
|
export * from './orm/domain-event-bus.js';
|
|
39
39
|
export * from './orm/runtime-types.js';
|
|
40
40
|
export * from './orm/query-logger.js';
|
|
41
|
+
export * from './decorators/index.js';
|
|
41
42
|
|
|
42
43
|
// NEW: execution abstraction + helpers
|
|
43
44
|
export * from './core/execution/db-executor.js';
|
package/src/orm/entity.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import {
|
|
2
|
+
import { EntityInstance, RelationMap, HasManyCollection, HasOneReference, BelongsToReference, ManyToManyCollection } from '../schema/types.js';
|
|
3
3
|
import { EntityContext } from './entity-context.js';
|
|
4
4
|
import { ENTITY_META, EntityMeta, getEntityMeta } from './entity-meta.js';
|
|
5
5
|
import { DefaultHasManyCollection } from './relations/has-many.js';
|
|
@@ -49,7 +49,7 @@ export const createEntityProxy = <
|
|
|
49
49
|
table: TTable,
|
|
50
50
|
row: Record<string, any>,
|
|
51
51
|
lazyRelations: TLazy[] = [] as TLazy[]
|
|
52
|
-
):
|
|
52
|
+
): EntityInstance<TTable> => {
|
|
53
53
|
const target: Record<string, any> = { ...row };
|
|
54
54
|
const meta: EntityMeta<TTable> = {
|
|
55
55
|
ctx,
|
|
@@ -66,7 +66,7 @@ export const createEntityProxy = <
|
|
|
66
66
|
writable: false
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
let proxy:
|
|
69
|
+
let proxy: EntityInstance<TTable>;
|
|
70
70
|
const handler: ProxyHandler<any> = {
|
|
71
71
|
get(targetObj, prop, receiver) {
|
|
72
72
|
if (prop === ENTITY_META) {
|
|
@@ -99,7 +99,7 @@ export const createEntityProxy = <
|
|
|
99
99
|
}
|
|
100
100
|
};
|
|
101
101
|
|
|
102
|
-
proxy = new Proxy(target, handler) as
|
|
102
|
+
proxy = new Proxy(target, handler) as EntityInstance<TTable>;
|
|
103
103
|
populateHydrationCache(proxy, row, meta);
|
|
104
104
|
return proxy;
|
|
105
105
|
};
|
|
@@ -109,7 +109,7 @@ export const createEntityFromRow = <TTable extends TableDef>(
|
|
|
109
109
|
table: TTable,
|
|
110
110
|
row: Record<string, any>,
|
|
111
111
|
lazyRelations: (keyof RelationMap<TTable>)[] = []
|
|
112
|
-
):
|
|
112
|
+
): EntityInstance<TTable> => {
|
|
113
113
|
const pkName = findPrimaryKey(table);
|
|
114
114
|
const pkValue = row[pkName];
|
|
115
115
|
if (pkValue !== undefined && pkValue !== null) {
|
package/src/orm/execute.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TableDef } from '../schema/table.js';
|
|
2
|
-
import {
|
|
2
|
+
import { EntityInstance } from '../schema/types.js';
|
|
3
3
|
import { hydrateRows } from './hydration.js';
|
|
4
4
|
import { OrmSession } from './orm-session.ts';
|
|
5
5
|
import { SelectQueryBuilder } from '../query-builder/select.js';
|
|
@@ -28,7 +28,7 @@ const flattenResults = (results: { columns: string[]; values: unknown[][] }[]):
|
|
|
28
28
|
const executeWithEntityContext = async <TTable extends TableDef>(
|
|
29
29
|
entityCtx: EntityContext,
|
|
30
30
|
qb: SelectQueryBuilder<any, TTable>
|
|
31
|
-
): Promise<
|
|
31
|
+
): Promise<EntityInstance<TTable>[]> => {
|
|
32
32
|
const ast = qb.getAST();
|
|
33
33
|
const compiled = entityCtx.dialect.compileSelect(ast);
|
|
34
34
|
const executed = await entityCtx.executor.executeSql(compiled.sql, compiled.params);
|
|
@@ -45,7 +45,7 @@ const executeWithEntityContext = async <TTable extends TableDef>(
|
|
|
45
45
|
export async function executeHydrated<TTable extends TableDef>(
|
|
46
46
|
session: OrmSession,
|
|
47
47
|
qb: SelectQueryBuilder<any, TTable>
|
|
48
|
-
): Promise<
|
|
48
|
+
): Promise<EntityInstance<TTable>[]> {
|
|
49
49
|
return executeWithEntityContext(session, qb);
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -53,7 +53,7 @@ export async function executeHydratedWithContexts<TTable extends TableDef>(
|
|
|
53
53
|
_execCtx: ExecutionContext,
|
|
54
54
|
hydCtx: HydrationContext,
|
|
55
55
|
qb: SelectQueryBuilder<any, TTable>
|
|
56
|
-
): Promise<
|
|
56
|
+
): Promise<EntityInstance<TTable>[]> {
|
|
57
57
|
const entityCtx = hydCtx.entityContext;
|
|
58
58
|
if (!entityCtx) {
|
|
59
59
|
throw new Error('Hydration context is missing an EntityContext');
|
package/src/orm/orm-session.ts
CHANGED
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
import { Dialect } from '../core/dialect/abstract.js';
|
|
2
|
-
import { eq } from '../core/ast/expression.js';
|
|
3
|
-
import type { DbExecutor } from '../core/execution/db-executor.js';
|
|
1
|
+
import { Dialect } from '../core/dialect/abstract.js';
|
|
2
|
+
import { eq } from '../core/ast/expression.js';
|
|
3
|
+
import type { DbExecutor } from '../core/execution/db-executor.js';
|
|
4
4
|
import { SelectQueryBuilder } from '../query-builder/select.js';
|
|
5
5
|
import { findPrimaryKey } from '../query-builder/hydration-planner.js';
|
|
6
6
|
import type { ColumnDef } from '../schema/column.js';
|
|
7
7
|
import type { TableDef } from '../schema/table.js';
|
|
8
|
-
import {
|
|
9
|
-
import { RelationDef } from '../schema/relation.js';
|
|
10
|
-
|
|
11
|
-
import { selectFromEntity, getTableDefFromEntity } from '../decorators/bootstrap.js';
|
|
12
|
-
import type { EntityConstructor } from './entity-metadata.js';
|
|
13
|
-
import { Orm } from './orm.js';
|
|
14
|
-
import { IdentityMap } from './identity-map.js';
|
|
15
|
-
import { UnitOfWork } from './unit-of-work.js';
|
|
16
|
-
import { DomainEventBus, DomainEventHandler, InitialHandlers } from './domain-event-bus.js';
|
|
17
|
-
import { RelationChangeProcessor } from './relation-change-processor.js';
|
|
18
|
-
import { createQueryLoggingExecutor, QueryLogger } from './query-logger.js';
|
|
19
|
-
import { ExecutionContext } from './execution-context.js';
|
|
20
|
-
import type { HydrationContext } from './hydration-context.js';
|
|
21
|
-
import type { EntityContext } from './entity-context.js';
|
|
22
|
-
import {
|
|
23
|
-
DomainEvent,
|
|
24
|
-
OrmDomainEvent,
|
|
25
|
-
RelationChange,
|
|
26
|
-
RelationChangeEntry,
|
|
27
|
-
RelationKey,
|
|
28
|
-
TrackedEntity
|
|
29
|
-
} from './runtime-types.js';
|
|
30
|
-
import { executeHydrated } from './execute.js';
|
|
31
|
-
import { runInTransaction } from './transaction-runner.js';
|
|
32
|
-
|
|
33
|
-
export interface OrmInterceptor {
|
|
34
|
-
beforeFlush?(ctx: EntityContext): Promise<void> | void;
|
|
35
|
-
afterFlush?(ctx: EntityContext): Promise<void> | void;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface OrmSessionOptions<E extends DomainEvent = OrmDomainEvent> {
|
|
39
|
-
orm: Orm<E>;
|
|
40
|
-
executor: DbExecutor;
|
|
41
|
-
queryLogger?: QueryLogger;
|
|
42
|
-
interceptors?: OrmInterceptor[];
|
|
43
|
-
domainEventHandlers?: InitialHandlers<E, OrmSession<E>>;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements EntityContext {
|
|
47
|
-
readonly orm: Orm<E>;
|
|
48
|
-
readonly executor: DbExecutor;
|
|
49
|
-
readonly identityMap: IdentityMap;
|
|
50
|
-
readonly unitOfWork: UnitOfWork;
|
|
51
|
-
readonly domainEvents: DomainEventBus<E, OrmSession<E>>;
|
|
52
|
-
readonly relationChanges: RelationChangeProcessor;
|
|
53
|
-
|
|
54
|
-
private readonly interceptors: OrmInterceptor[];
|
|
55
|
-
|
|
56
|
-
constructor(opts: OrmSessionOptions<E>) {
|
|
57
|
-
this.orm = opts.orm;
|
|
58
|
-
this.executor = createQueryLoggingExecutor(opts.executor, opts.queryLogger);
|
|
59
|
-
this.interceptors = [...(opts.interceptors ?? [])];
|
|
60
|
-
|
|
61
|
-
this.identityMap = new IdentityMap();
|
|
62
|
-
this.unitOfWork = new UnitOfWork(this.orm.dialect, this.executor, this.identityMap, () => this);
|
|
63
|
-
this.relationChanges = new RelationChangeProcessor(this.unitOfWork, this.orm.dialect, this.executor);
|
|
64
|
-
this.domainEvents = new DomainEventBus<E, OrmSession<E>>(opts.domainEventHandlers);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
get dialect(): Dialect {
|
|
68
|
-
return this.orm.dialect;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
get identityBuckets(): Map<string, Map<string, TrackedEntity>> {
|
|
72
|
-
return this.unitOfWork.identityBuckets;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
get tracked(): TrackedEntity[] {
|
|
76
|
-
return this.unitOfWork.getTracked();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
getEntity(table: TableDef, pk: any): any | undefined {
|
|
80
|
-
return this.unitOfWork.getEntity(table, pk);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
setEntity(table: TableDef, pk: any, entity: any): void {
|
|
84
|
-
this.unitOfWork.setEntity(table, pk, entity);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
trackNew(table: TableDef, entity: any, pk?: any): void {
|
|
88
|
-
this.unitOfWork.trackNew(table, entity, pk);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
trackManaged(table: TableDef, pk: any, entity: any): void {
|
|
92
|
-
this.unitOfWork.trackManaged(table, pk, entity);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
markDirty(entity: any): void {
|
|
96
|
-
this.unitOfWork.markDirty(entity);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
markRemoved(entity: any): void {
|
|
100
|
-
this.unitOfWork.markRemoved(entity);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
registerRelationChange = (
|
|
104
|
-
root: any,
|
|
105
|
-
relationKey: RelationKey,
|
|
106
|
-
rootTable: TableDef,
|
|
107
|
-
relationName: string,
|
|
108
|
-
relation: RelationDef,
|
|
109
|
-
change: RelationChange<any>
|
|
110
|
-
): void => {
|
|
111
|
-
this.relationChanges.registerChange(
|
|
112
|
-
buildRelationChangeEntry(root, relationKey, rootTable, relationName, relation, change)
|
|
113
|
-
);
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
getEntitiesForTable(table: TableDef): TrackedEntity[] {
|
|
117
|
-
return this.unitOfWork.getEntitiesForTable(table);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
registerInterceptor(interceptor: OrmInterceptor): void {
|
|
121
|
-
this.interceptors.push(interceptor);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
registerDomainEventHandler<TType extends E['type']>(
|
|
125
|
-
type: TType,
|
|
126
|
-
handler: DomainEventHandler<Extract<E, { type: TType }>, OrmSession<E>>
|
|
127
|
-
): void {
|
|
128
|
-
this.domainEvents.on(type, handler);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async find<TTable extends TableDef>(entityClass: EntityConstructor, id: any): Promise<
|
|
132
|
-
const table = getTableDefFromEntity(entityClass);
|
|
133
|
-
if (!table) {
|
|
134
|
-
throw new Error('Entity metadata has not been bootstrapped');
|
|
135
|
-
}
|
|
136
|
-
const primaryKey = findPrimaryKey(table);
|
|
8
|
+
import { EntityInstance } from '../schema/types.js';
|
|
9
|
+
import { RelationDef } from '../schema/relation.js';
|
|
10
|
+
|
|
11
|
+
import { selectFromEntity, getTableDefFromEntity } from '../decorators/bootstrap.js';
|
|
12
|
+
import type { EntityConstructor } from './entity-metadata.js';
|
|
13
|
+
import { Orm } from './orm.js';
|
|
14
|
+
import { IdentityMap } from './identity-map.js';
|
|
15
|
+
import { UnitOfWork } from './unit-of-work.js';
|
|
16
|
+
import { DomainEventBus, DomainEventHandler, InitialHandlers } from './domain-event-bus.js';
|
|
17
|
+
import { RelationChangeProcessor } from './relation-change-processor.js';
|
|
18
|
+
import { createQueryLoggingExecutor, QueryLogger } from './query-logger.js';
|
|
19
|
+
import { ExecutionContext } from './execution-context.js';
|
|
20
|
+
import type { HydrationContext } from './hydration-context.js';
|
|
21
|
+
import type { EntityContext } from './entity-context.js';
|
|
22
|
+
import {
|
|
23
|
+
DomainEvent,
|
|
24
|
+
OrmDomainEvent,
|
|
25
|
+
RelationChange,
|
|
26
|
+
RelationChangeEntry,
|
|
27
|
+
RelationKey,
|
|
28
|
+
TrackedEntity
|
|
29
|
+
} from './runtime-types.js';
|
|
30
|
+
import { executeHydrated } from './execute.js';
|
|
31
|
+
import { runInTransaction } from './transaction-runner.js';
|
|
32
|
+
|
|
33
|
+
export interface OrmInterceptor {
|
|
34
|
+
beforeFlush?(ctx: EntityContext): Promise<void> | void;
|
|
35
|
+
afterFlush?(ctx: EntityContext): Promise<void> | void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface OrmSessionOptions<E extends DomainEvent = OrmDomainEvent> {
|
|
39
|
+
orm: Orm<E>;
|
|
40
|
+
executor: DbExecutor;
|
|
41
|
+
queryLogger?: QueryLogger;
|
|
42
|
+
interceptors?: OrmInterceptor[];
|
|
43
|
+
domainEventHandlers?: InitialHandlers<E, OrmSession<E>>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements EntityContext {
|
|
47
|
+
readonly orm: Orm<E>;
|
|
48
|
+
readonly executor: DbExecutor;
|
|
49
|
+
readonly identityMap: IdentityMap;
|
|
50
|
+
readonly unitOfWork: UnitOfWork;
|
|
51
|
+
readonly domainEvents: DomainEventBus<E, OrmSession<E>>;
|
|
52
|
+
readonly relationChanges: RelationChangeProcessor;
|
|
53
|
+
|
|
54
|
+
private readonly interceptors: OrmInterceptor[];
|
|
55
|
+
|
|
56
|
+
constructor(opts: OrmSessionOptions<E>) {
|
|
57
|
+
this.orm = opts.orm;
|
|
58
|
+
this.executor = createQueryLoggingExecutor(opts.executor, opts.queryLogger);
|
|
59
|
+
this.interceptors = [...(opts.interceptors ?? [])];
|
|
60
|
+
|
|
61
|
+
this.identityMap = new IdentityMap();
|
|
62
|
+
this.unitOfWork = new UnitOfWork(this.orm.dialect, this.executor, this.identityMap, () => this);
|
|
63
|
+
this.relationChanges = new RelationChangeProcessor(this.unitOfWork, this.orm.dialect, this.executor);
|
|
64
|
+
this.domainEvents = new DomainEventBus<E, OrmSession<E>>(opts.domainEventHandlers);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get dialect(): Dialect {
|
|
68
|
+
return this.orm.dialect;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get identityBuckets(): Map<string, Map<string, TrackedEntity>> {
|
|
72
|
+
return this.unitOfWork.identityBuckets;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get tracked(): TrackedEntity[] {
|
|
76
|
+
return this.unitOfWork.getTracked();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
getEntity(table: TableDef, pk: any): any | undefined {
|
|
80
|
+
return this.unitOfWork.getEntity(table, pk);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
setEntity(table: TableDef, pk: any, entity: any): void {
|
|
84
|
+
this.unitOfWork.setEntity(table, pk, entity);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
trackNew(table: TableDef, entity: any, pk?: any): void {
|
|
88
|
+
this.unitOfWork.trackNew(table, entity, pk);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
trackManaged(table: TableDef, pk: any, entity: any): void {
|
|
92
|
+
this.unitOfWork.trackManaged(table, pk, entity);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
markDirty(entity: any): void {
|
|
96
|
+
this.unitOfWork.markDirty(entity);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
markRemoved(entity: any): void {
|
|
100
|
+
this.unitOfWork.markRemoved(entity);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
registerRelationChange = (
|
|
104
|
+
root: any,
|
|
105
|
+
relationKey: RelationKey,
|
|
106
|
+
rootTable: TableDef,
|
|
107
|
+
relationName: string,
|
|
108
|
+
relation: RelationDef,
|
|
109
|
+
change: RelationChange<any>
|
|
110
|
+
): void => {
|
|
111
|
+
this.relationChanges.registerChange(
|
|
112
|
+
buildRelationChangeEntry(root, relationKey, rootTable, relationName, relation, change)
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
getEntitiesForTable(table: TableDef): TrackedEntity[] {
|
|
117
|
+
return this.unitOfWork.getEntitiesForTable(table);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
registerInterceptor(interceptor: OrmInterceptor): void {
|
|
121
|
+
this.interceptors.push(interceptor);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
registerDomainEventHandler<TType extends E['type']>(
|
|
125
|
+
type: TType,
|
|
126
|
+
handler: DomainEventHandler<Extract<E, { type: TType }>, OrmSession<E>>
|
|
127
|
+
): void {
|
|
128
|
+
this.domainEvents.on(type, handler);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async find<TTable extends TableDef>(entityClass: EntityConstructor, id: any): Promise<EntityInstance<TTable> | null> {
|
|
132
|
+
const table = getTableDefFromEntity(entityClass);
|
|
133
|
+
if (!table) {
|
|
134
|
+
throw new Error('Entity metadata has not been bootstrapped');
|
|
135
|
+
}
|
|
136
|
+
const primaryKey = findPrimaryKey(table);
|
|
137
137
|
const column = table.columns[primaryKey];
|
|
138
138
|
if (!column) {
|
|
139
139
|
throw new Error('Entity table does not expose a primary key');
|
|
@@ -146,100 +146,100 @@ export class OrmSession<E extends DomainEvent = OrmDomainEvent> implements Entit
|
|
|
146
146
|
.select(columnSelections)
|
|
147
147
|
.where(eq(column, id))
|
|
148
148
|
.limit(1);
|
|
149
|
-
const rows = await executeHydrated(this, qb);
|
|
150
|
-
return rows[0] ?? null;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
async findOne<TTable extends TableDef>(qb: SelectQueryBuilder<any, TTable>): Promise<
|
|
154
|
-
const limited = qb.limit(1);
|
|
155
|
-
const rows = await executeHydrated(this, limited);
|
|
156
|
-
return rows[0] ?? null;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async findMany<TTable extends TableDef>(qb: SelectQueryBuilder<any, TTable>): Promise<
|
|
160
|
-
return executeHydrated(this, qb);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
async persist(entity: object): Promise<void> {
|
|
164
|
-
if (this.unitOfWork.findTracked(entity)) {
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
const table = getTableDefFromEntity((entity as any).constructor as EntityConstructor);
|
|
168
|
-
if (!table) {
|
|
169
|
-
throw new Error('Entity metadata has not been bootstrapped');
|
|
170
|
-
}
|
|
171
|
-
const primaryKey = findPrimaryKey(table);
|
|
172
|
-
const pkValue = (entity as Record<string, any>)[primaryKey];
|
|
173
|
-
if (pkValue !== undefined && pkValue !== null) {
|
|
174
|
-
this.trackManaged(table, pkValue, entity);
|
|
175
|
-
} else {
|
|
176
|
-
this.trackNew(table, entity);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
async remove(entity: object): Promise<void> {
|
|
181
|
-
this.markRemoved(entity);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
async flush(): Promise<void> {
|
|
185
|
-
await this.unitOfWork.flush();
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
async commit(): Promise<void> {
|
|
189
|
-
await runInTransaction(this.executor, async () => {
|
|
190
|
-
for (const interceptor of this.interceptors) {
|
|
191
|
-
await interceptor.beforeFlush?.(this);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
await this.unitOfWork.flush();
|
|
195
|
-
await this.relationChanges.process();
|
|
196
|
-
await this.unitOfWork.flush();
|
|
197
|
-
|
|
198
|
-
for (const interceptor of this.interceptors) {
|
|
199
|
-
await interceptor.afterFlush?.(this);
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
await this.domainEvents.dispatch(this.unitOfWork.getTracked(), this);
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
async rollback(): Promise<void> {
|
|
207
|
-
await this.executor.rollbackTransaction?.();
|
|
208
|
-
this.unitOfWork.reset();
|
|
209
|
-
this.relationChanges.reset();
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
getExecutionContext(): ExecutionContext {
|
|
213
|
-
return {
|
|
214
|
-
dialect: this.orm.dialect,
|
|
215
|
-
executor: this.executor,
|
|
216
|
-
interceptors: this.orm.interceptors
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
getHydrationContext(): HydrationContext<E> {
|
|
221
|
-
return {
|
|
222
|
-
identityMap: this.identityMap,
|
|
223
|
-
unitOfWork: this.unitOfWork,
|
|
224
|
-
domainEvents: this.domainEvents,
|
|
225
|
-
relationChanges: this.relationChanges,
|
|
226
|
-
entityContext: this
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
const buildRelationChangeEntry = (
|
|
232
|
-
root: any,
|
|
233
|
-
relationKey: RelationKey,
|
|
234
|
-
rootTable: TableDef,
|
|
235
|
-
relationName: string,
|
|
236
|
-
relation: RelationDef,
|
|
237
|
-
change: RelationChange<any>
|
|
238
|
-
): RelationChangeEntry => ({
|
|
239
|
-
root,
|
|
240
|
-
relationKey,
|
|
241
|
-
rootTable,
|
|
242
|
-
relationName,
|
|
243
|
-
relation,
|
|
244
|
-
change
|
|
245
|
-
});
|
|
149
|
+
const rows = await executeHydrated(this, qb);
|
|
150
|
+
return rows[0] ?? null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async findOne<TTable extends TableDef>(qb: SelectQueryBuilder<any, TTable>): Promise<EntityInstance<TTable> | null> {
|
|
154
|
+
const limited = qb.limit(1);
|
|
155
|
+
const rows = await executeHydrated(this, limited);
|
|
156
|
+
return rows[0] ?? null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async findMany<TTable extends TableDef>(qb: SelectQueryBuilder<any, TTable>): Promise<EntityInstance<TTable>[]> {
|
|
160
|
+
return executeHydrated(this, qb);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async persist(entity: object): Promise<void> {
|
|
164
|
+
if (this.unitOfWork.findTracked(entity)) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const table = getTableDefFromEntity((entity as any).constructor as EntityConstructor);
|
|
168
|
+
if (!table) {
|
|
169
|
+
throw new Error('Entity metadata has not been bootstrapped');
|
|
170
|
+
}
|
|
171
|
+
const primaryKey = findPrimaryKey(table);
|
|
172
|
+
const pkValue = (entity as Record<string, any>)[primaryKey];
|
|
173
|
+
if (pkValue !== undefined && pkValue !== null) {
|
|
174
|
+
this.trackManaged(table, pkValue, entity);
|
|
175
|
+
} else {
|
|
176
|
+
this.trackNew(table, entity);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async remove(entity: object): Promise<void> {
|
|
181
|
+
this.markRemoved(entity);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async flush(): Promise<void> {
|
|
185
|
+
await this.unitOfWork.flush();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async commit(): Promise<void> {
|
|
189
|
+
await runInTransaction(this.executor, async () => {
|
|
190
|
+
for (const interceptor of this.interceptors) {
|
|
191
|
+
await interceptor.beforeFlush?.(this);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
await this.unitOfWork.flush();
|
|
195
|
+
await this.relationChanges.process();
|
|
196
|
+
await this.unitOfWork.flush();
|
|
197
|
+
|
|
198
|
+
for (const interceptor of this.interceptors) {
|
|
199
|
+
await interceptor.afterFlush?.(this);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
await this.domainEvents.dispatch(this.unitOfWork.getTracked(), this);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async rollback(): Promise<void> {
|
|
207
|
+
await this.executor.rollbackTransaction?.();
|
|
208
|
+
this.unitOfWork.reset();
|
|
209
|
+
this.relationChanges.reset();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
getExecutionContext(): ExecutionContext {
|
|
213
|
+
return {
|
|
214
|
+
dialect: this.orm.dialect,
|
|
215
|
+
executor: this.executor,
|
|
216
|
+
interceptors: this.orm.interceptors
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
getHydrationContext(): HydrationContext<E> {
|
|
221
|
+
return {
|
|
222
|
+
identityMap: this.identityMap,
|
|
223
|
+
unitOfWork: this.unitOfWork,
|
|
224
|
+
domainEvents: this.domainEvents,
|
|
225
|
+
relationChanges: this.relationChanges,
|
|
226
|
+
entityContext: this
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const buildRelationChangeEntry = (
|
|
232
|
+
root: any,
|
|
233
|
+
relationKey: RelationKey,
|
|
234
|
+
rootTable: TableDef,
|
|
235
|
+
relationName: string,
|
|
236
|
+
relation: RelationDef,
|
|
237
|
+
change: RelationChange<any>
|
|
238
|
+
): RelationChangeEntry => ({
|
|
239
|
+
root,
|
|
240
|
+
relationKey,
|
|
241
|
+
rootTable,
|
|
242
|
+
relationName,
|
|
243
|
+
relation,
|
|
244
|
+
change
|
|
245
|
+
});
|