@mikro-orm/core 7.0.0-dev.3 → 7.0.0-dev.300
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/EntityManager.d.ts +114 -63
- package/EntityManager.js +385 -310
- package/MikroORM.d.ts +44 -35
- package/MikroORM.js +109 -143
- package/README.md +3 -2
- package/cache/FileCacheAdapter.d.ts +1 -1
- package/cache/FileCacheAdapter.js +17 -8
- package/cache/GeneratedCacheAdapter.d.ts +0 -1
- package/cache/GeneratedCacheAdapter.js +0 -2
- package/cache/index.d.ts +0 -1
- package/cache/index.js +0 -1
- package/connections/Connection.d.ts +16 -7
- package/connections/Connection.js +23 -14
- package/drivers/DatabaseDriver.d.ts +25 -16
- package/drivers/DatabaseDriver.js +119 -36
- package/drivers/IDatabaseDriver.d.ts +125 -23
- package/entity/BaseEntity.d.ts +63 -4
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +102 -31
- package/entity/Collection.js +446 -108
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +26 -18
- package/entity/EntityFactory.d.ts +13 -1
- package/entity/EntityFactory.js +106 -60
- package/entity/EntityHelper.d.ts +2 -2
- package/entity/EntityHelper.js +65 -20
- package/entity/EntityLoader.d.ts +13 -11
- package/entity/EntityLoader.js +257 -107
- package/entity/EntityRepository.d.ts +28 -8
- package/entity/EntityRepository.js +8 -2
- package/entity/PolymorphicRef.d.ts +12 -0
- package/entity/PolymorphicRef.js +18 -0
- package/entity/Reference.d.ts +9 -12
- package/entity/Reference.js +34 -9
- package/entity/WrappedEntity.d.ts +3 -8
- package/entity/WrappedEntity.js +3 -8
- package/entity/defineEntity.d.ts +753 -0
- package/entity/defineEntity.js +537 -0
- package/entity/index.d.ts +4 -2
- package/entity/index.js +4 -2
- package/entity/utils.d.ts +13 -1
- package/entity/utils.js +49 -4
- package/entity/validators.d.ts +11 -0
- package/entity/validators.js +65 -0
- package/enums.d.ts +23 -8
- package/enums.js +15 -1
- package/errors.d.ts +25 -9
- package/errors.js +67 -21
- package/events/EventManager.d.ts +2 -1
- package/events/EventManager.js +19 -11
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/Hydrator.js +1 -2
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +89 -36
- package/index.d.ts +2 -2
- package/index.js +1 -2
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/DefaultLogger.js +1 -0
- package/logging/SimpleLogger.d.ts +1 -1
- package/logging/colors.d.ts +1 -1
- package/logging/colors.js +7 -6
- package/logging/index.d.ts +1 -0
- package/logging/index.js +1 -0
- package/logging/inspect.d.ts +2 -0
- package/logging/inspect.js +11 -0
- package/metadata/EntitySchema.d.ts +53 -27
- package/metadata/EntitySchema.js +125 -52
- package/metadata/MetadataDiscovery.d.ts +64 -10
- package/metadata/MetadataDiscovery.js +823 -344
- package/metadata/MetadataProvider.d.ts +11 -2
- package/metadata/MetadataProvider.js +66 -2
- package/metadata/MetadataStorage.d.ts +13 -11
- package/metadata/MetadataStorage.js +71 -38
- package/metadata/MetadataValidator.d.ts +32 -9
- package/metadata/MetadataValidator.js +198 -42
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +40 -0
- package/metadata/index.d.ts +1 -1
- package/metadata/index.js +1 -1
- package/metadata/types.d.ts +577 -0
- package/metadata/types.js +1 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +16 -4
- package/naming-strategy/AbstractNamingStrategy.js +20 -2
- package/naming-strategy/EntityCaseNamingStrategy.d.ts +3 -3
- package/naming-strategy/EntityCaseNamingStrategy.js +6 -5
- package/naming-strategy/MongoNamingStrategy.d.ts +3 -3
- package/naming-strategy/MongoNamingStrategy.js +6 -6
- package/naming-strategy/NamingStrategy.d.ts +28 -4
- package/naming-strategy/UnderscoreNamingStrategy.d.ts +3 -3
- package/naming-strategy/UnderscoreNamingStrategy.js +6 -6
- package/not-supported.d.ts +2 -0
- package/not-supported.js +4 -0
- package/package.json +22 -11
- package/platforms/ExceptionConverter.js +1 -1
- package/platforms/Platform.d.ts +14 -16
- package/platforms/Platform.js +24 -44
- package/serialization/EntitySerializer.d.ts +8 -3
- package/serialization/EntitySerializer.js +47 -27
- package/serialization/EntityTransformer.js +33 -21
- package/serialization/SerializationContext.d.ts +6 -6
- package/serialization/SerializationContext.js +16 -13
- package/types/ArrayType.d.ts +1 -1
- package/types/ArrayType.js +2 -3
- package/types/BigIntType.d.ts +9 -6
- package/types/BigIntType.js +4 -1
- package/types/BlobType.d.ts +0 -1
- package/types/BlobType.js +0 -3
- package/types/BooleanType.d.ts +2 -1
- package/types/BooleanType.js +3 -0
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +3 -3
- package/types/DoubleType.js +2 -2
- package/types/EnumArrayType.js +1 -2
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/TinyIntType.js +1 -1
- package/types/Type.d.ts +2 -4
- package/types/Type.js +3 -3
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +1 -4
- package/types/index.d.ts +1 -1
- package/typings.d.ts +469 -175
- package/typings.js +120 -45
- package/unit-of-work/ChangeSet.d.ts +4 -6
- package/unit-of-work/ChangeSet.js +4 -5
- package/unit-of-work/ChangeSetComputer.d.ts +3 -8
- package/unit-of-work/ChangeSetComputer.js +44 -21
- package/unit-of-work/ChangeSetPersister.d.ts +15 -12
- package/unit-of-work/ChangeSetPersister.js +113 -45
- package/unit-of-work/CommitOrderCalculator.d.ts +12 -10
- package/unit-of-work/CommitOrderCalculator.js +13 -13
- package/unit-of-work/IdentityMap.d.ts +12 -0
- package/unit-of-work/IdentityMap.js +39 -1
- package/unit-of-work/UnitOfWork.d.ts +28 -3
- package/unit-of-work/UnitOfWork.js +315 -110
- package/utils/AbstractMigrator.d.ts +101 -0
- package/utils/AbstractMigrator.js +305 -0
- package/utils/AbstractSchemaGenerator.d.ts +5 -5
- package/utils/AbstractSchemaGenerator.js +32 -18
- package/utils/AsyncContext.d.ts +6 -0
- package/utils/AsyncContext.js +42 -0
- package/utils/Configuration.d.ts +801 -207
- package/utils/Configuration.js +150 -191
- package/utils/ConfigurationLoader.d.ts +1 -54
- package/utils/ConfigurationLoader.js +1 -352
- package/utils/Cursor.d.ts +3 -6
- package/utils/Cursor.js +27 -11
- package/utils/DataloaderUtils.d.ts +15 -5
- package/utils/DataloaderUtils.js +65 -17
- package/utils/EntityComparator.d.ts +21 -10
- package/utils/EntityComparator.js +243 -106
- package/utils/QueryHelper.d.ts +24 -6
- package/utils/QueryHelper.js +122 -26
- package/utils/RawQueryFragment.d.ts +60 -32
- package/utils/RawQueryFragment.js +69 -66
- package/utils/RequestContext.js +2 -2
- package/utils/TransactionContext.js +2 -2
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +15 -122
- package/utils/Utils.js +108 -376
- package/utils/clone.js +8 -23
- package/utils/env-vars.d.ts +7 -0
- package/utils/env-vars.js +97 -0
- package/utils/fs-utils.d.ts +34 -0
- package/utils/fs-utils.js +196 -0
- package/utils/index.d.ts +2 -3
- package/utils/index.js +2 -3
- package/utils/upsert-utils.d.ts +9 -4
- package/utils/upsert-utils.js +55 -4
- package/decorators/Check.d.ts +0 -3
- package/decorators/Check.js +0 -13
- package/decorators/CreateRequestContext.d.ts +0 -3
- package/decorators/CreateRequestContext.js +0 -32
- package/decorators/Embeddable.d.ts +0 -8
- package/decorators/Embeddable.js +0 -11
- package/decorators/Embedded.d.ts +0 -18
- package/decorators/Embedded.js +0 -18
- package/decorators/Entity.d.ts +0 -18
- package/decorators/Entity.js +0 -13
- package/decorators/Enum.d.ts +0 -9
- package/decorators/Enum.js +0 -16
- package/decorators/Filter.d.ts +0 -2
- package/decorators/Filter.js +0 -8
- package/decorators/Formula.d.ts +0 -5
- package/decorators/Formula.js +0 -15
- package/decorators/Indexed.d.ts +0 -17
- package/decorators/Indexed.js +0 -20
- package/decorators/ManyToMany.d.ts +0 -40
- package/decorators/ManyToMany.js +0 -14
- package/decorators/ManyToOne.d.ts +0 -30
- package/decorators/ManyToOne.js +0 -14
- package/decorators/OneToMany.d.ts +0 -28
- package/decorators/OneToMany.js +0 -17
- package/decorators/OneToOne.d.ts +0 -24
- package/decorators/OneToOne.js +0 -7
- package/decorators/PrimaryKey.d.ts +0 -9
- package/decorators/PrimaryKey.js +0 -20
- package/decorators/Property.d.ts +0 -250
- package/decorators/Property.js +0 -32
- package/decorators/Transactional.d.ts +0 -13
- package/decorators/Transactional.js +0 -28
- package/decorators/hooks.d.ts +0 -16
- package/decorators/hooks.js +0 -47
- package/decorators/index.d.ts +0 -17
- package/decorators/index.js +0 -17
- package/entity/ArrayCollection.d.ts +0 -116
- package/entity/ArrayCollection.js +0 -395
- package/entity/EntityValidator.d.ts +0 -19
- package/entity/EntityValidator.js +0 -150
- package/metadata/ReflectMetadataProvider.d.ts +0 -8
- package/metadata/ReflectMetadataProvider.js +0 -44
- package/utils/resolveContextProvider.d.ts +0 -10
- package/utils/resolveContextProvider.js +0 -28
package/utils/QueryHelper.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { Reference } from '../entity/Reference.js';
|
|
2
2
|
import { Utils } from './Utils.js';
|
|
3
|
-
import { GroupOperator, ReferenceKind } from '../enums.js';
|
|
3
|
+
import { ARRAY_OPERATORS, GroupOperator, JSON_KEY_OPERATORS, ReferenceKind } from '../enums.js';
|
|
4
4
|
import { JsonType } from '../types/JsonType.js';
|
|
5
5
|
import { helper } from '../entity/wrap.js';
|
|
6
|
-
import {
|
|
6
|
+
import { isRaw, Raw } from './RawQueryFragment.js';
|
|
7
|
+
/** @internal */
|
|
7
8
|
export class QueryHelper {
|
|
8
9
|
static SUPPORTED_OPERATORS = ['>', '<', '<=', '>=', '!', '!='];
|
|
10
|
+
/**
|
|
11
|
+
* Finds the discriminator value (key) for a given entity class in a discriminator map.
|
|
12
|
+
*/
|
|
13
|
+
static findDiscriminatorValue(discriminatorMap, targetClass) {
|
|
14
|
+
return Object.entries(discriminatorMap).find(([, cls]) => cls === targetClass)?.[0];
|
|
15
|
+
}
|
|
9
16
|
static processParams(params) {
|
|
10
17
|
if (Reference.isReference(params)) {
|
|
11
18
|
params = params.unwrap();
|
|
@@ -28,16 +35,60 @@ export class QueryHelper {
|
|
|
28
35
|
return params;
|
|
29
36
|
}
|
|
30
37
|
static processObjectParams(params = {}) {
|
|
31
|
-
Utils.
|
|
38
|
+
Utils.getObjectQueryKeys(params).forEach(k => {
|
|
32
39
|
params[k] = QueryHelper.processParams(params[k]);
|
|
33
40
|
});
|
|
34
41
|
return params;
|
|
35
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* converts `{ account: { $or: [ [Object], [Object] ] } }`
|
|
45
|
+
* to `{ $or: [ { account: [Object] }, { account: [Object] } ] }`
|
|
46
|
+
*/
|
|
47
|
+
static liftGroupOperators(where, meta, metadata, key) {
|
|
48
|
+
if (!Utils.isPlainObject(where)) {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
const keys = Object.keys(where);
|
|
52
|
+
const groupOperator = keys.find(k => {
|
|
53
|
+
return k in GroupOperator && Array.isArray(where[k]) && where[k].every(cond => {
|
|
54
|
+
return Utils.isPlainObject(cond) && Object.keys(cond).every(k2 => {
|
|
55
|
+
if (Utils.isOperator(k2, false)) {
|
|
56
|
+
if (k2 === '$not') {
|
|
57
|
+
return Object.keys(cond[k2]).every(k3 => meta.primaryKeys.includes(k3));
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return meta.primaryKeys.includes(k2);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
if (groupOperator) {
|
|
66
|
+
return groupOperator;
|
|
67
|
+
}
|
|
68
|
+
for (const k of keys) {
|
|
69
|
+
const value = where[k];
|
|
70
|
+
const prop = meta.properties[k];
|
|
71
|
+
// Polymorphic relations use multiple columns (discriminator + FK), so they cannot
|
|
72
|
+
// participate in the standard single-column FK expansion. Query by discriminator
|
|
73
|
+
// column directly instead, e.g. { likeableType: 'post', likeableId: 1 }.
|
|
74
|
+
if (!prop || ![ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) || prop.polymorphic) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const op = this.liftGroupOperators(value, prop.targetMeta, metadata, k);
|
|
78
|
+
if (op) {
|
|
79
|
+
delete where[k];
|
|
80
|
+
where[op] = value[op].map((v) => {
|
|
81
|
+
return { [k]: v };
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
36
87
|
static inlinePrimaryKeyObjects(where, meta, metadata, key) {
|
|
37
88
|
if (Array.isArray(where)) {
|
|
38
89
|
where.forEach((item, i) => {
|
|
39
90
|
if (this.inlinePrimaryKeyObjects(item, meta, metadata, key)) {
|
|
40
|
-
where[i] = Utils.getPrimaryKeyValues(item, meta
|
|
91
|
+
where[i] = Utils.getPrimaryKeyValues(item, meta, false);
|
|
41
92
|
}
|
|
42
93
|
});
|
|
43
94
|
}
|
|
@@ -45,9 +96,9 @@ export class QueryHelper {
|
|
|
45
96
|
return false;
|
|
46
97
|
}
|
|
47
98
|
if (meta.primaryKeys.every(pk => pk in where) && Utils.getObjectKeysSize(where) === meta.primaryKeys.length) {
|
|
48
|
-
return !!key && !GroupOperator[key] && Object.keys(where).every(k => !Utils.isPlainObject(where[k]) || Object.keys(where[k]).every(v => {
|
|
99
|
+
return !!key && !GroupOperator[key] && key !== '$not' && Object.keys(where).every(k => !Utils.isPlainObject(where[k]) || Object.keys(where[k]).every(v => {
|
|
49
100
|
if (Utils.isOperator(v, false)) {
|
|
50
|
-
return
|
|
101
|
+
return true;
|
|
51
102
|
}
|
|
52
103
|
if (meta.properties[k].primary && [ReferenceKind.ONE_TO_ONE, ReferenceKind.MANY_TO_ONE].includes(meta.properties[k].kind)) {
|
|
53
104
|
return this.inlinePrimaryKeyObjects(where[k], meta.properties[k].targetMeta, metadata, v);
|
|
@@ -56,9 +107,9 @@ export class QueryHelper {
|
|
|
56
107
|
}));
|
|
57
108
|
}
|
|
58
109
|
Object.keys(where).forEach(k => {
|
|
59
|
-
const meta2 = metadata.find(meta.properties[k]?.
|
|
110
|
+
const meta2 = metadata.find(meta.properties[k]?.targetMeta?.class) || meta;
|
|
60
111
|
if (this.inlinePrimaryKeyObjects(where[k], meta2, metadata, k)) {
|
|
61
|
-
where[k] = Utils.getPrimaryKeyValues(where[k], meta2
|
|
112
|
+
where[k] = Utils.getPrimaryKeyValues(where[k], meta2, true);
|
|
62
113
|
}
|
|
63
114
|
});
|
|
64
115
|
return false;
|
|
@@ -69,13 +120,14 @@ export class QueryHelper {
|
|
|
69
120
|
const meta = metadata.find(entityName);
|
|
70
121
|
// inline PK-only objects in M:N queries, so we don't join the target entity when not needed
|
|
71
122
|
if (meta && root) {
|
|
123
|
+
QueryHelper.liftGroupOperators(where, meta, metadata);
|
|
72
124
|
QueryHelper.inlinePrimaryKeyObjects(where, meta, metadata);
|
|
73
125
|
}
|
|
74
126
|
if (platform.getConfig().get('ignoreUndefinedInQuery') && where && typeof where === 'object') {
|
|
75
127
|
Utils.dropUndefinedProperties(where);
|
|
76
128
|
}
|
|
77
129
|
where = QueryHelper.processParams(where) ?? {};
|
|
78
|
-
/* v8 ignore next
|
|
130
|
+
/* v8 ignore next */
|
|
79
131
|
if (!root && Utils.isPrimaryKey(where)) {
|
|
80
132
|
return where;
|
|
81
133
|
}
|
|
@@ -83,7 +135,7 @@ export class QueryHelper {
|
|
|
83
135
|
where = { [Utils.getPrimaryKeyHash(meta.primaryKeys)]: where };
|
|
84
136
|
}
|
|
85
137
|
if (Array.isArray(where) && root) {
|
|
86
|
-
const rootPrimaryKey = meta ? Utils.getPrimaryKeyHash(meta.primaryKeys) : entityName;
|
|
138
|
+
const rootPrimaryKey = meta ? Utils.getPrimaryKeyHash(meta.primaryKeys) : Utils.className(entityName);
|
|
87
139
|
let cond = { [rootPrimaryKey]: { $in: where } };
|
|
88
140
|
// @ts-ignore
|
|
89
141
|
// detect tuple comparison, use `$or` in case the number of constituents don't match
|
|
@@ -95,12 +147,10 @@ export class QueryHelper {
|
|
|
95
147
|
if (!Utils.isPlainObject(where)) {
|
|
96
148
|
return where;
|
|
97
149
|
}
|
|
98
|
-
return
|
|
150
|
+
return Utils.getObjectQueryKeys(where).reduce((o, key) => {
|
|
99
151
|
let value = where[key];
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
const composite = keys > 1;
|
|
103
|
-
if (Array.isArray(value) && value.length === 0 && RawQueryFragment.isKnownFragment(key)) {
|
|
152
|
+
const customExpression = Raw.isKnownFragmentSymbol(key);
|
|
153
|
+
if (Array.isArray(value) && value.length === 0 && customExpression) {
|
|
104
154
|
o[key] = value;
|
|
105
155
|
return o;
|
|
106
156
|
}
|
|
@@ -114,14 +164,17 @@ export class QueryHelper {
|
|
|
114
164
|
o[rootPrimaryKey] = { [key]: QueryHelper.processWhere({ ...options, where: value, root: false }) };
|
|
115
165
|
return o;
|
|
116
166
|
}
|
|
167
|
+
const prop = customExpression ? null : this.findProperty(key, options);
|
|
168
|
+
const keys = prop?.joinColumns?.length ?? 0;
|
|
169
|
+
const composite = keys > 1;
|
|
117
170
|
if (prop?.customType && convertCustomTypes && !isRaw(value)) {
|
|
118
171
|
value = QueryHelper.processCustomType(prop, value, platform, undefined, true);
|
|
119
172
|
}
|
|
120
173
|
const isJsonProperty = prop?.customType instanceof JsonType && Utils.isPlainObject(value) && !isRaw(value) && Object.keys(value)[0] !== '$eq';
|
|
121
|
-
if (isJsonProperty) {
|
|
174
|
+
if (isJsonProperty && prop?.kind !== ReferenceKind.EMBEDDED) {
|
|
122
175
|
return this.processJsonCondition(o, value, [prop.fieldNames[0]], platform, aliased);
|
|
123
176
|
}
|
|
124
|
-
if (Array.isArray(value) && !Utils.isOperator(key) && !QueryHelper.isSupportedOperator(key) && !
|
|
177
|
+
if (Array.isArray(value) && !Utils.isOperator(key) && !QueryHelper.isSupportedOperator(key) && !(customExpression && Raw.getKnownFragment(key).params.length > 0) && options.type !== 'orderBy') {
|
|
125
178
|
// comparing single composite key - use $eq instead of $in
|
|
126
179
|
const op = composite && !value.every(v => Array.isArray(v)) ? '$eq' : '$in';
|
|
127
180
|
o[key] = { [op]: value };
|
|
@@ -131,7 +184,7 @@ export class QueryHelper {
|
|
|
131
184
|
o[key] = QueryHelper.processWhere({
|
|
132
185
|
...options,
|
|
133
186
|
where: value,
|
|
134
|
-
entityName: prop?.
|
|
187
|
+
entityName: prop?.targetMeta?.class ?? entityName,
|
|
135
188
|
root: false,
|
|
136
189
|
});
|
|
137
190
|
}
|
|
@@ -141,7 +194,7 @@ export class QueryHelper {
|
|
|
141
194
|
return o;
|
|
142
195
|
}, {});
|
|
143
196
|
}
|
|
144
|
-
static getActiveFilters(
|
|
197
|
+
static getActiveFilters(meta, options, filters) {
|
|
145
198
|
if (options === false) {
|
|
146
199
|
return [];
|
|
147
200
|
}
|
|
@@ -153,14 +206,32 @@ export class QueryHelper {
|
|
|
153
206
|
Object.keys(options).forEach(filter => opts[filter] = options[filter]);
|
|
154
207
|
}
|
|
155
208
|
return Object.keys(filters)
|
|
156
|
-
.filter(f => QueryHelper.isFilterActive(
|
|
209
|
+
.filter(f => QueryHelper.isFilterActive(meta, f, filters[f], opts))
|
|
157
210
|
.map(f => {
|
|
158
211
|
filters[f].name = f;
|
|
159
212
|
return filters[f];
|
|
160
213
|
});
|
|
161
214
|
}
|
|
162
|
-
static
|
|
163
|
-
if (
|
|
215
|
+
static mergePropertyFilters(propFilters, options) {
|
|
216
|
+
if (!options || !propFilters || options === true || propFilters === true) {
|
|
217
|
+
return options ?? propFilters;
|
|
218
|
+
}
|
|
219
|
+
if (Array.isArray(propFilters)) {
|
|
220
|
+
propFilters = propFilters.reduce((o, item) => {
|
|
221
|
+
o[item] = true;
|
|
222
|
+
return o;
|
|
223
|
+
}, {});
|
|
224
|
+
}
|
|
225
|
+
if (Array.isArray(options)) {
|
|
226
|
+
options = options.reduce((o, item) => {
|
|
227
|
+
o[item] = true;
|
|
228
|
+
return o;
|
|
229
|
+
}, {});
|
|
230
|
+
}
|
|
231
|
+
return Utils.mergeConfig({}, propFilters, options);
|
|
232
|
+
}
|
|
233
|
+
static isFilterActive(meta, filterName, filter, options) {
|
|
234
|
+
if (filter.entity && !filter.entity.includes(meta.className)) {
|
|
164
235
|
return false;
|
|
165
236
|
}
|
|
166
237
|
if (options[filterName] === false) {
|
|
@@ -170,8 +241,8 @@ export class QueryHelper {
|
|
|
170
241
|
}
|
|
171
242
|
static processCustomType(prop, cond, platform, key, fromQuery) {
|
|
172
243
|
if (Utils.isPlainObject(cond)) {
|
|
173
|
-
return Utils.
|
|
174
|
-
if (Utils.isOperator(k, true) || prop.referencedPKs?.includes(k)) {
|
|
244
|
+
return Utils.getObjectQueryKeys(cond).reduce((o, k) => {
|
|
245
|
+
if (!Raw.isKnownFragmentSymbol(k) && (Utils.isOperator(k, true) || prop.referencedPKs?.includes(k))) {
|
|
175
246
|
o[k] = QueryHelper.processCustomType(prop, cond[k], platform, k, fromQuery);
|
|
176
247
|
}
|
|
177
248
|
else {
|
|
@@ -180,12 +251,12 @@ export class QueryHelper {
|
|
|
180
251
|
return o;
|
|
181
252
|
}, {});
|
|
182
253
|
}
|
|
183
|
-
if (key &&
|
|
254
|
+
if (key && JSON_KEY_OPERATORS.includes(key)) {
|
|
184
255
|
return Array.isArray(cond)
|
|
185
256
|
? platform.marshallArray(cond)
|
|
186
257
|
: cond;
|
|
187
258
|
}
|
|
188
|
-
if (Array.isArray(cond) && !(key &&
|
|
259
|
+
if (Array.isArray(cond) && !(key && ARRAY_OPERATORS.includes(key))) {
|
|
189
260
|
return cond.map(v => QueryHelper.processCustomType(prop, v, platform, key, fromQuery));
|
|
190
261
|
}
|
|
191
262
|
if (isRaw(cond)) {
|
|
@@ -229,4 +300,29 @@ export class QueryHelper {
|
|
|
229
300
|
const meta = entityName ? options.metadata.find(entityName) : undefined;
|
|
230
301
|
return meta?.properties[propName];
|
|
231
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Merges multiple orderBy sources with key-level deduplication (first-seen key wins).
|
|
305
|
+
* RawQueryFragment symbol keys are never deduped (each is unique).
|
|
306
|
+
*/
|
|
307
|
+
static mergeOrderBy(...sources) {
|
|
308
|
+
const result = [];
|
|
309
|
+
const seenKeys = new Set();
|
|
310
|
+
for (const source of sources) {
|
|
311
|
+
if (source == null) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
for (const item of Utils.asArray(source)) {
|
|
315
|
+
for (const key of Utils.getObjectQueryKeys(item)) {
|
|
316
|
+
if (typeof key === 'symbol') {
|
|
317
|
+
result.push({ [key]: item[key] });
|
|
318
|
+
}
|
|
319
|
+
else if (!seenKeys.has(key)) {
|
|
320
|
+
seenKeys.add(key);
|
|
321
|
+
result.push({ [key]: item[key] });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return result;
|
|
327
|
+
}
|
|
232
328
|
}
|
|
@@ -1,34 +1,25 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
1
|
import type { AnyString, Dictionary, EntityKey } from '../typings.js';
|
|
3
|
-
|
|
2
|
+
declare const rawFragmentSymbolBrand: unique symbol;
|
|
3
|
+
export type RawQueryFragmentSymbol = symbol & {
|
|
4
|
+
readonly [rawFragmentSymbolBrand]: true;
|
|
5
|
+
};
|
|
6
|
+
export declare class RawQueryFragment<Alias extends string = string> {
|
|
4
7
|
#private;
|
|
5
8
|
readonly sql: string;
|
|
6
9
|
readonly params: unknown[];
|
|
7
|
-
|
|
10
|
+
/** @internal Type-level only - used to track the alias for type inference */
|
|
11
|
+
private readonly __alias?;
|
|
8
12
|
constructor(sql: string, params?: unknown[]);
|
|
9
|
-
|
|
10
|
-
|
|
13
|
+
get key(): RawQueryFragmentSymbol;
|
|
14
|
+
as<A extends string>(alias: A): RawQueryFragment<A>;
|
|
15
|
+
[Symbol.toPrimitive](hint: 'string'): RawQueryFragmentSymbol;
|
|
16
|
+
get [Symbol.toStringTag](): string;
|
|
11
17
|
toJSON(): string;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
static
|
|
17
|
-
/**
|
|
18
|
-
* @internal allows testing we don't leak memory, as the raw fragments cache needs to be cleared automatically
|
|
19
|
-
*/
|
|
20
|
-
static checkCacheSize(): number;
|
|
21
|
-
static isKnownFragment(key: string | RawQueryFragment): boolean;
|
|
22
|
-
static getKnownFragment(key: string | RawQueryFragment, cleanup?: boolean): RawQueryFragment | undefined;
|
|
23
|
-
static remove(key: string): void;
|
|
24
|
-
/** @ignore */
|
|
25
|
-
[inspect.custom](): {
|
|
26
|
-
sql: string;
|
|
27
|
-
params: unknown[];
|
|
28
|
-
} | {
|
|
29
|
-
sql: string;
|
|
30
|
-
params?: undefined;
|
|
31
|
-
};
|
|
18
|
+
clone(): this;
|
|
19
|
+
static isKnownFragmentSymbol(key: unknown): key is RawQueryFragmentSymbol;
|
|
20
|
+
static hasObjectFragments(object: unknown): boolean;
|
|
21
|
+
static isKnownFragment(key: unknown): key is RawQueryFragment | symbol;
|
|
22
|
+
static getKnownFragment(key: unknown): RawQueryFragment<any> | undefined;
|
|
32
23
|
}
|
|
33
24
|
export { RawQueryFragment as Raw };
|
|
34
25
|
export declare function isRaw(value: unknown): value is RawQueryFragment;
|
|
@@ -72,8 +63,26 @@ export declare const ALIAS_REPLACEMENT_RE = "\\[::alias::\\]";
|
|
|
72
63
|
* ```ts
|
|
73
64
|
* @Filter({ name: 'long', cond: () => ({ [raw('length(perex)')]: { $gt: 10000 } }) })
|
|
74
65
|
* ```
|
|
66
|
+
*
|
|
67
|
+
* The `raw` helper can be used within indexes and uniques to write database-agnostic SQL expressions. In that case, you can use `'??'` to tag your database identifiers (table name, column names, index name, ...) inside your expression, and pass those identifiers as a second parameter to the `raw` helper. Internally, those will automatically be quoted according to the database in use:
|
|
68
|
+
*
|
|
69
|
+
* ```ts
|
|
70
|
+
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("country")
|
|
71
|
+
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`country`)
|
|
72
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => raw(`create index ?? on ?? (??)`, ['custom_idx_on_name', table, columns.name]) })
|
|
73
|
+
* @Entity({ schema: 'library' })
|
|
74
|
+
* export class Author { ... }
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* You can also use the `quote` tag function to write database-agnostic SQL expressions. The end-result is the same as using the `raw` function regarding database identifiers quoting, only to have a more elegant expression syntax:
|
|
78
|
+
*
|
|
79
|
+
* ```ts
|
|
80
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
|
|
81
|
+
* @Entity({ schema: 'library' })
|
|
82
|
+
* export class Author { ... }
|
|
83
|
+
* ```
|
|
75
84
|
*/
|
|
76
|
-
export declare function raw<
|
|
85
|
+
export declare function raw<R = RawQueryFragment & symbol, T extends object = any>(sql: EntityKey<T> | EntityKey<T>[] | AnyString | ((alias: string) => string) | RawQueryFragment, params?: readonly unknown[] | Dictionary<unknown>): R;
|
|
77
86
|
/**
|
|
78
87
|
* Alternative to the `raw()` helper allowing to use it as a tagged template function for the simple cases.
|
|
79
88
|
*
|
|
@@ -86,13 +95,32 @@ export declare function raw<T extends object = any, R = any>(sql: EntityKey<T> |
|
|
|
86
95
|
*
|
|
87
96
|
* // value can be empty array
|
|
88
97
|
* await em.find(User, { [sql`(select 1 = 1)`]: [] });
|
|
98
|
+
*
|
|
99
|
+
* // with type parameter for assignment without casting
|
|
100
|
+
* entity.date = sql<Date>`now()`;
|
|
89
101
|
* ```
|
|
90
102
|
*/
|
|
91
|
-
export declare function sql(sql: readonly string[], ...values: unknown[]):
|
|
103
|
+
export declare function sql<R = RawQueryFragment & symbol>(sql: readonly string[], ...values: unknown[]): R;
|
|
92
104
|
export declare namespace sql {
|
|
93
|
-
var ref: <T extends object>(...keys: string[]) => RawQueryFragment;
|
|
94
|
-
var now: (length?: number) => string;
|
|
95
|
-
var lower: <T extends object>(key: string | ((alias: string) => string)) =>
|
|
96
|
-
var upper: <T extends object>(key: string | ((alias: string) => string)) =>
|
|
105
|
+
var ref: <T extends object = any>(...keys: string[]) => RawQueryFragment<string> & symbol;
|
|
106
|
+
var now: (length?: number) => RawQueryFragment<string> & symbol;
|
|
107
|
+
var lower: <R = RawQueryFragment<string> & symbol, T extends object = any>(key: string | ((alias: string) => string)) => R;
|
|
108
|
+
var upper: <R = RawQueryFragment<string> & symbol, T extends object = any>(key: string | ((alias: string) => string)) => R;
|
|
97
109
|
}
|
|
98
|
-
export declare function createSqlFunction<T extends object
|
|
110
|
+
export declare function createSqlFunction<R = RawQueryFragment & symbol, T extends object = any>(func: string, key: string | ((alias: string) => string)): R;
|
|
111
|
+
/**
|
|
112
|
+
* Tag function providing quoting of db identifiers (table name, columns names, index names, ...).
|
|
113
|
+
*
|
|
114
|
+
* Within the template literal on which the tag function is applied, all placeholders are considered to be database identifiers, and will thus be quoted as so according to the database in use.
|
|
115
|
+
*
|
|
116
|
+
* ```ts
|
|
117
|
+
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("name")
|
|
118
|
+
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`name`)
|
|
119
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns, indexName) => quote`create index ${indexName} on ${table} (${columns.name})` })
|
|
120
|
+
* @Entity({ schema: 'library' })
|
|
121
|
+
* export class Author { ... }
|
|
122
|
+
* ```
|
|
123
|
+
*/
|
|
124
|
+
export declare function quote(expParts: readonly string[], ...values: (string | {
|
|
125
|
+
toString(): string;
|
|
126
|
+
})[]): RawQueryFragment<string> & symbol;
|
|
@@ -1,94 +1,64 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
-
import { inspect } from 'node:util';
|
|
3
1
|
import { Utils } from './Utils.js';
|
|
4
2
|
export class RawQueryFragment {
|
|
5
3
|
sql;
|
|
6
4
|
params;
|
|
7
|
-
static #
|
|
8
|
-
static #storage = new AsyncLocalStorage();
|
|
9
|
-
static #index = 0n;
|
|
10
|
-
static cloneRegistry;
|
|
11
|
-
#assigned = false;
|
|
12
|
-
#used = 0;
|
|
5
|
+
static #rawQueryReferences = new WeakMap();
|
|
13
6
|
#key;
|
|
14
7
|
constructor(sql, params = []) {
|
|
15
8
|
this.sql = sql;
|
|
16
9
|
this.params = params;
|
|
17
|
-
|
|
10
|
+
}
|
|
11
|
+
get key() {
|
|
12
|
+
if (!this.#key) {
|
|
13
|
+
this.#key = Symbol(this.toJSON());
|
|
14
|
+
RawQueryFragment.#rawQueryReferences.set(this.#key, this);
|
|
15
|
+
}
|
|
16
|
+
return this.#key;
|
|
18
17
|
}
|
|
19
18
|
as(alias) {
|
|
20
|
-
return new RawQueryFragment(`${this.sql} as
|
|
19
|
+
return new RawQueryFragment(`${this.sql} as ??`, [...this.params, alias]);
|
|
21
20
|
}
|
|
22
|
-
|
|
21
|
+
[Symbol.toPrimitive](hint) {
|
|
22
|
+
// if a fragment is converted to string (used as an object key), return a unique symbol
|
|
23
|
+
// and save a weak reference to map so we can retrieve it when compiling the query
|
|
24
|
+
if (hint === 'string') {
|
|
25
|
+
return this.key;
|
|
26
|
+
}
|
|
23
27
|
throw new Error(`Trying to modify raw SQL fragment: '${this.sql}'`);
|
|
24
28
|
}
|
|
29
|
+
get [Symbol.toStringTag]() {
|
|
30
|
+
return this.toJSON();
|
|
31
|
+
}
|
|
25
32
|
toJSON() {
|
|
26
|
-
return this
|
|
33
|
+
return `raw('${this.sql}')`;
|
|
27
34
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
this.#used++;
|
|
31
|
-
return this.#key;
|
|
35
|
+
clone() {
|
|
36
|
+
return this;
|
|
32
37
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (this.#assigned) {
|
|
36
|
-
throw new Error(`Cannot reassign already used RawQueryFragment: '${this.sql}'`);
|
|
37
|
-
}
|
|
38
|
-
this.#assigned = true;
|
|
38
|
+
static isKnownFragmentSymbol(key) {
|
|
39
|
+
return typeof key === 'symbol' && this.#rawQueryReferences.has(key);
|
|
39
40
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
return new RawQueryFragment(this.sql, this.params);
|
|
43
|
-
}
|
|
44
|
-
static async run(cb) {
|
|
45
|
-
const removeStack = new Set();
|
|
46
|
-
const res = await this.#storage.run(removeStack, cb);
|
|
47
|
-
removeStack.forEach(key => RawQueryFragment.remove(key));
|
|
48
|
-
removeStack.clear();
|
|
49
|
-
return res;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* @internal allows testing we don't leak memory, as the raw fragments cache needs to be cleared automatically
|
|
53
|
-
*/
|
|
54
|
-
static checkCacheSize() {
|
|
55
|
-
return this.#rawQueryCache.size;
|
|
41
|
+
static hasObjectFragments(object) {
|
|
42
|
+
return Utils.isPlainObject(object) && Object.getOwnPropertySymbols(object).some(symbol => this.isKnownFragmentSymbol(symbol));
|
|
56
43
|
}
|
|
57
44
|
static isKnownFragment(key) {
|
|
58
45
|
if (key instanceof RawQueryFragment) {
|
|
59
46
|
return true;
|
|
60
47
|
}
|
|
61
|
-
return this
|
|
48
|
+
return this.isKnownFragmentSymbol(key);
|
|
62
49
|
}
|
|
63
|
-
static getKnownFragment(key
|
|
50
|
+
static getKnownFragment(key) {
|
|
64
51
|
if (key instanceof RawQueryFragment) {
|
|
65
52
|
return key;
|
|
66
53
|
}
|
|
67
|
-
|
|
68
|
-
if (raw && cleanup) {
|
|
69
|
-
this.remove(key);
|
|
70
|
-
}
|
|
71
|
-
return raw;
|
|
72
|
-
}
|
|
73
|
-
static remove(key) {
|
|
74
|
-
const raw = this.#rawQueryCache.get(key);
|
|
75
|
-
if (!raw) {
|
|
54
|
+
if (typeof key !== 'symbol') {
|
|
76
55
|
return;
|
|
77
56
|
}
|
|
78
|
-
|
|
79
|
-
if (raw.#used <= 0) {
|
|
80
|
-
const removeStack = this.#storage.getStore();
|
|
81
|
-
if (removeStack) {
|
|
82
|
-
removeStack.add(key);
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
this.#rawQueryCache.delete(key);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
57
|
+
return this.#rawQueryReferences.get(key);
|
|
88
58
|
}
|
|
89
|
-
/* v8 ignore next 8 */
|
|
90
59
|
/** @ignore */
|
|
91
|
-
|
|
60
|
+
/* v8 ignore next */
|
|
61
|
+
[Symbol.for('nodejs.util.inspect.custom')]() {
|
|
92
62
|
if (this.params) {
|
|
93
63
|
return { sql: this.sql, params: this.params };
|
|
94
64
|
}
|
|
@@ -142,6 +112,24 @@ export const ALIAS_REPLACEMENT_RE = '\\[::alias::\\]';
|
|
|
142
112
|
* ```ts
|
|
143
113
|
* @Filter({ name: 'long', cond: () => ({ [raw('length(perex)')]: { $gt: 10000 } }) })
|
|
144
114
|
* ```
|
|
115
|
+
*
|
|
116
|
+
* The `raw` helper can be used within indexes and uniques to write database-agnostic SQL expressions. In that case, you can use `'??'` to tag your database identifiers (table name, column names, index name, ...) inside your expression, and pass those identifiers as a second parameter to the `raw` helper. Internally, those will automatically be quoted according to the database in use:
|
|
117
|
+
*
|
|
118
|
+
* ```ts
|
|
119
|
+
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("country")
|
|
120
|
+
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`country`)
|
|
121
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => raw(`create index ?? on ?? (??)`, ['custom_idx_on_name', table, columns.name]) })
|
|
122
|
+
* @Entity({ schema: 'library' })
|
|
123
|
+
* export class Author { ... }
|
|
124
|
+
* ```
|
|
125
|
+
*
|
|
126
|
+
* You can also use the `quote` tag function to write database-agnostic SQL expressions. The end-result is the same as using the `raw` function regarding database identifiers quoting, only to have a more elegant expression syntax:
|
|
127
|
+
*
|
|
128
|
+
* ```ts
|
|
129
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns) => quote`create index ${'custom_idx_on_name'} on ${table} (${columns.name})` })
|
|
130
|
+
* @Entity({ schema: 'library' })
|
|
131
|
+
* export class Author { ... }
|
|
132
|
+
* ```
|
|
145
133
|
*/
|
|
146
134
|
export function raw(sql, params) {
|
|
147
135
|
if (sql instanceof RawQueryFragment) {
|
|
@@ -181,14 +169,13 @@ export function raw(sql, params) {
|
|
|
181
169
|
*
|
|
182
170
|
* // value can be empty array
|
|
183
171
|
* await em.find(User, { [sql`(select 1 = 1)`]: [] });
|
|
172
|
+
*
|
|
173
|
+
* // with type parameter for assignment without casting
|
|
174
|
+
* entity.date = sql<Date>`now()`;
|
|
184
175
|
* ```
|
|
185
176
|
*/
|
|
186
177
|
export function sql(sql, ...values) {
|
|
187
|
-
return raw(sql.
|
|
188
|
-
const valueExists = i < values.length;
|
|
189
|
-
const text = query + queryPart;
|
|
190
|
-
return valueExists ? text + '?' : text;
|
|
191
|
-
}, ''), values);
|
|
178
|
+
return raw(sql.join('?'), values);
|
|
192
179
|
}
|
|
193
180
|
export function createSqlFunction(func, key) {
|
|
194
181
|
if (typeof key === 'string') {
|
|
@@ -200,3 +187,19 @@ sql.ref = (...keys) => raw('??', [keys.join('.')]);
|
|
|
200
187
|
sql.now = (length) => raw('current_timestamp' + (length == null ? '' : `(${length})`));
|
|
201
188
|
sql.lower = (key) => createSqlFunction('lower', key);
|
|
202
189
|
sql.upper = (key) => createSqlFunction('upper', key);
|
|
190
|
+
/**
|
|
191
|
+
* Tag function providing quoting of db identifiers (table name, columns names, index names, ...).
|
|
192
|
+
*
|
|
193
|
+
* Within the template literal on which the tag function is applied, all placeholders are considered to be database identifiers, and will thus be quoted as so according to the database in use.
|
|
194
|
+
*
|
|
195
|
+
* ```ts
|
|
196
|
+
* // On postgres, will produce: create index "index custom_idx_on_name" on "library.author" ("name")
|
|
197
|
+
* // On mysql, will produce: create index `index custom_idx_on_name` on `library.author` (`name`)
|
|
198
|
+
* @Index({ name: 'custom_idx_on_name', expression: (table, columns, indexName) => quote`create index ${indexName} on ${table} (${columns.name})` })
|
|
199
|
+
* @Entity({ schema: 'library' })
|
|
200
|
+
* export class Author { ... }
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
export function quote(expParts, ...values) {
|
|
204
|
+
return raw(expParts.join('??'), values);
|
|
205
|
+
}
|
package/utils/RequestContext.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createAsyncContext } from './AsyncContext.js';
|
|
2
2
|
/**
|
|
3
3
|
* Uses `AsyncLocalStorage` to create async context that holds the current EM fork.
|
|
4
4
|
*/
|
|
5
5
|
export class RequestContext {
|
|
6
6
|
map;
|
|
7
|
-
static storage =
|
|
7
|
+
static storage = createAsyncContext();
|
|
8
8
|
static counter = 1;
|
|
9
9
|
id = RequestContext.counter++;
|
|
10
10
|
constructor(map) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createAsyncContext } from './AsyncContext.js';
|
|
2
2
|
export class TransactionContext {
|
|
3
3
|
em;
|
|
4
|
-
static storage =
|
|
4
|
+
static storage = createAsyncContext();
|
|
5
5
|
id;
|
|
6
6
|
constructor(em) {
|
|
7
7
|
this.em = em;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { EntityManager } from '../EntityManager.js';
|
|
2
|
+
import { type TransactionOptions } from '../enums.js';
|
|
3
|
+
/**
|
|
4
|
+
* Manages transaction lifecycle and propagation for EntityManager.
|
|
5
|
+
*/
|
|
6
|
+
export declare class TransactionManager {
|
|
7
|
+
private readonly em;
|
|
8
|
+
constructor(em: EntityManager);
|
|
9
|
+
/**
|
|
10
|
+
* Main entry point for handling transactional operations with propagation support.
|
|
11
|
+
*/
|
|
12
|
+
handle<T>(cb: (em: EntityManager) => T | Promise<T>, options?: TransactionOptions): Promise<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Executes the callback with the specified propagation type.
|
|
15
|
+
*/
|
|
16
|
+
private executeWithPropagation;
|
|
17
|
+
/**
|
|
18
|
+
* Suspends the current transaction and returns the suspended resources.
|
|
19
|
+
*/
|
|
20
|
+
private suspendTransaction;
|
|
21
|
+
/**
|
|
22
|
+
* Resumes a previously suspended transaction.
|
|
23
|
+
*/
|
|
24
|
+
private resumeTransaction;
|
|
25
|
+
/**
|
|
26
|
+
* Executes operation without transaction context.
|
|
27
|
+
*/
|
|
28
|
+
private executeWithoutTransaction;
|
|
29
|
+
/**
|
|
30
|
+
* Creates new independent transaction, suspending any existing one.
|
|
31
|
+
*/
|
|
32
|
+
private executeWithNewTransaction;
|
|
33
|
+
/**
|
|
34
|
+
* Creates new transaction context.
|
|
35
|
+
*/
|
|
36
|
+
private createNewTransaction;
|
|
37
|
+
/**
|
|
38
|
+
* Executes nested transaction with savepoint.
|
|
39
|
+
*/
|
|
40
|
+
private executeNestedTransaction;
|
|
41
|
+
/**
|
|
42
|
+
* Creates a fork of the EntityManager with the given options.
|
|
43
|
+
*/
|
|
44
|
+
private createFork;
|
|
45
|
+
/**
|
|
46
|
+
* Determines if changes should be propagated to the upper context.
|
|
47
|
+
*/
|
|
48
|
+
private shouldPropagateToUpperContext;
|
|
49
|
+
/**
|
|
50
|
+
* Merges entities from fork to parent EntityManager.
|
|
51
|
+
*/
|
|
52
|
+
private mergeEntitiesToParent;
|
|
53
|
+
/**
|
|
54
|
+
* Registers a deletion handler to unset entity identities after flush.
|
|
55
|
+
*/
|
|
56
|
+
private registerDeletionHandler;
|
|
57
|
+
/**
|
|
58
|
+
* Processes transaction execution.
|
|
59
|
+
*/
|
|
60
|
+
private processTransaction;
|
|
61
|
+
/**
|
|
62
|
+
* Executes transaction workflow with entity synchronization.
|
|
63
|
+
*/
|
|
64
|
+
private executeTransactionFlow;
|
|
65
|
+
}
|