@ptc-org/nestjs-query-sequelize 1.0.0-alpha.1 → 1.0.0-alpha.2

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.
Files changed (35) hide show
  1. package/README.md +5 -5
  2. package/package.json +4 -4
  3. package/src/index.d.ts +2 -0
  4. package/src/index.js.map +1 -0
  5. package/src/module.d.ts +5 -0
  6. package/src/module.js +19 -0
  7. package/src/module.js.map +1 -0
  8. package/src/providers.d.ts +3 -0
  9. package/src/providers.js +21 -0
  10. package/src/providers.js.map +1 -0
  11. package/src/query/aggregate.builder.d.ts +19 -0
  12. package/src/query/aggregate.builder.js +87 -0
  13. package/src/query/aggregate.builder.js.map +1 -0
  14. package/src/query/filter-query.builder.d.ts +96 -0
  15. package/src/query/filter-query.builder.js +203 -0
  16. package/src/query/filter-query.builder.js.map +1 -0
  17. package/src/query/index.d.ts +4 -0
  18. package/src/query/index.js +8 -0
  19. package/src/query/index.js.map +1 -0
  20. package/src/query/sql-comparison.builder.d.ts +26 -0
  21. package/src/query/sql-comparison.builder.js +74 -0
  22. package/src/query/sql-comparison.builder.js.map +1 -0
  23. package/src/query/where.builder.d.ts +24 -0
  24. package/src/query/where.builder.js +81 -0
  25. package/src/query/where.builder.js.map +1 -0
  26. package/src/services/index.d.ts +1 -0
  27. package/src/services/index.js +5 -0
  28. package/src/services/index.js.map +1 -0
  29. package/src/services/relation-query.service.d.ts +119 -0
  30. package/src/services/relation-query.service.js +234 -0
  31. package/src/services/relation-query.service.js.map +1 -0
  32. package/src/services/sequelize-query.service.d.ts +147 -0
  33. package/src/services/sequelize-query.service.js +239 -0
  34. package/src/services/sequelize-query.service.js.map +1 -0
  35. package/CHANGELOG.md +0 -426
@@ -0,0 +1,147 @@
1
+ import { Query, DeleteManyResponse, UpdateManyResponse, DeepPartial, QueryService, Filter, AggregateQuery, AggregateResponse, FindByIdOptions, GetByIdOptions, UpdateOneOptions, DeleteOneOptions } from '@ptc-org/nestjs-query-core';
2
+ import { Model, ModelCtor } from 'sequelize-typescript';
3
+ import { FilterQueryBuilder } from '../query';
4
+ import { RelationQueryService } from './relation-query.service';
5
+ /**
6
+ * Base class for all query services that use a `sequelize` Model.
7
+ *
8
+ * @example
9
+ *
10
+ * ```ts
11
+ * @QueryService(TodoItemEntity)
12
+ * export class TodoItemService extends SequelizeQueryService<TodoItemEntity> {
13
+ * constructor(
14
+ * @InjectRepository(TodoItemEntity) repo: Repository<TodoItemEntity>,
15
+ * ) {
16
+ * super(repo);
17
+ * }
18
+ * }
19
+ * ```
20
+ */
21
+ export declare class SequelizeQueryService<Entity extends Model<Entity, Partial<Entity>>> extends RelationQueryService<Entity> implements QueryService<Entity, DeepPartial<Entity>, DeepPartial<Entity>> {
22
+ readonly model: ModelCtor<Entity>;
23
+ readonly filterQueryBuilder: FilterQueryBuilder<Entity>;
24
+ constructor(model: ModelCtor<Entity>);
25
+ /**
26
+ * Query for multiple entities, using a Query from `@ptc-org/nestjs-query-core`.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const todoItems = await this.service.query({
31
+ * filter: { title: { eq: 'Foo' } },
32
+ * paging: { limit: 10 },
33
+ * sorting: [{ field: "create", direction: SortDirection.DESC }],
34
+ * });
35
+ * ```
36
+ * @param query - The Query used to filter, page, and sort rows.
37
+ */
38
+ query(query: Query<Entity>): Promise<Entity[]>;
39
+ aggregate(filter: Filter<Entity>, aggregate: AggregateQuery<Entity>): Promise<AggregateResponse<Entity>[]>;
40
+ count(filter: Filter<Entity>): Promise<number>;
41
+ /**
42
+ * Find an entity by it's `id`.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const todoItem = await this.service.findById(1);
47
+ * ```
48
+ * @param id - The id of the record to find.
49
+ * @param opts - Additional options
50
+ */
51
+ findById(id: string | number, opts?: FindByIdOptions<Entity>): Promise<Entity | undefined>;
52
+ /**
53
+ * Gets an entity by it's `id`. If the entity is not found a rejected promise is returned.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * try {
58
+ * const todoItem = await this.service.getById(1);
59
+ * } catch(e) {
60
+ * console.error('Unable to find entity with id = 1');
61
+ * }
62
+ * ```
63
+ * @param id - The id of the record to find.
64
+ * @param opts - Additional options
65
+ */
66
+ getById(id: string | number, opts?: GetByIdOptions<Entity>): Promise<Entity>;
67
+ /**
68
+ * Creates a single entity.
69
+ *
70
+ * @example
71
+ * ```ts
72
+ * const todoItem = await this.service.createOne({title: 'Todo Item', completed: false });
73
+ * ```
74
+ * @param record - The entity to create.
75
+ */
76
+ createOne(record: DeepPartial<Entity>): Promise<Entity>;
77
+ /**
78
+ * Create multiple entities.
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * const todoItem = await this.service.createMany([
83
+ * {title: 'Todo Item 1', completed: false },
84
+ * {title: 'Todo Item 2', completed: true },
85
+ * ]);
86
+ * ```
87
+ * @param records - The entities to create.
88
+ */
89
+ createMany(records: DeepPartial<Entity>[]): Promise<Entity[]>;
90
+ /**
91
+ * Update an entity.
92
+ *
93
+ * @example
94
+ * ```ts
95
+ * const updatedEntity = await this.service.updateOne(1, { completed: true });
96
+ * ```
97
+ * @param id - The `id` of the record.
98
+ * @param update - A `Partial` of the entity with fields to update.
99
+ * @param opts - Additional options.
100
+ */
101
+ updateOne(id: number | string, update: DeepPartial<Entity>, opts?: UpdateOneOptions<Entity>): Promise<Entity>;
102
+ /**
103
+ * Update multiple entities with a `@ptc-org/nestjs-query-core` Filter.
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const { updatedCount } = await this.service.updateMany(
108
+ * { completed: true }, // the update to apply
109
+ * { title: { eq: 'Foo Title' } } // Filter to find records to update
110
+ * );
111
+ * ```
112
+ * @param update - A `Partial` of entity with the fields to update
113
+ * @param filter - A Filter used to find the records to update
114
+ */
115
+ updateMany(update: DeepPartial<Entity>, filter: Filter<Entity>): Promise<UpdateManyResponse>;
116
+ /**
117
+ * Delete an entity by `id`.
118
+ *
119
+ * @example
120
+ *
121
+ * ```ts
122
+ * const deletedTodo = await this.service.deleteOne(1);
123
+ * ```
124
+ *
125
+ * @param id - The `id` of the entity to delete.
126
+ * @param opts - Additional options.
127
+ */
128
+ deleteOne(id: string | number, opts?: DeleteOneOptions<Entity>): Promise<Entity>;
129
+ /**
130
+ * Delete multiple records with a `@ptc-org/nestjs-query-core` `Filter`.
131
+ *
132
+ * @example
133
+ *
134
+ * ```ts
135
+ * const { deletedCount } = this.service.deleteMany({
136
+ * created: { lte: new Date('2020-1-1') }
137
+ * });
138
+ * ```
139
+ *
140
+ * @param filter - A `Filter` to find records to delete.
141
+ */
142
+ deleteMany(filter: Filter<Entity>): Promise<DeleteManyResponse>;
143
+ private getChangedValues;
144
+ private ensureEntityDoesNotExist;
145
+ private ensureIdIsNotPresent;
146
+ private primaryKeyValues;
147
+ }
@@ -0,0 +1,239 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SequelizeQueryService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const lodash_pick_1 = (0, tslib_1.__importDefault)(require("lodash.pick"));
6
+ const common_1 = require("@nestjs/common");
7
+ const query_1 = require("../query");
8
+ const relation_query_service_1 = require("./relation-query.service");
9
+ /**
10
+ * Base class for all query services that use a `sequelize` Model.
11
+ *
12
+ * @example
13
+ *
14
+ * ```ts
15
+ * @QueryService(TodoItemEntity)
16
+ * export class TodoItemService extends SequelizeQueryService<TodoItemEntity> {
17
+ * constructor(
18
+ * @InjectRepository(TodoItemEntity) repo: Repository<TodoItemEntity>,
19
+ * ) {
20
+ * super(repo);
21
+ * }
22
+ * }
23
+ * ```
24
+ */
25
+ class SequelizeQueryService extends relation_query_service_1.RelationQueryService {
26
+ constructor(model) {
27
+ super();
28
+ this.model = model;
29
+ this.filterQueryBuilder = new query_1.FilterQueryBuilder(model);
30
+ }
31
+ /**
32
+ * Query for multiple entities, using a Query from `@ptc-org/nestjs-query-core`.
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * const todoItems = await this.service.query({
37
+ * filter: { title: { eq: 'Foo' } },
38
+ * paging: { limit: 10 },
39
+ * sorting: [{ field: "create", direction: SortDirection.DESC }],
40
+ * });
41
+ * ```
42
+ * @param query - The Query used to filter, page, and sort rows.
43
+ */
44
+ async query(query) {
45
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
46
+ return this.model.findAll(this.filterQueryBuilder.findOptions(query));
47
+ }
48
+ async aggregate(filter, aggregate) {
49
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
50
+ const result = await this.model.findAll(this.filterQueryBuilder.aggregateOptions({ filter }, aggregate));
51
+ if (!result) {
52
+ return [{}];
53
+ }
54
+ return query_1.AggregateBuilder.convertToAggregateResponse(result);
55
+ }
56
+ async count(filter) {
57
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
58
+ return this.model.count(this.filterQueryBuilder.countOptions({ filter }));
59
+ }
60
+ /**
61
+ * Find an entity by it's `id`.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * const todoItem = await this.service.findById(1);
66
+ * ```
67
+ * @param id - The id of the record to find.
68
+ * @param opts - Additional options
69
+ */
70
+ async findById(id, opts) {
71
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
72
+ const model = await this.model.findOne(this.filterQueryBuilder.findByIdOptions(id, opts ?? {}));
73
+ if (!model) {
74
+ return undefined;
75
+ }
76
+ return model;
77
+ }
78
+ /**
79
+ * Gets an entity by it's `id`. If the entity is not found a rejected promise is returned.
80
+ *
81
+ * @example
82
+ * ```ts
83
+ * try {
84
+ * const todoItem = await this.service.getById(1);
85
+ * } catch(e) {
86
+ * console.error('Unable to find entity with id = 1');
87
+ * }
88
+ * ```
89
+ * @param id - The id of the record to find.
90
+ * @param opts - Additional options
91
+ */
92
+ async getById(id, opts) {
93
+ const entity = await this.findById(id, opts ?? {});
94
+ if (!entity) {
95
+ throw new common_1.NotFoundException(`Unable to find ${this.model.name} with id: ${id}`);
96
+ }
97
+ return entity;
98
+ }
99
+ /**
100
+ * Creates a single entity.
101
+ *
102
+ * @example
103
+ * ```ts
104
+ * const todoItem = await this.service.createOne({title: 'Todo Item', completed: false });
105
+ * ```
106
+ * @param record - The entity to create.
107
+ */
108
+ async createOne(record) {
109
+ await this.ensureEntityDoesNotExist(record);
110
+ const changedValues = this.getChangedValues(record);
111
+ return this.model.create(changedValues);
112
+ }
113
+ /**
114
+ * Create multiple entities.
115
+ *
116
+ * @example
117
+ * ```ts
118
+ * const todoItem = await this.service.createMany([
119
+ * {title: 'Todo Item 1', completed: false },
120
+ * {title: 'Todo Item 2', completed: true },
121
+ * ]);
122
+ * ```
123
+ * @param records - The entities to create.
124
+ */
125
+ async createMany(records) {
126
+ await Promise.all(records.map((r) => this.ensureEntityDoesNotExist(r)));
127
+ return this.model.bulkCreate(records.map((r) => this.getChangedValues(r)));
128
+ }
129
+ /**
130
+ * Update an entity.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * const updatedEntity = await this.service.updateOne(1, { completed: true });
135
+ * ```
136
+ * @param id - The `id` of the record.
137
+ * @param update - A `Partial` of the entity with fields to update.
138
+ * @param opts - Additional options.
139
+ */
140
+ async updateOne(id, update, opts) {
141
+ this.ensureIdIsNotPresent(update);
142
+ const entity = await this.getById(id, opts);
143
+ const changedValues = this.getChangedValues(update);
144
+ return entity.update(changedValues);
145
+ }
146
+ /**
147
+ * Update multiple entities with a `@ptc-org/nestjs-query-core` Filter.
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * const { updatedCount } = await this.service.updateMany(
152
+ * { completed: true }, // the update to apply
153
+ * { title: { eq: 'Foo Title' } } // Filter to find records to update
154
+ * );
155
+ * ```
156
+ * @param update - A `Partial` of entity with the fields to update
157
+ * @param filter - A Filter used to find the records to update
158
+ */
159
+ async updateMany(update, filter) {
160
+ this.ensureIdIsNotPresent(update);
161
+ const changedValues = this.getChangedValues(update);
162
+ const [count] = await this.model.update(changedValues, this.filterQueryBuilder.updateOptions({ filter }));
163
+ return { updatedCount: count };
164
+ }
165
+ /**
166
+ * Delete an entity by `id`.
167
+ *
168
+ * @example
169
+ *
170
+ * ```ts
171
+ * const deletedTodo = await this.service.deleteOne(1);
172
+ * ```
173
+ *
174
+ * @param id - The `id` of the entity to delete.
175
+ * @param opts - Additional options.
176
+ */
177
+ async deleteOne(id, opts) {
178
+ const entity = await this.getById(id, opts);
179
+ await entity.destroy();
180
+ return entity;
181
+ }
182
+ /**
183
+ * Delete multiple records with a `@ptc-org/nestjs-query-core` `Filter`.
184
+ *
185
+ * @example
186
+ *
187
+ * ```ts
188
+ * const { deletedCount } = this.service.deleteMany({
189
+ * created: { lte: new Date('2020-1-1') }
190
+ * });
191
+ * ```
192
+ *
193
+ * @param filter - A `Filter` to find records to delete.
194
+ */
195
+ async deleteMany(filter) {
196
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
197
+ const deletedCount = await this.model.destroy(this.filterQueryBuilder.destroyOptions({ filter }));
198
+ return { deletedCount: deletedCount || 0 };
199
+ }
200
+ // eslint-disable-next-line @typescript-eslint/ban-types
201
+ getChangedValues(record) {
202
+ if (record instanceof this.model) {
203
+ const recordEntity = record;
204
+ const raw = recordEntity.get({ plain: true });
205
+ const changed = recordEntity.changed();
206
+ if (changed === false) {
207
+ return {};
208
+ }
209
+ return (0, lodash_pick_1.default)(raw, changed);
210
+ }
211
+ return record;
212
+ }
213
+ async ensureEntityDoesNotExist(entity) {
214
+ const pks = this.primaryKeyValues(entity);
215
+ if (Object.keys(pks).length) {
216
+ const found = await this.model.findOne({ where: pks });
217
+ if (found) {
218
+ throw new Error('Entity already exists');
219
+ }
220
+ }
221
+ }
222
+ ensureIdIsNotPresent(entity) {
223
+ if (Object.keys(this.primaryKeyValues(entity)).length) {
224
+ throw new Error('Id cannot be specified when updating');
225
+ }
226
+ }
227
+ primaryKeyValues(entity) {
228
+ const changed = this.getChangedValues(entity);
229
+ return this.model.primaryKeyAttributes.reduce((pks, pk) => {
230
+ const key = pk;
231
+ if (key in changed && changed[key] !== undefined) {
232
+ return { ...pks, [pk]: changed[key] };
233
+ }
234
+ return pks;
235
+ }, {});
236
+ }
237
+ }
238
+ exports.SequelizeQueryService = SequelizeQueryService;
239
+ //# sourceMappingURL=sequelize-query.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sequelize-query.service.js","sourceRoot":"","sources":["../../../../../packages/query-sequelize/src/services/sequelize-query.service.ts"],"names":[],"mappings":"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"}