@koalarx/nest 1.6.4 → 1.8.0

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.
@@ -1,14 +1,20 @@
1
- import { IComparable, IComparableId } from '../utils/interfaces/icomparable';
2
1
  import { Overwrite } from '..';
2
+ import { IComparable, IComparableId } from '../utils/interfaces/icomparable';
3
+ export declare enum EntityActionType {
4
+ create = 1,
5
+ update = 2
6
+ }
3
7
  export type EntityProps<T extends IComparable<T>> = Overwrite<Omit<{
4
8
  [K in keyof T as T[K] extends Function ? never : K]: T[K];
5
- }, '_id'>, {
9
+ }, '_id' | '_action'>, {
6
10
  id?: T extends {
7
11
  id: infer U;
8
12
  } ? U : never;
9
13
  }>;
10
14
  export declare abstract class EntityBase<T extends IComparable<T>> implements IComparable<T> {
11
15
  _id: IComparableId;
16
+ _action: EntityActionType;
17
+ constructor(props?: EntityProps<T>);
12
18
  automap(props?: EntityProps<T>): void;
13
19
  equals(obj: EntityBase<T>): boolean;
14
20
  }
@@ -1,10 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EntityBase = void 0;
3
+ exports.EntityBase = exports.EntityActionType = void 0;
4
4
  const auto_mapping_list_1 = require("../mapping/auto-mapping-list");
5
5
  const list_1 = require("../utils/list");
6
+ var EntityActionType;
7
+ (function (EntityActionType) {
8
+ EntityActionType[EntityActionType["create"] = 1] = "create";
9
+ EntityActionType[EntityActionType["update"] = 2] = "update";
10
+ })(EntityActionType || (exports.EntityActionType = EntityActionType = {}));
6
11
  class EntityBase {
7
12
  _id;
13
+ _action = EntityActionType.create;
14
+ constructor(props) {
15
+ if (props) {
16
+ this.automap(props);
17
+ }
18
+ }
8
19
  automap(props) {
9
20
  if (props) {
10
21
  for (const key of Object.keys(props)) {
@@ -17,16 +28,16 @@ class EntityBase {
17
28
  let value = props[key];
18
29
  if (this[key].entityType) {
19
30
  value = value.map((item) => {
20
- const entity = new this[key].entityType();
21
- entity.automap(item);
31
+ const entity = new this[key].entityType(item);
32
+ entity._action = this._action;
22
33
  return entity;
23
34
  });
24
35
  }
25
36
  this[key].setList(value);
26
37
  }
27
38
  else if (EntityOnPropKey) {
28
- const entity = new EntityOnPropKey();
29
- entity.automap(props[key]);
39
+ const entity = new EntityOnPropKey(props[key]);
40
+ entity._action = this._action;
30
41
  this[key] = entity;
31
42
  }
32
43
  else if (propDefinitions) {
@@ -0,0 +1,9 @@
1
+ import { EntityBase } from './entity.base';
2
+ export declare function Entity<T extends new (...args: any[]) => EntityBase<any>>(): (target: T) => {
3
+ new (...args: any[]): {
4
+ _id: import("../utils/interfaces/icomparable").IComparableId;
5
+ _action: import("./entity.base").EntityActionType;
6
+ automap(props?: import("./entity.base").EntityProps<any> | undefined): void;
7
+ equals(obj: EntityBase<any>): boolean;
8
+ };
9
+ } & T;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Entity = void 0;
4
+ function Entity() {
5
+ return function (target) {
6
+ const originalConstructor = target;
7
+ class NewConstructor extends target {
8
+ constructor(...args) {
9
+ super(...args);
10
+ if (typeof this.automap === 'function') {
11
+ this.automap(args[0]);
12
+ }
13
+ }
14
+ }
15
+ const newConstructor = function (...args) {
16
+ const instance = Reflect.construct(originalConstructor, args, newConstructor);
17
+ if (typeof instance.automap === 'function') {
18
+ instance.automap(args[0]);
19
+ }
20
+ return instance;
21
+ };
22
+ Object.setPrototypeOf(NewConstructor.prototype, target.prototype);
23
+ Object.setPrototypeOf(NewConstructor, target);
24
+ Object.defineProperty(NewConstructor, 'name', {
25
+ value: target.name,
26
+ writable: false,
27
+ });
28
+ return NewConstructor;
29
+ };
30
+ }
31
+ exports.Entity = Entity;
@@ -0,0 +1,17 @@
1
+ import { List } from '../utils/list';
2
+ import { EntityBase } from './entity.base';
3
+ export declare class PersonAddress extends EntityBase<PersonAddress> {
4
+ id: number;
5
+ address: string;
6
+ }
7
+ export declare class PersonPhone extends EntityBase<PersonPhone> {
8
+ id: number;
9
+ phone: string;
10
+ }
11
+ export declare class Person extends EntityBase<Person> {
12
+ id: number;
13
+ name: string;
14
+ phones: List<PersonPhone>;
15
+ address: PersonAddress;
16
+ active: boolean;
17
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.Person = exports.PersonPhone = exports.PersonAddress = void 0;
13
+ const faker_1 = require("@faker-js/faker");
14
+ const auto_mapping_decorator_1 = require("../mapping/auto-mapping.decorator");
15
+ const list_1 = require("../utils/list");
16
+ const entity_base_1 = require("./entity.base");
17
+ const entity_decorator_1 = require("./entity.decorator");
18
+ let PersonAddress = exports.PersonAddress = class PersonAddress extends entity_base_1.EntityBase {
19
+ id;
20
+ address;
21
+ };
22
+ __decorate([
23
+ (0, auto_mapping_decorator_1.AutoMap)(),
24
+ __metadata("design:type", Number)
25
+ ], PersonAddress.prototype, "id", void 0);
26
+ __decorate([
27
+ (0, auto_mapping_decorator_1.AutoMap)(),
28
+ __metadata("design:type", String)
29
+ ], PersonAddress.prototype, "address", void 0);
30
+ exports.PersonAddress = PersonAddress = __decorate([
31
+ (0, entity_decorator_1.Entity)()
32
+ ], PersonAddress);
33
+ let PersonPhone = exports.PersonPhone = class PersonPhone extends entity_base_1.EntityBase {
34
+ id;
35
+ phone;
36
+ };
37
+ __decorate([
38
+ (0, auto_mapping_decorator_1.AutoMap)(),
39
+ __metadata("design:type", Number)
40
+ ], PersonPhone.prototype, "id", void 0);
41
+ __decorate([
42
+ (0, auto_mapping_decorator_1.AutoMap)(),
43
+ __metadata("design:type", String)
44
+ ], PersonPhone.prototype, "phone", void 0);
45
+ exports.PersonPhone = PersonPhone = __decorate([
46
+ (0, entity_decorator_1.Entity)()
47
+ ], PersonPhone);
48
+ let Person = exports.Person = class Person extends entity_base_1.EntityBase {
49
+ id;
50
+ name;
51
+ phones = new list_1.List(PersonPhone);
52
+ address;
53
+ active;
54
+ };
55
+ __decorate([
56
+ (0, auto_mapping_decorator_1.AutoMap)(),
57
+ __metadata("design:type", Number)
58
+ ], Person.prototype, "id", void 0);
59
+ __decorate([
60
+ (0, auto_mapping_decorator_1.AutoMap)(),
61
+ __metadata("design:type", String)
62
+ ], Person.prototype, "name", void 0);
63
+ __decorate([
64
+ (0, auto_mapping_decorator_1.AutoMap)({ type: list_1.List }),
65
+ __metadata("design:type", Object)
66
+ ], Person.prototype, "phones", void 0);
67
+ __decorate([
68
+ (0, auto_mapping_decorator_1.AutoMap)({ type: PersonAddress }),
69
+ __metadata("design:type", PersonAddress)
70
+ ], Person.prototype, "address", void 0);
71
+ __decorate([
72
+ (0, auto_mapping_decorator_1.AutoMap)(),
73
+ __metadata("design:type", Boolean)
74
+ ], Person.prototype, "active", void 0);
75
+ exports.Person = Person = __decorate([
76
+ (0, entity_decorator_1.Entity)()
77
+ ], Person);
78
+ describe('Entity decorator', () => {
79
+ it('should create an instance of Person', () => {
80
+ const phones = new list_1.List(PersonPhone);
81
+ phones.setList([
82
+ new PersonPhone({ phone: faker_1.faker.phone.number() }),
83
+ new PersonPhone({ phone: faker_1.faker.phone.number() }),
84
+ ]);
85
+ const person = new Person({
86
+ name: faker_1.faker.person.fullName(),
87
+ phones,
88
+ address: new PersonAddress({ address: faker_1.faker.location.streetAddress() }),
89
+ active: true,
90
+ });
91
+ expect(person).toBeInstanceOf(Person);
92
+ expect(person).toBeInstanceOf(entity_base_1.EntityBase);
93
+ expect(person.constructor.name).toBe('Person');
94
+ expect(person.phones).toBeInstanceOf(list_1.List);
95
+ expect(person.phones.toArray()[0]).toBeInstanceOf(PersonPhone);
96
+ expect(person.phones.toArray()[1]).toBeInstanceOf(PersonPhone);
97
+ expect(person.phones.toArray()[0].phone).toBeDefined();
98
+ expect(person.phones.toArray()[1].phone).toBeDefined();
99
+ expect(person.address).toBeInstanceOf(PersonAddress);
100
+ expect(person.address.address).toBeDefined();
101
+ expect(person.name).toBeDefined();
102
+ expect(person.active).toBe(true);
103
+ });
104
+ });
@@ -24,8 +24,7 @@ export declare abstract class RepositoryBase<TEntity extends EntityBase<TEntity>
24
24
  protected findUnique<T>(where: T): Promise<any>;
25
25
  protected findMany<T>(where: T, pagination?: PaginationDto): Promise<any>;
26
26
  protected findManyAndCount<T>(where: T, pagination?: PaginationDto): Promise<ListResponse<TEntity>>;
27
- protected insert(entity: TEntity): any;
28
- protected edit<TWhere = any>(entity: TEntity, updateWhere?: TWhere): Promise<any>;
27
+ protected saveChanges<TWhere = any>(entity: TEntity, updateWhere?: TWhere): any;
29
28
  protected remove<TWhere = any>(where: TWhere, externalServices?: Promise<any>): Promise<any>;
30
29
  private listToRelationActionList;
31
30
  private entityToPrisma;
@@ -72,26 +72,27 @@ class RepositoryBase {
72
72
  }
73
73
  return { items: [], count };
74
74
  }
75
- insert(entity) {
76
- const prismaEntity = this.entityToPrisma(entity, true);
77
- return this.context().create({
78
- data: prismaEntity,
79
- });
80
- }
81
- edit(entity, updateWhere) {
82
- const prismaEntity = this.entityToPrisma(entity, false);
83
- return this.withTransaction((client) => this.context(client)
84
- .update({
85
- where: updateWhere ?? { id: entity._id },
86
- data: prismaEntity,
87
- })
88
- .then(() => {
89
- const { relationUpdates, relationDeletes } = this.listToRelationActionList(entity);
90
- return Promise.all([
91
- ...relationUpdates.map((relation) => client[relation.modelName].updateMany(relation.schema)),
92
- ...relationDeletes.map((relation) => client[relation.modelName].deleteMany(relation.schema)),
93
- ]);
94
- }));
75
+ saveChanges(entity, updateWhere) {
76
+ const prismaEntity = this.entityToPrisma(entity);
77
+ if (entity._action === entity_base_1.EntityActionType.create) {
78
+ return this.context().create({
79
+ data: prismaEntity,
80
+ });
81
+ }
82
+ else {
83
+ return this.withTransaction((client) => this.context(client)
84
+ .update({
85
+ where: updateWhere ?? { id: entity._id },
86
+ data: prismaEntity,
87
+ })
88
+ .then(() => {
89
+ const { relationUpdates, relationDeletes } = this.listToRelationActionList(entity);
90
+ return Promise.all([
91
+ ...relationUpdates.map((relation) => client[relation.modelName].updateMany(relation.schema)),
92
+ ...relationDeletes.map((relation) => client[relation.modelName].deleteMany(relation.schema)),
93
+ ]);
94
+ }));
95
+ }
95
96
  }
96
97
  async remove(where, externalServices) {
97
98
  const entity = await this.findUnique(where);
@@ -126,7 +127,7 @@ class RepositoryBase {
126
127
  modelName: (0, string_1.toCamelCase)(modelName),
127
128
  schema: {
128
129
  where: { id: item._id },
129
- data: this.entityToPrisma(item, false),
130
+ data: this.entityToPrisma(item),
130
131
  },
131
132
  });
132
133
  });
@@ -135,10 +136,10 @@ class RepositoryBase {
135
136
  });
136
137
  return { relationUpdates, relationDeletes };
137
138
  }
138
- entityToPrisma(entity, isCreate) {
139
+ entityToPrisma(entity) {
139
140
  const prismaSchema = {};
140
141
  Object.keys(entity)
141
- .filter((key) => !['id', '_id'].includes(key))
142
+ .filter((key) => !['id', '_id', '_action'].includes(key))
142
143
  .filter((key) => !(entity[key] instanceof Function))
143
144
  .forEach((key) => {
144
145
  if (entity[key] instanceof list_1.List) {
@@ -146,16 +147,17 @@ class RepositoryBase {
146
147
  prismaSchema[key] = {
147
148
  createMany: {
148
149
  data: entity[key].toArray('added').map((item) => {
149
- return this.entityToPrisma(item, isCreate);
150
+ return this.entityToPrisma(item);
150
151
  }),
151
152
  },
152
153
  };
153
154
  }
154
155
  }
155
156
  else if (entity[key] instanceof entity_base_1.EntityBase) {
156
- prismaSchema[key] = isCreate
157
- ? { create: this.entityToPrisma(entity[key], isCreate) }
158
- : { update: this.entityToPrisma(entity[key], isCreate) };
157
+ prismaSchema[key] =
158
+ entity[key]._action === entity_base_1.EntityActionType.create
159
+ ? { create: this.entityToPrisma(entity[key]) }
160
+ : { update: this.entityToPrisma(entity[key]) };
159
161
  }
160
162
  else {
161
163
  prismaSchema[key] = entity[key];
@@ -183,6 +185,7 @@ class RepositoryBase {
183
185
  }
184
186
  createEntity(data) {
185
187
  const entity = new this._modelName();
188
+ entity._action = entity_base_1.EntityActionType.update;
186
189
  entity.automap(data);
187
190
  return entity;
188
191
  }
@@ -1,6 +1,6 @@
1
1
  import { Type } from '@nestjs/common';
2
- import { AutoMappingContext } from './auto-mapping-context';
3
2
  import { AutoMappingClassContext } from './auto-mapping-class-context';
3
+ import { AutoMappingContext } from './auto-mapping-context';
4
4
  import { ForMemberDefinition } from './for-member';
5
5
  interface AutoMappingGetContext {
6
6
  mapContext: AutoMappingContext | null;
@@ -2,8 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AutoMappingList = void 0;
4
4
  const list_1 = require("../utils/list");
5
- const auto_mapping_context_1 = require("./auto-mapping-context");
6
5
  const auto_mapping_class_context_1 = require("./auto-mapping-class-context");
6
+ const auto_mapping_context_1 = require("./auto-mapping-context");
7
7
  class AutoMappingList {
8
8
  static _mappedPropList = new list_1.List(auto_mapping_class_context_1.AutoMappingClassContext);
9
9
  static _mappingProfileList = new list_1.List(auto_mapping_context_1.AutoMappingContext);
@@ -31,7 +31,7 @@ class AutoMappingList {
31
31
  }
32
32
  static getPropDefinitions(source, propName) {
33
33
  return this._mappedPropList
34
- .find((mp) => mp.source === source)
34
+ .find((mp) => mp.source.name === source.name)
35
35
  ?.props.find((prop) => prop.name === propName);
36
36
  }
37
37
  static getTargets(source) {
@@ -46,7 +46,6 @@ class List {
46
46
  this._list.splice(index, 1);
47
47
  if (!this.contains(item, this._removedItemsList)) {
48
48
  this._removedItemsList.push(item);
49
- console.log(this._removedItemsList);
50
49
  }
51
50
  }
52
51
  return this;
@@ -10,16 +10,13 @@ var __metadata = (this && this.__metadata) || function (k, v) {
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const entity_base_1 = require("../database/entity.base");
13
+ const entity_decorator_1 = require("../database/entity.decorator");
13
14
  const auto_mapping_decorator_1 = require("../mapping/auto-mapping.decorator");
14
15
  const list_1 = require("./list");
15
- class EntityTest extends entity_base_1.EntityBase {
16
+ let EntityTest = class EntityTest extends entity_base_1.EntityBase {
16
17
  id;
17
18
  value;
18
- constructor(props) {
19
- super();
20
- this.automap(props);
21
- }
22
- }
19
+ };
23
20
  __decorate([
24
21
  (0, auto_mapping_decorator_1.AutoMap)(),
25
22
  __metadata("design:type", Number)
@@ -28,6 +25,9 @@ __decorate([
28
25
  (0, auto_mapping_decorator_1.AutoMap)(),
29
26
  __metadata("design:type", Number)
30
27
  ], EntityTest.prototype, "value", void 0);
28
+ EntityTest = __decorate([
29
+ (0, entity_decorator_1.Entity)()
30
+ ], EntityTest);
31
31
  describe('List test', () => {
32
32
  let entity;
33
33
  beforeEach(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koalarx/nest",
3
- "version": "1.6.4",
3
+ "version": "1.8.0",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,5 +1,4 @@
1
1
  import { PaginationDto } from '@koalarx/nest/core/dtos/pagination.dto';
2
- import { CreatedRegistreResponseBase } from '../../core/controllers/created-registre-response.base';
3
2
  import { ListResponseBase } from '../../core/controllers/list-response.base';
4
3
  import { EntityBase } from '../../core/database/entity.base';
5
4
  import { IComparableId } from '../../core/utils/interfaces/icomparable';
@@ -10,8 +9,9 @@ export declare abstract class InMemoryBaseRepository<TClass extends EntityBase<a
10
9
  protected findById(id: IComparableId): Promise<TClass | null>;
11
10
  protected findMany<T extends PaginationDto>(query: T, predicate?: (value: TClass, index: number, array: TClass[]) => unknown): Promise<TClass[]>;
12
11
  protected findManyAndCount<T extends PaginationDto>(query: T, predicate?: (value: TClass, index: number, array: TClass[]) => unknown): Promise<ListResponseBase<TClass>>;
13
- protected insert(item: TClass): Promise<CreatedRegistreResponseBase<any>>;
14
- protected edit(item: TClass, updateWhere?: (item: TClass) => boolean): Promise<void>;
12
+ protected saveChanges(item: TClass, updateWhere?: (item: TClass) => boolean): Promise<{
13
+ id: IComparableId;
14
+ } | undefined>;
15
15
  protected remove(predicate: (value: TClass, index: number, obj: TClass[]) => unknown): Promise<void>;
16
16
  private getNewId;
17
17
  }
@@ -4,6 +4,7 @@ exports.InMemoryBaseRepository = void 0;
4
4
  const query_params_1 = require("../../core/constants/query-params");
5
5
  const array_1 = require("@koalarx/utils/operators/array");
6
6
  const node_crypto_1 = require("node:crypto");
7
+ const entity_base_1 = require("../../core/database/entity.base");
7
8
  class InMemoryBaseRepository {
8
9
  typeId;
9
10
  items = [];
@@ -11,7 +12,11 @@ class InMemoryBaseRepository {
11
12
  this.typeId = typeId;
12
13
  }
13
14
  async findById(id) {
14
- return this.items.find((item) => item._id === id) ?? null;
15
+ const entity = this.items.find((item) => item._id === id) ?? null;
16
+ if (entity) {
17
+ entity._action = entity_base_1.EntityActionType.update;
18
+ }
19
+ return entity;
15
20
  }
16
21
  async findMany(query, predicate) {
17
22
  const page = query.page ?? query_params_1.QUERY_FILTER_PARAMS.page;
@@ -19,7 +24,11 @@ class InMemoryBaseRepository {
19
24
  return (0, array_1.klArray)(predicate ? this.items.filter(predicate) : this.items)
20
25
  .orderBy(query.orderBy ?? '', query.direction === 'desc')
21
26
  .getValue()
22
- .slice(page * limit, (page + 1) * limit);
27
+ .slice(page * limit, (page + 1) * limit)
28
+ .map((item) => {
29
+ item._action = entity_base_1.EntityActionType.update;
30
+ return item;
31
+ });
23
32
  }
24
33
  async findManyAndCount(query, predicate) {
25
34
  const items = await this.findMany(query, predicate);
@@ -28,13 +37,13 @@ class InMemoryBaseRepository {
28
37
  count: items.length,
29
38
  };
30
39
  }
31
- async insert(item) {
32
- const id = this.typeId === 'number' ? this.getNewId() : (0, node_crypto_1.randomUUID)();
33
- item.automap({ ...item, id });
34
- this.items.push(item);
35
- return { id: item._id };
36
- }
37
- async edit(item, updateWhere) {
40
+ async saveChanges(item, updateWhere) {
41
+ if (item._action === entity_base_1.EntityActionType.create) {
42
+ const id = this.typeId === 'number' ? this.getNewId() : (0, node_crypto_1.randomUUID)();
43
+ item.automap({ ...item, id });
44
+ this.items.push(item);
45
+ return { id: item._id };
46
+ }
38
47
  const predicate = updateWhere ?? ((itemDB) => itemDB.equals(item));
39
48
  const itemIndex = this.items.findIndex(predicate);
40
49
  if (itemIndex > -1) {