@mikro-orm/core 7.1.8-dev.8 → 7.1.8
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/core",
|
|
3
|
-
"version": "7.1.8
|
|
3
|
+
"version": "7.1.8",
|
|
4
4
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"data-mapper",
|
|
@@ -95,6 +95,8 @@ export declare abstract class AbstractMigrator<D extends IDatabaseDriver> implem
|
|
|
95
95
|
*/
|
|
96
96
|
unlogMigration(name: string): Promise<void>;
|
|
97
97
|
protected init(): Promise<void>;
|
|
98
|
+
/** Resolves the migrations path (including source folder auto-detection) without touching the filesystem. */
|
|
99
|
+
protected resolvePaths(): Promise<void>;
|
|
98
100
|
protected initPaths(): Promise<void>;
|
|
99
101
|
protected initServices(): void;
|
|
100
102
|
protected resolve(params: {
|
|
@@ -9,6 +9,7 @@ export class AbstractMigrator {
|
|
|
9
9
|
options;
|
|
10
10
|
absolutePath;
|
|
11
11
|
initialized = false;
|
|
12
|
+
#pathsEnsured = false;
|
|
12
13
|
#listeners = new Map();
|
|
13
14
|
constructor(em) {
|
|
14
15
|
this.em = em;
|
|
@@ -303,7 +304,8 @@ export class AbstractMigrator {
|
|
|
303
304
|
this.initialized = true;
|
|
304
305
|
await this.initPaths();
|
|
305
306
|
}
|
|
306
|
-
|
|
307
|
+
/** Resolves the migrations path (including source folder auto-detection) without touching the filesystem. */
|
|
308
|
+
async resolvePaths() {
|
|
307
309
|
if (this.absolutePath || this.options.migrationsList) {
|
|
308
310
|
return;
|
|
309
311
|
}
|
|
@@ -312,6 +314,14 @@ export class AbstractMigrator {
|
|
|
312
314
|
/* v8 ignore next */
|
|
313
315
|
const key = this.config.get('preferTs', Utils.detectTypeScriptSupport()) && this.options.pathTs ? 'pathTs' : 'path';
|
|
314
316
|
this.absolutePath = fs.absolutePath(this.options[key], this.config.get('baseDir'));
|
|
317
|
+
}
|
|
318
|
+
async initPaths() {
|
|
319
|
+
await this.resolvePaths();
|
|
320
|
+
if (this.#pathsEnsured || this.options.migrationsList) {
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
this.#pathsEnsured = true;
|
|
324
|
+
const { fs } = await import('@mikro-orm/core/fs-utils');
|
|
315
325
|
try {
|
|
316
326
|
fs.ensureDir(this.absolutePath);
|
|
317
327
|
}
|
package/utils/QueryHelper.d.ts
CHANGED
|
@@ -40,6 +40,11 @@ export declare class QueryHelper {
|
|
|
40
40
|
static mergePropertyFilters(propFilters: FilterOptions | undefined, options: FilterOptions | undefined): FilterOptions | undefined;
|
|
41
41
|
static isFilterActive<T>(meta: EntityMetadata<T>, filterName: string, filter: FilterDef, options: Dictionary<boolean | Dictionary>): boolean;
|
|
42
42
|
static processCustomType<T extends object>(prop: EntityProperty<T>, cond: FilterQuery<T>, platform: Platform, key?: string, fromQuery?: boolean): FilterQuery<T>;
|
|
43
|
+
/**
|
|
44
|
+
* Composite PK conditions are keyed by a hash of all the PK names, which `findProperty` cannot
|
|
45
|
+
* resolve, so the custom types have to be applied positionally instead.
|
|
46
|
+
*/
|
|
47
|
+
private static processCompositeCustomTypes;
|
|
43
48
|
private static isSupportedOperator;
|
|
44
49
|
private static processJsonCondition;
|
|
45
50
|
static findProperty<T>(fieldName: string, options: ProcessWhereOptions<T>): EntityProperty<T> | undefined;
|
package/utils/QueryHelper.js
CHANGED
|
@@ -227,6 +227,13 @@ export class QueryHelper {
|
|
|
227
227
|
if (prop?.customType && convertCustomTypes && !isRaw(value)) {
|
|
228
228
|
value = QueryHelper.processCustomType(prop, value, platform, undefined, true);
|
|
229
229
|
}
|
|
230
|
+
else if (!prop &&
|
|
231
|
+
meta?.compositePK &&
|
|
232
|
+
convertCustomTypes &&
|
|
233
|
+
Array.isArray(value) &&
|
|
234
|
+
key === Utils.getPrimaryKeyHash(meta.primaryKeys)) {
|
|
235
|
+
value = QueryHelper.processCompositeCustomTypes(value, meta, platform);
|
|
236
|
+
}
|
|
230
237
|
// oxfmt-ignore
|
|
231
238
|
const isJsonProperty = prop?.customType instanceof JsonType && !isRaw(value) && (Utils.isPlainObject(value) ? !['$eq', '$elemMatch'].includes(Object.keys(value)[0]) : !Array.isArray(value));
|
|
232
239
|
if (isJsonProperty && prop?.kind !== ReferenceKind.EMBEDDED) {
|
|
@@ -321,6 +328,24 @@ export class QueryHelper {
|
|
|
321
328
|
}
|
|
322
329
|
return prop.customType.convertToDatabaseValue(cond, platform, { fromQuery, key, mode: 'query' });
|
|
323
330
|
}
|
|
331
|
+
/**
|
|
332
|
+
* Composite PK conditions are keyed by a hash of all the PK names, which `findProperty` cannot
|
|
333
|
+
* resolve, so the custom types have to be applied positionally instead.
|
|
334
|
+
*/
|
|
335
|
+
static processCompositeCustomTypes(value, meta, platform) {
|
|
336
|
+
const props = meta.primaryKeys.map(pk => meta.properties[pk]);
|
|
337
|
+
if (!props.some(prop => prop.customType)) {
|
|
338
|
+
return value;
|
|
339
|
+
}
|
|
340
|
+
// the tuple can be longer than the PK when the user passes a malformed condition
|
|
341
|
+
const convert = (tuple) => tuple.map((val, idx) => {
|
|
342
|
+
if (!props[idx]?.customType) {
|
|
343
|
+
return val;
|
|
344
|
+
}
|
|
345
|
+
return QueryHelper.processCustomType(props[idx], val, platform, undefined, true);
|
|
346
|
+
});
|
|
347
|
+
return value.every(val => Array.isArray(val)) ? value.map(val => convert(val)) : convert(value);
|
|
348
|
+
}
|
|
324
349
|
static isSupportedOperator(key) {
|
|
325
350
|
return !!QueryHelper.SUPPORTED_OPERATORS.find(op => key === op);
|
|
326
351
|
}
|
|
@@ -50,6 +50,12 @@ export declare class TransactionManager {
|
|
|
50
50
|
* Merges entities from fork to parent EntityManager.
|
|
51
51
|
*/
|
|
52
52
|
private mergeEntitiesToParent;
|
|
53
|
+
/**
|
|
54
|
+
* Returns the property names a given property is tracked and snapshotted under, paired with their values.
|
|
55
|
+
* Inlined embeddables are hydrated as a single object, so only their leaves tell whether it is complete.
|
|
56
|
+
*/
|
|
57
|
+
private getTrackedValues;
|
|
58
|
+
private restore;
|
|
53
59
|
/**
|
|
54
60
|
* Registers a deletion handler to unset entity identities after flush.
|
|
55
61
|
*/
|
|
@@ -169,19 +169,52 @@ export class TransactionManager {
|
|
|
169
169
|
if (!wrapped.__initialized && parentWrapped.__initialized) {
|
|
170
170
|
continue;
|
|
171
171
|
}
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
const parentData = parentWrapped.__data;
|
|
173
|
+
const parentSnapshot = parentWrapped.__originalEntityData;
|
|
174
|
+
parentWrapped.__data = { ...wrapped.__data };
|
|
175
|
+
const originalEntityData = { ...wrapped.__originalEntityData };
|
|
174
176
|
for (const prop of meta.hydrateProps) {
|
|
177
|
+
const tracked = this.getTrackedValues(prop, entity[prop.name]);
|
|
178
|
+
// the fork entity can be partially loaded, and propagating a property it does not know about
|
|
179
|
+
// would clobber the parent state, so we restore both its value and its snapshot entries
|
|
180
|
+
if (!tracked.every(([key, value]) => value !== undefined || wrapped.__loadedProperties.has(key))) {
|
|
181
|
+
this.restore(parentWrapped.__data, parentData, prop.name);
|
|
182
|
+
tracked.forEach(([key]) => this.restore(originalEntityData, parentSnapshot, key));
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
175
185
|
if (prop.kind === ReferenceKind.SCALAR) {
|
|
176
186
|
parentEntity[prop.name] = entity[prop.name];
|
|
177
187
|
}
|
|
178
188
|
}
|
|
189
|
+
if (wrapped.__originalEntityData) {
|
|
190
|
+
parentWrapped.__originalEntityData = originalEntityData;
|
|
191
|
+
}
|
|
179
192
|
}
|
|
180
193
|
else {
|
|
181
194
|
parentUoW.merge(entity, new Set([entity]));
|
|
182
195
|
}
|
|
183
196
|
}
|
|
184
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Returns the property names a given property is tracked and snapshotted under, paired with their values.
|
|
200
|
+
* Inlined embeddables are hydrated as a single object, so only their leaves tell whether it is complete.
|
|
201
|
+
*/
|
|
202
|
+
getTrackedValues(prop, value) {
|
|
203
|
+
if (prop.kind === ReferenceKind.EMBEDDED && !prop.object) {
|
|
204
|
+
return Object.values(prop.embeddedProps).flatMap(child => {
|
|
205
|
+
return this.getTrackedValues(child, value?.[child.embedded[1]]);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
return [[prop.name, value]];
|
|
209
|
+
}
|
|
210
|
+
restore(target, source, key) {
|
|
211
|
+
if (source && key in source) {
|
|
212
|
+
target[key] = source[key];
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
delete target[key];
|
|
216
|
+
}
|
|
217
|
+
}
|
|
185
218
|
/**
|
|
186
219
|
* Registers a deletion handler to unset entity identities after flush.
|
|
187
220
|
*/
|
package/utils/Utils.js
CHANGED
|
@@ -153,7 +153,7 @@ export function parseJsonSafe(value) {
|
|
|
153
153
|
/** Collection of general-purpose utility methods used throughout the ORM. */
|
|
154
154
|
export class Utils {
|
|
155
155
|
static PK_SEPARATOR = '~~~';
|
|
156
|
-
static #ORM_VERSION = '7.1.8
|
|
156
|
+
static #ORM_VERSION = '7.1.8';
|
|
157
157
|
/**
|
|
158
158
|
* Checks if the argument is instance of `Object`. Returns false for arrays.
|
|
159
159
|
*/
|