@koalarx/nest 1.18.13 → 1.18.15

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.
@@ -19,6 +19,16 @@ export declare abstract class RepositoryBase<TEntity extends EntityBase<TEntity>
19
19
  private readonly _modelName;
20
20
  private readonly _include?;
21
21
  constructor({ context, modelName, include, }: RepositoryInitProps<TEntity, TContext>);
22
+ private listRelationEntities;
23
+ private listToRelationActionList;
24
+ private entityToPrisma;
25
+ private findManySchema;
26
+ private createEntity;
27
+ private orphanRemoval;
28
+ private getIdPropName;
29
+ private getInclude;
30
+ private getPropNameFromEntitySource;
31
+ private persistRelations;
22
32
  protected context(transactionalClient?: TContext): TContext[TModelKey];
23
33
  protected findById(id: IComparableId): Promise<TEntity | null>;
24
34
  protected findFirst<T>(where: T): Promise<TEntity | null>;
@@ -29,13 +39,6 @@ export declare abstract class RepositoryBase<TEntity extends EntityBase<TEntity>
29
39
  protected saveMany<TWhere = any>(entities: TEntity[], updateWhere?: TWhere): Promise<void>;
30
40
  protected remove<TWhere = any>(where: TWhere, externalServices?: Promise<any>, notCascadeEntityProps?: Array<keyof TEntity>): Promise<any>;
31
41
  protected removeMany<TWhere = any>(where: TWhere, externalServices?: Promise<any>, notCascadeEntityProps?: Array<keyof TEntity>): Promise<void>;
32
- private listToRelationActionList;
33
- private entityToPrisma;
34
- private findManySchema;
35
- private createEntity;
36
- private orphanRemoval;
37
- private getIdPropName;
38
- private getInclude;
39
42
  withTransaction(fn: (prisma: TContext) => Promise<any>): Promise<any>;
40
43
  }
41
44
  export {};
@@ -15,6 +15,183 @@ class RepositoryBase {
15
15
  this._modelName = modelName;
16
16
  this._include = include;
17
17
  }
18
+ listRelationEntities(entity) {
19
+ const relationEntities = [];
20
+ Object.keys(entity).forEach((key) => {
21
+ if (entity[key] instanceof list_1.List) {
22
+ const list = entity[key];
23
+ list.toArray('added').forEach((item) => {
24
+ relationEntities.push(item);
25
+ relationEntities.push(...this.listRelationEntities(item));
26
+ });
27
+ list.toArray('updated').forEach((item) => {
28
+ relationEntities.push(item);
29
+ relationEntities.push(...this.listRelationEntities(item));
30
+ });
31
+ }
32
+ else if (entity[key] instanceof entity_base_1.EntityBase) {
33
+ relationEntities.push(entity[key]);
34
+ relationEntities.push(...this.listRelationEntities(entity[key]));
35
+ }
36
+ });
37
+ return relationEntities;
38
+ }
39
+ listToRelationActionList(entity) {
40
+ const relationCreates = [];
41
+ const relationUpdates = [];
42
+ const relationDeletes = [];
43
+ Object.keys(entity).forEach((key) => {
44
+ if (entity[key] instanceof list_1.List) {
45
+ const list = entity[key];
46
+ const modelName = list.entityType?.name;
47
+ const parentModelName = entity.constructor.name;
48
+ if (modelName) {
49
+ list.toArray('removed').forEach((item) => {
50
+ relationDeletes.push({
51
+ modelName: (0, KlString_1.toCamelCase)(modelName),
52
+ schema: { where: { id: item._id } },
53
+ relations: [],
54
+ });
55
+ });
56
+ list.toArray('added').forEach((item) => {
57
+ relationCreates.push({
58
+ modelName: (0, KlString_1.toCamelCase)(modelName),
59
+ schema: {
60
+ data: {
61
+ ...this.entityToPrisma(item),
62
+ [(0, KlString_1.toCamelCase)(parentModelName)]: {
63
+ connect: {
64
+ [this.getIdPropName(entity)]: entity[this.getIdPropName(entity)],
65
+ },
66
+ },
67
+ },
68
+ },
69
+ relations: this.listRelationEntities(item),
70
+ });
71
+ });
72
+ list.toArray('updated').forEach((item) => {
73
+ relationUpdates.push({
74
+ modelName: (0, KlString_1.toCamelCase)(modelName),
75
+ schema: {
76
+ where: { id: item._id },
77
+ data: this.entityToPrisma(item),
78
+ },
79
+ relations: this.listRelationEntities(item),
80
+ });
81
+ });
82
+ }
83
+ }
84
+ });
85
+ return { relationCreates, relationUpdates, relationDeletes };
86
+ }
87
+ entityToPrisma(entity) {
88
+ const prismaSchema = {};
89
+ Object.keys(entity)
90
+ .filter((key) => !['id', '_id', '_action'].includes(key))
91
+ .filter((key) => !(entity[key] instanceof Function || entity[key] instanceof list_1.List))
92
+ .forEach((key) => {
93
+ if (entity[key] instanceof entity_base_1.EntityBase) {
94
+ if (entity[key]._action === entity_base_1.EntityActionType.create) {
95
+ if (entity[key][this.getIdPropName()]) {
96
+ prismaSchema[key] = {
97
+ connectOrCreate: {
98
+ where: {
99
+ [this.getIdPropName()]: entity[key][this.getIdPropName()],
100
+ },
101
+ create: this.entityToPrisma(entity[key]),
102
+ },
103
+ };
104
+ }
105
+ else {
106
+ prismaSchema[key] = {
107
+ create: this.entityToPrisma(entity[key]),
108
+ };
109
+ }
110
+ }
111
+ else {
112
+ prismaSchema[key] = {
113
+ update: this.entityToPrisma(entity[key]),
114
+ };
115
+ }
116
+ }
117
+ else {
118
+ prismaSchema[key] = entity[key];
119
+ }
120
+ });
121
+ return prismaSchema;
122
+ }
123
+ findManySchema(where, pagination) {
124
+ return {
125
+ include: this.getInclude(),
126
+ where,
127
+ orderBy: pagination?.generateOrderBy(),
128
+ skip: pagination?.skip(),
129
+ take: (pagination?.limit ?? 0) > 0 ? pagination?.limit : undefined,
130
+ };
131
+ }
132
+ createEntity(data) {
133
+ const entity = new this._modelName();
134
+ entity._action = entity_base_1.EntityActionType.update;
135
+ entity.automap(data);
136
+ return entity;
137
+ }
138
+ orphanRemoval(client, entity) {
139
+ const where = {};
140
+ Object.keys(entity)
141
+ .filter((key) => key === 'id' || key.includes('Id'))
142
+ .forEach((key) => (where[key] = entity[key]));
143
+ return client[(0, KlString_1.toCamelCase)(entity.constructor.name)].delete({ where });
144
+ }
145
+ getIdPropName(entity) {
146
+ return (Reflect.getMetadata('entity:id', entity ? entity.constructor.prototype : this._modelName.prototype) ?? 'id');
147
+ }
148
+ getInclude(include) {
149
+ include = include ?? this._include ?? {};
150
+ const result = {};
151
+ Object.keys(include).forEach((key) => {
152
+ if (typeof include[key] === 'boolean') {
153
+ result[key] = include[key];
154
+ }
155
+ else {
156
+ result[key] = {
157
+ include: this.getInclude(include[key]),
158
+ };
159
+ }
160
+ });
161
+ return result;
162
+ }
163
+ getPropNameFromEntitySource(source, entity) {
164
+ return Object.keys(source).find((key) => {
165
+ if (source[key] instanceof entity_base_1.EntityBase) {
166
+ return source[key].constructor.name === entity.constructor.name;
167
+ }
168
+ else if (source[key] instanceof list_1.List) {
169
+ const list = source[key];
170
+ return list.entityType?.name === entity.constructor.name;
171
+ }
172
+ return false;
173
+ });
174
+ }
175
+ persistRelations(transaction, entity) {
176
+ const { relationCreates, relationUpdates, relationDeletes } = this.listToRelationActionList(entity);
177
+ return Promise.all([
178
+ ...relationCreates.map((relationCreate) => transaction[relationCreate.modelName]
179
+ .create(relationCreate.schema)
180
+ .then((response) => {
181
+ return Promise.all(relationCreate.relations.map((relation) => {
182
+ const relationPropName = this.getPropNameFromEntitySource(entity, relation);
183
+ if (!relationPropName) {
184
+ throw new Error(`Propname not found for relation entity ${relation.constructor.name} on entity ${entity.constructor.name}`);
185
+ }
186
+ entity.automap(response);
187
+ relation[relationPropName] = entity;
188
+ return this.persistRelations(transaction, relation);
189
+ }));
190
+ })),
191
+ ...relationUpdates.map((relation) => transaction[relation.modelName].update(relation.schema)),
192
+ ...relationDeletes.map((relation) => this.removeMany(relation.schema)),
193
+ ]);
194
+ }
18
195
  context(transactionalClient) {
19
196
  const modelName = this._modelName.name;
20
197
  if (!modelName)
@@ -80,12 +257,17 @@ class RepositoryBase {
80
257
  async saveChanges(entity, updateWhere) {
81
258
  const prismaEntity = this.entityToPrisma(entity);
82
259
  if (entity._action === entity_base_1.EntityActionType.create) {
83
- return this.context()
260
+ return this.withTransaction((client) => this.context(client)
84
261
  .create({
85
262
  data: prismaEntity,
86
263
  include: this.getInclude(),
87
264
  })
88
- .then((response) => this.createEntity(response));
265
+ .then((response) => {
266
+ entity[this.getIdPropName()] = response[this.getIdPropName()];
267
+ return this.persistRelations(client, entity).then(() => entity);
268
+ })).then((response) => this.findUnique({
269
+ [this.getIdPropName()]: response[this.getIdPropName()],
270
+ }));
89
271
  }
90
272
  else {
91
273
  const where = updateWhere ?? { id: entity._id };
@@ -94,13 +276,7 @@ class RepositoryBase {
94
276
  where,
95
277
  data: prismaEntity,
96
278
  })
97
- .then(() => {
98
- const { relationUpdates, relationDeletes } = this.listToRelationActionList(entity);
99
- return Promise.all([
100
- ...relationUpdates.map((relation) => client[relation.modelName].updateMany(relation.schema)),
101
- ...relationDeletes.map((relation) => client[relation.modelName].deleteMany(relation.schema)),
102
- ]);
103
- })).then(() => this.findUnique(where));
279
+ .then(() => this.persistRelations(client, entity))).then(() => this.findUnique(where));
104
280
  }
105
281
  }
106
282
  async saveMany(entities, updateWhere) {
@@ -160,121 +336,6 @@ class RepositoryBase {
160
336
  .then((response) => Promise.all(relationEntity.map((entity) => this.orphanRemoval(client, entity))).then(() => response));
161
337
  }));
162
338
  }
163
- listToRelationActionList(entity) {
164
- const relationUpdates = [];
165
- const relationDeletes = [];
166
- Object.keys(entity).forEach((key) => {
167
- if (entity[key] instanceof list_1.List) {
168
- const list = entity[key];
169
- const modelName = list.entityType?.name;
170
- if (modelName) {
171
- list.toArray('removed').forEach((item) => {
172
- relationDeletes.push({
173
- modelName: (0, KlString_1.toCamelCase)(modelName),
174
- schema: { where: { id: item._id } },
175
- });
176
- });
177
- list.toArray('updated').forEach((item) => {
178
- relationUpdates.push({
179
- modelName: (0, KlString_1.toCamelCase)(modelName),
180
- schema: {
181
- where: { id: item._id },
182
- data: this.entityToPrisma(item),
183
- },
184
- });
185
- });
186
- }
187
- }
188
- });
189
- return { relationUpdates, relationDeletes };
190
- }
191
- entityToPrisma(entity) {
192
- const prismaSchema = {};
193
- Object.keys(entity)
194
- .filter((key) => !['id', '_id', '_action'].includes(key))
195
- .filter((key) => !(entity[key] instanceof Function))
196
- .forEach((key) => {
197
- if (entity[key] instanceof list_1.List) {
198
- if (entity[key].toArray('added').length > 0) {
199
- prismaSchema[key] = {
200
- createMany: {
201
- data: entity[key].toArray('added').map((item) => {
202
- return this.entityToPrisma(item);
203
- }),
204
- },
205
- };
206
- }
207
- }
208
- else if (entity[key] instanceof entity_base_1.EntityBase) {
209
- if (entity[key]._action === entity_base_1.EntityActionType.create) {
210
- if (entity[key][this.getIdPropName()]) {
211
- prismaSchema[key] = {
212
- connectOrCreate: {
213
- where: {
214
- [this.getIdPropName()]: entity[key][this.getIdPropName()],
215
- },
216
- create: this.entityToPrisma(entity[key]),
217
- },
218
- };
219
- }
220
- else {
221
- prismaSchema[key] = {
222
- create: this.entityToPrisma(entity[key]),
223
- };
224
- }
225
- }
226
- else {
227
- prismaSchema[key] = {
228
- update: this.entityToPrisma(entity[key]),
229
- };
230
- }
231
- }
232
- else {
233
- prismaSchema[key] = entity[key];
234
- }
235
- });
236
- return prismaSchema;
237
- }
238
- findManySchema(where, pagination) {
239
- return {
240
- include: this.getInclude(),
241
- where,
242
- orderBy: pagination?.generateOrderBy(),
243
- skip: pagination?.skip(),
244
- take: (pagination?.limit ?? 0) > 0 ? pagination?.limit : undefined,
245
- };
246
- }
247
- createEntity(data) {
248
- const entity = new this._modelName();
249
- entity._action = entity_base_1.EntityActionType.update;
250
- entity.automap(data);
251
- return entity;
252
- }
253
- orphanRemoval(client, entity) {
254
- const where = {};
255
- Object.keys(entity)
256
- .filter((key) => key === 'id' || key.includes('Id'))
257
- .forEach((key) => (where[key] = entity[key]));
258
- return client[(0, KlString_1.toCamelCase)(entity.constructor.name)].delete({ where });
259
- }
260
- getIdPropName() {
261
- return Reflect.getMetadata('entity:id', this._modelName.prototype) ?? 'id';
262
- }
263
- getInclude(include) {
264
- include = include ?? this._include ?? {};
265
- const result = {};
266
- Object.keys(include).forEach((key) => {
267
- if (typeof include[key] === 'boolean') {
268
- result[key] = include[key];
269
- }
270
- else {
271
- result[key] = {
272
- include: this.getInclude(include[key]),
273
- };
274
- }
275
- });
276
- return result;
277
- }
278
339
  withTransaction(fn) {
279
340
  return this._context.withTransaction(async (client) => {
280
341
  return fn(new koala_global_vars_1.KoalaGlobalVars.dbTransactionContext(client));
@@ -5,6 +5,7 @@ export declare class AutoMappingService {
5
5
  constructor(automappingProfile: AutoMappingProfile);
6
6
  private getInstanceType;
7
7
  map<S, T>(data: any, source: Type<S>, target: Type<T>): T;
8
+ private getTarget;
8
9
  private mapNestedProp;
9
10
  private mapListToArray;
10
11
  private mapArrayToList;
@@ -82,7 +82,7 @@ let AutoMappingService = class AutoMappingService {
82
82
  });
83
83
  return mappedTarget;
84
84
  }
85
- mapNestedProp(data, source) {
85
+ getTarget(data, source) {
86
86
  if (this.isPrimitiveType(data)) {
87
87
  return data;
88
88
  }
@@ -90,7 +90,10 @@ let AutoMappingService = class AutoMappingService {
90
90
  if (targets.length === 0) {
91
91
  throw new Error(`No mapping context found for ${source.name}`);
92
92
  }
93
- return this.map(data, source.prototype.constructor, targets[0]);
93
+ return targets[0];
94
+ }
95
+ mapNestedProp(data, source) {
96
+ return this.map(data, source.prototype.constructor, this.getTarget(data, source));
94
97
  }
95
98
  mapListToArray(value) {
96
99
  return value.toArray().map((item) => {
@@ -102,7 +105,7 @@ let AutoMappingService = class AutoMappingService {
102
105
  });
103
106
  }
104
107
  mapArrayToList(value, compositionType, onlySet = true) {
105
- const list = new list_1.List(compositionType.prototype.constructor);
108
+ const list = new list_1.List(this.getTarget(value, compositionType.prototype.constructor));
106
109
  const mappedValue = value.map((item) => this.mapNestedProp(item, compositionType.prototype.constructor) ?? {});
107
110
  if (onlySet) {
108
111
  list.setList(mappedValue);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koalarx/nest",
3
- "version": "1.18.13",
3
+ "version": "1.18.15",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",