@koalarx/nest 3.1.12 → 3.1.14
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.
|
@@ -2,7 +2,13 @@ import { EntityBase } from './entity.base';
|
|
|
2
2
|
type EntityProps<T> = Omit<{
|
|
3
3
|
[K in keyof T as T[K] extends Function ? never : K]: T[K];
|
|
4
4
|
}, '_id' | '_action'>;
|
|
5
|
-
export
|
|
5
|
+
export type CompositeId = readonly (string | number)[];
|
|
6
|
+
export interface IdConfig<T extends EntityProps<any>> {
|
|
7
|
+
single?: keyof T;
|
|
8
|
+
composite?: readonly (keyof T)[];
|
|
9
|
+
custom?: (props: T) => string | number | CompositeId;
|
|
10
|
+
}
|
|
11
|
+
export declare function Entity<T extends new (...args: any[]) => EntityBase<any>>(id?: keyof EntityProps<InstanceType<T>> | IdConfig<EntityProps<InstanceType<T>>>): (target: T) => {
|
|
6
12
|
new (...args: any[]): {
|
|
7
13
|
_id: import("../utils/interfaces/icomparable").IComparableId;
|
|
8
14
|
_action: import("./entity.base").EntityActionType;
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Entity = Entity;
|
|
4
|
+
function normalizeIdConfig(id) {
|
|
5
|
+
if (!id)
|
|
6
|
+
return undefined;
|
|
7
|
+
if (typeof id === 'string' || typeof id === 'symbol') {
|
|
8
|
+
return { single: id };
|
|
9
|
+
}
|
|
10
|
+
return id;
|
|
11
|
+
}
|
|
4
12
|
function Entity(id) {
|
|
5
13
|
return function (target) {
|
|
6
14
|
class NewConstructor extends target {
|
|
@@ -17,7 +25,8 @@ function Entity(id) {
|
|
|
17
25
|
value: target.name,
|
|
18
26
|
writable: false,
|
|
19
27
|
});
|
|
20
|
-
|
|
28
|
+
const idConfig = normalizeIdConfig(id);
|
|
29
|
+
Reflect.defineMetadata('entity:id', idConfig, NewConstructor.prototype);
|
|
21
30
|
return NewConstructor;
|
|
22
31
|
};
|
|
23
32
|
}
|
|
@@ -15,7 +15,9 @@ export declare abstract class RepositoryBase<TEntity extends EntityBase<TEntity>
|
|
|
15
15
|
private readonly _includeFindMany?;
|
|
16
16
|
constructor({ context, modelName }: RepositoryInitProps<TEntity, TContext>);
|
|
17
17
|
private getIdPropName;
|
|
18
|
+
private getWhereByIdSchema;
|
|
18
19
|
private getConnectPrismaSchemaForRelation;
|
|
20
|
+
private checkIdHasValue;
|
|
19
21
|
private getSelectRootPrismaSchema;
|
|
20
22
|
private getSelectWithRelationsId;
|
|
21
23
|
private getPropNameFromEntitySource;
|
|
@@ -26,6 +28,7 @@ export declare abstract class RepositoryBase<TEntity extends EntityBase<TEntity>
|
|
|
26
28
|
private findManySchema;
|
|
27
29
|
private createEntity;
|
|
28
30
|
private orphanRemoval;
|
|
31
|
+
private getIdOnEntity;
|
|
29
32
|
private loadRelationForEntity;
|
|
30
33
|
private enrichEntityWithRelations;
|
|
31
34
|
private persistRelations;
|
|
@@ -22,16 +22,40 @@ class RepositoryBase {
|
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
getIdPropName(entity) {
|
|
25
|
-
|
|
25
|
+
const idConfig = Reflect.getMetadata('entity:id', entity ? entity.constructor.prototype : this._modelName.prototype);
|
|
26
|
+
if (idConfig) {
|
|
27
|
+
if (idConfig.single) {
|
|
28
|
+
return idConfig.single;
|
|
29
|
+
}
|
|
30
|
+
else if (idConfig.composite) {
|
|
31
|
+
return idConfig.composite;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return 'id';
|
|
26
35
|
}
|
|
27
|
-
|
|
36
|
+
getWhereByIdSchema(entity, value) {
|
|
28
37
|
const propIdName = this.getIdPropName(entity);
|
|
38
|
+
if (Array.isArray(propIdName)) {
|
|
39
|
+
const whereSchema = {};
|
|
40
|
+
propIdName.forEach((propName) => {
|
|
41
|
+
whereSchema[propName] =
|
|
42
|
+
typeof value === 'object' ? value[propName] : value;
|
|
43
|
+
});
|
|
44
|
+
return whereSchema;
|
|
45
|
+
}
|
|
29
46
|
return {
|
|
30
|
-
|
|
31
|
-
[propIdName]: (data ?? entity)[propIdName],
|
|
32
|
-
},
|
|
47
|
+
[propIdName]: typeof value === 'object' ? value[propIdName] : value,
|
|
33
48
|
};
|
|
34
49
|
}
|
|
50
|
+
getConnectPrismaSchemaForRelation(entity, data) {
|
|
51
|
+
return {
|
|
52
|
+
connect: this.getWhereByIdSchema(entity, data ?? entity),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
checkIdHasValue(entity, value) {
|
|
56
|
+
const result = this.getWhereByIdSchema(entity, value);
|
|
57
|
+
return Object.values(result).every((val) => val !== undefined && val !== null);
|
|
58
|
+
}
|
|
35
59
|
getSelectRootPrismaSchema(entity) {
|
|
36
60
|
const selectSchema = {};
|
|
37
61
|
Object.keys(entity)
|
|
@@ -62,18 +86,14 @@ class RepositoryBase {
|
|
|
62
86
|
}
|
|
63
87
|
if (instance instanceof entity_base_1.EntityBase) {
|
|
64
88
|
selectSchema[prop.name] = {
|
|
65
|
-
select:
|
|
66
|
-
[this.getIdPropName(entity[prop.name])]: true,
|
|
67
|
-
},
|
|
89
|
+
select: this.getWhereByIdSchema(instance, true),
|
|
68
90
|
};
|
|
69
91
|
}
|
|
70
92
|
else if (instance instanceof list_1.List) {
|
|
71
93
|
const list = new entity()[prop.name];
|
|
72
94
|
const entityInstance = list.entityType;
|
|
73
95
|
selectSchema[prop.name] = {
|
|
74
|
-
select:
|
|
75
|
-
[this.getIdPropName(entityInstance)]: true,
|
|
76
|
-
},
|
|
96
|
+
select: this.getWhereByIdSchema(new entityInstance(), true),
|
|
77
97
|
};
|
|
78
98
|
}
|
|
79
99
|
else {
|
|
@@ -174,12 +194,10 @@ class RepositoryBase {
|
|
|
174
194
|
.forEach((key) => {
|
|
175
195
|
if (entity[key] instanceof entity_base_1.EntityBase) {
|
|
176
196
|
if (entity[key]._action === entity_base_1.EntityActionType.create) {
|
|
177
|
-
if (entity[key]
|
|
197
|
+
if (entity[key] && this.checkIdHasValue(entity, entity[key])) {
|
|
178
198
|
prismaSchema[key] = {
|
|
179
199
|
connectOrCreate: {
|
|
180
|
-
where:
|
|
181
|
-
[this.getIdPropName(entity)]: entity[key][this.getIdPropName(entity)],
|
|
182
|
-
},
|
|
200
|
+
where: this.getWhereByIdSchema(entity[key].constructor, entity[key]),
|
|
183
201
|
create: this.entityToPrisma(entity[key]),
|
|
184
202
|
},
|
|
185
203
|
};
|
|
@@ -237,15 +255,28 @@ class RepositoryBase {
|
|
|
237
255
|
.forEach((key) => (where[key] = entity[key]));
|
|
238
256
|
return client[(0, KlString_1.toCamelCase)(entity.constructor.name)].delete({ where });
|
|
239
257
|
}
|
|
240
|
-
|
|
258
|
+
getIdOnEntity(entity, data) {
|
|
259
|
+
const propIdName = this.getIdPropName(entity);
|
|
260
|
+
if (Array.isArray(propIdName)) {
|
|
261
|
+
const idValues = [];
|
|
262
|
+
propIdName.forEach((propName) => {
|
|
263
|
+
idValues.push(data[propName]);
|
|
264
|
+
});
|
|
265
|
+
return idValues.join('-');
|
|
266
|
+
}
|
|
267
|
+
return data[propIdName];
|
|
268
|
+
}
|
|
269
|
+
async loadRelationForEntity(where, entity, cache) {
|
|
241
270
|
return this._context[(0, KlString_1.toCamelCase)((0, KlString_1.toCamelCase)(entity.name))]
|
|
242
|
-
.
|
|
271
|
+
.findFirst({
|
|
243
272
|
select: this.getSelectWithRelationsId(entity),
|
|
244
273
|
where,
|
|
245
274
|
})
|
|
246
|
-
.then((data) => this.enrichEntityWithRelations(entity, data));
|
|
275
|
+
.then((data) => this.enrichEntityWithRelations(entity, data, cache));
|
|
247
276
|
}
|
|
248
|
-
async enrichEntityWithRelations(entity, data) {
|
|
277
|
+
async enrichEntityWithRelations(entity, data, cache = new Map()) {
|
|
278
|
+
if (!data)
|
|
279
|
+
return data;
|
|
249
280
|
const relationQueries = [];
|
|
250
281
|
const relationKeys = [];
|
|
251
282
|
const allProps = auto_mapping_list_1.AutoMappingList.getAllProps(entity);
|
|
@@ -258,17 +289,27 @@ class RepositoryBase {
|
|
|
258
289
|
relationKeys.push(propName);
|
|
259
290
|
const items = [];
|
|
260
291
|
data[propName].forEach((item) => {
|
|
261
|
-
|
|
292
|
+
const cacheKey = `${entity.constructor.name}-${propName}-${this.getIdOnEntity(new entityInstance(), item)}`;
|
|
293
|
+
if (cache.has(cacheKey)) {
|
|
294
|
+
items.push(Promise.resolve(cache.get(cacheKey)));
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
cache.set(cacheKey, item);
|
|
298
|
+
items.push(this.loadRelationForEntity(item, entityInstance, cache));
|
|
262
299
|
});
|
|
263
300
|
relationQueries.push(Promise.all(items));
|
|
264
301
|
return;
|
|
265
302
|
}
|
|
266
303
|
const relationEntity = auto_mapping_list_1.AutoMappingList.getSourceByName(propDef?.type ?? '');
|
|
267
|
-
if (relationEntity) {
|
|
304
|
+
if (relationEntity && data[propName]) {
|
|
305
|
+
const cacheKey = `${entity.constructor.name}-${propName}-${this.getIdOnEntity(new relationEntity(), data[propName])}`;
|
|
306
|
+
if (cache.has(cacheKey)) {
|
|
307
|
+
data[propName] = cache.get(cacheKey);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
cache.set(cacheKey, data[propName]);
|
|
268
311
|
relationKeys.push(propName);
|
|
269
|
-
relationQueries.push(this.loadRelationForEntity(
|
|
270
|
-
[this.getIdPropName(relationEntity)]: data[propName][this.getIdPropName(relationEntity)],
|
|
271
|
-
}, relationEntity));
|
|
312
|
+
relationQueries.push(this.loadRelationForEntity(this.getWhereByIdSchema(relationEntity, data[propName]), relationEntity, cache));
|
|
272
313
|
}
|
|
273
314
|
});
|
|
274
315
|
if (relationQueries.length > 0) {
|
|
@@ -285,6 +326,9 @@ class RepositoryBase {
|
|
|
285
326
|
...relationCreates.map((relationCreate) => transaction[relationCreate.modelName]
|
|
286
327
|
.create(relationCreate.schema)
|
|
287
328
|
.then((response) => {
|
|
329
|
+
if (relationCreate.relations.length === 0) {
|
|
330
|
+
return Promise.all([]);
|
|
331
|
+
}
|
|
288
332
|
return Promise.all(relationCreate.relations.map((relation) => {
|
|
289
333
|
const relationPropName = this.getPropNameFromEntitySource(relation, relationCreate.entityInstance);
|
|
290
334
|
if (relationPropName &&
|
|
@@ -298,8 +342,15 @@ class RepositoryBase {
|
|
|
298
342
|
select: this.getSelectRootPrismaSchema(relation),
|
|
299
343
|
})
|
|
300
344
|
.then((response) => {
|
|
301
|
-
|
|
302
|
-
|
|
345
|
+
const idPropName = this.getIdPropName(relation);
|
|
346
|
+
if (!Array.isArray(idPropName)) {
|
|
347
|
+
relation[idPropName] = response[idPropName];
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
idPropName.forEach((propName) => {
|
|
351
|
+
relation[propName] = response[propName];
|
|
352
|
+
});
|
|
353
|
+
}
|
|
303
354
|
return this.persistRelations(transaction, relation);
|
|
304
355
|
});
|
|
305
356
|
}));
|
|
@@ -321,11 +372,13 @@ class RepositoryBase {
|
|
|
321
372
|
async findById(id) {
|
|
322
373
|
const data = await this.context().findFirst({
|
|
323
374
|
select: this.getSelectWithRelationsId(this._modelName.prototype.constructor),
|
|
324
|
-
where:
|
|
375
|
+
where: this.getWhereByIdSchema(this._modelName.prototype.constructor, {
|
|
376
|
+
id,
|
|
377
|
+
}),
|
|
325
378
|
});
|
|
326
379
|
if (!data)
|
|
327
380
|
return null;
|
|
328
|
-
const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, data);
|
|
381
|
+
const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, { ...data });
|
|
329
382
|
return this.createEntity(enrichedEntity);
|
|
330
383
|
}
|
|
331
384
|
async findFirst(where) {
|
|
@@ -335,7 +388,7 @@ class RepositoryBase {
|
|
|
335
388
|
});
|
|
336
389
|
if (!data)
|
|
337
390
|
return null;
|
|
338
|
-
const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, data);
|
|
391
|
+
const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, { ...data });
|
|
339
392
|
return this.createEntity(enrichedEntity);
|
|
340
393
|
}
|
|
341
394
|
async findUnique(where) {
|
|
@@ -345,7 +398,7 @@ class RepositoryBase {
|
|
|
345
398
|
});
|
|
346
399
|
if (!data)
|
|
347
400
|
return null;
|
|
348
|
-
const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, data);
|
|
401
|
+
const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, { ...data });
|
|
349
402
|
return this.createEntity(enrichedEntity);
|
|
350
403
|
}
|
|
351
404
|
async findMany(where, pagination) {
|
|
@@ -370,7 +423,15 @@ class RepositoryBase {
|
|
|
370
423
|
include: this.getInclude(),
|
|
371
424
|
})
|
|
372
425
|
.then((response) => {
|
|
373
|
-
|
|
426
|
+
const idPropName = this.getIdPropName(entity);
|
|
427
|
+
if (!Array.isArray(idPropName)) {
|
|
428
|
+
entity[idPropName] = response[idPropName];
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
idPropName.forEach((propName) => {
|
|
432
|
+
entity[propName] = response[propName];
|
|
433
|
+
});
|
|
434
|
+
}
|
|
374
435
|
return this.persistRelations(client, entity).then(() => entity);
|
|
375
436
|
}));
|
|
376
437
|
}
|