@koalarx/nest 3.1.13 → 3.1.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.
@@ -28,6 +28,7 @@ export declare abstract class RepositoryBase<TEntity extends EntityBase<TEntity>
28
28
  private findManySchema;
29
29
  private createEntity;
30
30
  private orphanRemoval;
31
+ private getIdOnEntity;
31
32
  private loadRelationForEntity;
32
33
  private enrichEntityWithRelations;
33
34
  private persistRelations;
@@ -17,23 +17,35 @@ class RepositoryBase {
17
17
  this._modelName = modelName;
18
18
  this._includeFindMany = (0, generate_prisma_include_schema_1.generateIncludeSchema)({
19
19
  forList: true,
20
- deepLimit: 1,
20
+ deepLimit: 2,
21
21
  entity: this._modelName,
22
22
  });
23
23
  }
24
24
  getIdPropName(entity) {
25
- return (Reflect.getMetadata('entity:id', entity ? entity.constructor.prototype : this._modelName.prototype) ?? 'id');
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);
29
38
  if (Array.isArray(propIdName)) {
30
39
  const whereSchema = {};
31
40
  propIdName.forEach((propName) => {
32
- whereSchema[propName] = value[propName];
41
+ whereSchema[propName] =
42
+ typeof value === 'object' ? value[propName] : value;
33
43
  });
34
44
  return whereSchema;
35
45
  }
36
- return { [propIdName]: value[propIdName] };
46
+ return {
47
+ [propIdName]: typeof value === 'object' ? value[propIdName] : value,
48
+ };
37
49
  }
38
50
  getConnectPrismaSchemaForRelation(entity, data) {
39
51
  return {
@@ -74,14 +86,14 @@ class RepositoryBase {
74
86
  }
75
87
  if (instance instanceof entity_base_1.EntityBase) {
76
88
  selectSchema[prop.name] = {
77
- select: this.getSelectRootPrismaSchema(instance),
89
+ select: this.getWhereByIdSchema(instance, true),
78
90
  };
79
91
  }
80
92
  else if (instance instanceof list_1.List) {
81
93
  const list = new entity()[prop.name];
82
94
  const entityInstance = list.entityType;
83
95
  selectSchema[prop.name] = {
84
- select: this.getSelectRootPrismaSchema(new entityInstance()),
96
+ select: this.getWhereByIdSchema(new entityInstance(), true),
85
97
  };
86
98
  }
87
99
  else {
@@ -171,6 +183,22 @@ class RepositoryBase {
171
183
  });
172
184
  }
173
185
  }
186
+ else if (entity[key] instanceof entity_base_1.EntityBase) {
187
+ const entityInstance = entity[key];
188
+ const modelName = entity[key].constructor.name;
189
+ if (entity[key]._action === entity_base_1.EntityActionType.update) {
190
+ relationUpdates.push({
191
+ modelName: (0, KlString_1.toCamelCase)(modelName),
192
+ entityInstance,
193
+ schema: {
194
+ where: { id: entityInstance._id },
195
+ data: this.entityToPrisma(entityInstance),
196
+ select: this.getSelectRootPrismaSchema(entityInstance),
197
+ },
198
+ relations: this.listRelationEntities(entityInstance),
199
+ });
200
+ }
201
+ }
174
202
  });
175
203
  return { relationCreates, relationUpdates, relationDeletes };
176
204
  }
@@ -243,15 +271,28 @@ class RepositoryBase {
243
271
  .forEach((key) => (where[key] = entity[key]));
244
272
  return client[(0, KlString_1.toCamelCase)(entity.constructor.name)].delete({ where });
245
273
  }
246
- async loadRelationForEntity(where, entity) {
274
+ getIdOnEntity(entity, data) {
275
+ const propIdName = this.getIdPropName(entity);
276
+ if (Array.isArray(propIdName)) {
277
+ const idValues = [];
278
+ propIdName.forEach((propName) => {
279
+ idValues.push(data[propName]);
280
+ });
281
+ return idValues.join('-');
282
+ }
283
+ return data[propIdName];
284
+ }
285
+ async loadRelationForEntity(where, entity, cache) {
247
286
  return this._context[(0, KlString_1.toCamelCase)((0, KlString_1.toCamelCase)(entity.name))]
248
- .findUnique({
287
+ .findFirst({
249
288
  select: this.getSelectWithRelationsId(entity),
250
289
  where,
251
290
  })
252
- .then((data) => this.enrichEntityWithRelations(entity, data));
291
+ .then((data) => this.enrichEntityWithRelations(entity, data, cache));
253
292
  }
254
- async enrichEntityWithRelations(entity, data) {
293
+ async enrichEntityWithRelations(entity, data, cache = new Map()) {
294
+ if (!data)
295
+ return data;
255
296
  const relationQueries = [];
256
297
  const relationKeys = [];
257
298
  const allProps = auto_mapping_list_1.AutoMappingList.getAllProps(entity);
@@ -264,15 +305,27 @@ class RepositoryBase {
264
305
  relationKeys.push(propName);
265
306
  const items = [];
266
307
  data[propName].forEach((item) => {
267
- items.push(this.loadRelationForEntity(item, entityInstance));
308
+ const cacheKey = `${entity.constructor.name}-${propName}-${this.getIdOnEntity(new entityInstance(), item)}`;
309
+ if (cache.has(cacheKey)) {
310
+ items.push(Promise.resolve(cache.get(cacheKey)));
311
+ return;
312
+ }
313
+ cache.set(cacheKey, item);
314
+ items.push(this.loadRelationForEntity(item, entityInstance, cache));
268
315
  });
269
316
  relationQueries.push(Promise.all(items));
270
317
  return;
271
318
  }
272
319
  const relationEntity = auto_mapping_list_1.AutoMappingList.getSourceByName(propDef?.type ?? '');
273
320
  if (relationEntity && data[propName]) {
321
+ const cacheKey = `${entity.constructor.name}-${propName}-${this.getIdOnEntity(new relationEntity(), data[propName])}`;
322
+ if (cache.has(cacheKey)) {
323
+ data[propName] = cache.get(cacheKey);
324
+ return;
325
+ }
326
+ cache.set(cacheKey, data[propName]);
274
327
  relationKeys.push(propName);
275
- relationQueries.push(this.loadRelationForEntity(this.getWhereByIdSchema(relationEntity, data[propName]), relationEntity));
328
+ relationQueries.push(this.loadRelationForEntity(this.getWhereByIdSchema(relationEntity, data[propName]), relationEntity, cache));
276
329
  }
277
330
  });
278
331
  if (relationQueries.length > 0) {
@@ -341,7 +394,7 @@ class RepositoryBase {
341
394
  });
342
395
  if (!data)
343
396
  return null;
344
- const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, data);
397
+ const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, { ...data });
345
398
  return this.createEntity(enrichedEntity);
346
399
  }
347
400
  async findFirst(where) {
@@ -351,7 +404,7 @@ class RepositoryBase {
351
404
  });
352
405
  if (!data)
353
406
  return null;
354
- const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, data);
407
+ const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, { ...data });
355
408
  return this.createEntity(enrichedEntity);
356
409
  }
357
410
  async findUnique(where) {
@@ -361,7 +414,7 @@ class RepositoryBase {
361
414
  });
362
415
  if (!data)
363
416
  return null;
364
- const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, data);
417
+ const enrichedEntity = await this.enrichEntityWithRelations(this._modelName.prototype.constructor, { ...data });
365
418
  return this.createEntity(enrichedEntity);
366
419
  }
367
420
  async findMany(where, pagination) {
@@ -2,33 +2,39 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateIncludeSchema = generateIncludeSchema;
4
4
  const entity_base_1 = require("../database/entity.base");
5
- const list_1 = require("./list");
6
5
  const auto_mapping_list_1 = require("../mapping/auto-mapping-list");
6
+ const list_1 = require("./list");
7
7
  function generateIncludeSchema({ forList, entity, deepIncludeCount = 0, deepLimit, }) {
8
8
  if (deepIncludeCount >= deepLimit) {
9
9
  return true;
10
10
  }
11
11
  const includeSchema = {};
12
+ const props = auto_mapping_list_1.AutoMappingList.getAllProps(entity);
12
13
  const entityInstance = new entity();
13
- Object.keys(entityInstance)
14
- .filter((key) => !['_id', '_action'].includes(key))
15
- .forEach((key) => {
14
+ props.forEach((prop) => {
15
+ let instance;
16
+ try {
17
+ instance = new (prop.type())();
18
+ }
19
+ catch {
20
+ instance = null;
21
+ }
16
22
  let includes;
17
- if (entityInstance[key] instanceof list_1.List) {
23
+ if (instance instanceof list_1.List) {
18
24
  if (forList) {
19
- includeSchema[key] = true;
25
+ includeSchema[prop.name] = true;
20
26
  }
21
27
  else {
22
28
  includes = generateIncludeSchema({
23
29
  forList,
24
- entity: entityInstance[key].entityType,
30
+ entity: instance.entityType,
25
31
  deepLimit,
26
32
  deepIncludeCount: deepIncludeCount > 0 ? deepIncludeCount + 1 : 1,
27
33
  });
28
34
  }
29
35
  }
30
36
  else {
31
- const propDefinitions = auto_mapping_list_1.AutoMappingList.getPropDefinitions(entityInstance.constructor, key);
37
+ const propDefinitions = auto_mapping_list_1.AutoMappingList.getPropDefinitions(entityInstance.constructor, prop.name);
32
38
  if (propDefinitions) {
33
39
  const source = auto_mapping_list_1.AutoMappingList.getSourceByName(propDefinitions.type);
34
40
  if (source?.prototype instanceof entity_base_1.EntityBase) {
@@ -43,10 +49,10 @@ function generateIncludeSchema({ forList, entity, deepIncludeCount = 0, deepLimi
43
49
  }
44
50
  if (includes) {
45
51
  if (includes === true || Object.keys(includes).length > 0) {
46
- includeSchema[key] = includes;
52
+ includeSchema[prop.name] = includes;
47
53
  }
48
54
  else {
49
- includeSchema[key] = true;
55
+ includeSchema[prop.name] = true;
50
56
  }
51
57
  }
52
58
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koalarx/nest",
3
- "version": "3.1.13",
3
+ "version": "3.1.15",
4
4
  "description": "",
5
5
  "author": "Igor D. Rangel",
6
6
  "license": "MIT",
@@ -1,2 +1,7 @@
1
+ import { Type } from '@nestjs/common';
1
2
  import 'dotenv/config';
2
- export declare function createE2EDatabase(runtime?: 'node' | 'bun'): Promise<`${string}-${string}-${string}-${string}-${string}`>;
3
+ import { E2EDatabaseClient } from './e2e-database-client';
4
+ export declare function createE2EDatabase<T extends E2EDatabaseClient>(runtime: "node" | "bun" | undefined, clientInstance: Type<T>): Promise<{
5
+ client: T;
6
+ schemaId: `${string}-${string}-${string}-${string}-${string}`;
7
+ }>;
@@ -4,7 +4,6 @@ exports.createE2EDatabase = createE2EDatabase;
4
4
  require("dotenv/config");
5
5
  const node_child_process_1 = require("node:child_process");
6
6
  const node_crypto_1 = require("node:crypto");
7
- const pg_1 = require("pg");
8
7
  function generateUniqueDatabaseURL() {
9
8
  const schemaId = (0, node_crypto_1.randomUUID)();
10
9
  if (!process.env.DATABASE_URL) {
@@ -17,31 +16,23 @@ function generateUniqueDatabaseURL() {
17
16
  schemaId,
18
17
  };
19
18
  }
20
- async function createE2EDatabase(runtime = 'node') {
19
+ async function createE2EDatabase(runtime = 'node', clientInstance) {
21
20
  const { url, schemaId } = generateUniqueDatabaseURL();
22
21
  process.env.DATABASE_URL = url;
23
- process.env.DIRECT_URL = url;
24
22
  process.env.PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK = 'true';
25
23
  try {
26
- const baseUrl = new URL(process.env.DATABASE_URL);
27
- baseUrl.pathname = '/postgres';
28
- const pool = new pg_1.Pool({ connectionString: baseUrl.toString() });
29
- try {
30
- await pool.query(`CREATE DATABASE "${schemaId}"`);
31
- }
32
- finally {
33
- await pool.end();
34
- }
24
+ const client = new clientInstance(url, schemaId);
25
+ await client.createDatabase(schemaId);
35
26
  const env = { ...process.env, DATABASE_URL: url, DIRECT_URL: url };
36
27
  (0, node_child_process_1.execSync)(`${runtime}x prisma migrate deploy`, {
37
28
  cwd: process.cwd(),
38
29
  env,
39
30
  stdio: 'inherit',
40
31
  });
32
+ return { client, schemaId };
41
33
  }
42
34
  catch (error) {
43
35
  console.error('Erro ao criar banco de dados e2e:', error);
44
36
  throw error;
45
37
  }
46
- return schemaId;
47
38
  }
@@ -0,0 +1,7 @@
1
+ export declare abstract class E2EDatabaseClient {
2
+ protected readonly url: string;
3
+ protected readonly schemaName: string;
4
+ constructor(url: string, schemaName: string);
5
+ abstract createDatabase(schemaName: string): Promise<void>;
6
+ abstract dropDatabase(): Promise<void>;
7
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.E2EDatabaseClient = void 0;
4
+ class E2EDatabaseClient {
5
+ url;
6
+ schemaName;
7
+ constructor(url, schemaName) {
8
+ this.url = url;
9
+ this.schemaName = schemaName;
10
+ }
11
+ }
12
+ exports.E2EDatabaseClient = E2EDatabaseClient;