@opra/sqb 1.26.3 → 1.27.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.
- package/README.md +24 -1
- package/adapter-utils/prepare-filter.d.ts +3 -4
- package/adapter-utils/prepare-filter.js +16 -31
- package/augmentation/datatype-factory.augmentation.js +1 -1
- package/package.json +3 -3
- package/sqb-adapter.d.ts +41 -1
- package/sqb-adapter.js +21 -6
- package/sqb-collection-service.d.ts +141 -159
- package/sqb-collection-service.js +52 -99
- package/sqb-entity-service.d.ts +133 -154
- package/sqb-entity-service.js +129 -132
- package/sqb-service-base.d.ts +17 -13
- package/sqb-service-base.js +15 -17
- package/sqb-singleton-service.d.ts +78 -88
- package/sqb-singleton-service.js +26 -26
package/sqb-entity-service.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { InternalServerError } from '@opra/common';
|
|
2
|
-
import {
|
|
2
|
+
import { sql } from '@sqb/builder';
|
|
3
3
|
import { EntityMetadata } from '@sqb/connect';
|
|
4
4
|
import { isNotNullish } from 'valgen';
|
|
5
5
|
import { SQBAdapter } from './sqb-adapter.js';
|
|
6
6
|
import { SqbServiceBase } from './sqb-service-base.js';
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Base service providing CRUD operations over an SQB entity.
|
|
9
|
+
*
|
|
10
|
+
* @typeParam T - The entity type managed by this service
|
|
10
11
|
*/
|
|
11
12
|
export class SqbEntityService extends SqbServiceBase {
|
|
12
13
|
_dataTypeScope;
|
|
@@ -17,33 +18,32 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
17
18
|
_inputCodecs = {};
|
|
18
19
|
_outputCodecs = {};
|
|
19
20
|
/**
|
|
20
|
-
*
|
|
21
|
+
* Comma-delimited scopes used to filter the API document.
|
|
21
22
|
*/
|
|
22
23
|
scope;
|
|
23
24
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
25
|
+
* Override for the resource name exposed in error messages and API metadata.
|
|
26
|
+
* Accepts a static string or a function that returns one.
|
|
26
27
|
*/
|
|
27
28
|
resourceName;
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
* @type {SqbEntityService.Filter | Function}
|
|
30
|
+
* Filter(s) automatically applied to every query for this service.
|
|
31
|
+
* Useful for multi-tenant isolation or other cross-cutting constraints.
|
|
32
32
|
*/
|
|
33
33
|
commonFilter;
|
|
34
34
|
/**
|
|
35
|
-
*
|
|
35
|
+
* Called whenever a command throws. Useful for logging or transforming errors.
|
|
36
36
|
*
|
|
37
|
-
* @param
|
|
38
|
-
* @param
|
|
37
|
+
* @param error - The thrown error.
|
|
38
|
+
* @param command - The service command during which the error was thrown.
|
|
39
|
+
* @param _this - The service instance.
|
|
39
40
|
*/
|
|
40
41
|
onError;
|
|
41
42
|
/**
|
|
42
|
-
* Constructs a new instance
|
|
43
|
+
* Constructs a new instance.
|
|
43
44
|
*
|
|
44
|
-
* @param dataType - The
|
|
45
|
-
* @param
|
|
46
|
-
* @constructor
|
|
45
|
+
* @param dataType - The entity class or its registered name.
|
|
46
|
+
* @param options - Options for the service.
|
|
47
47
|
*/
|
|
48
48
|
constructor(dataType, options) {
|
|
49
49
|
super(options);
|
|
@@ -53,9 +53,9 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
53
53
|
this.interceptor = options?.interceptor;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
56
|
+
* Returns the resolved OPRA `ComplexType` for this service's entity.
|
|
57
57
|
*
|
|
58
|
-
* @throws
|
|
58
|
+
* @throws If the data type is not registered as a `ComplexType`.
|
|
59
59
|
*/
|
|
60
60
|
get dataType() {
|
|
61
61
|
if (this._dataType && this._dataTypeScope !== this.scope)
|
|
@@ -66,9 +66,9 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
66
66
|
return this._dataType;
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
|
-
*
|
|
69
|
+
* Returns the constructor class of the entity data type.
|
|
70
70
|
*
|
|
71
|
-
* @throws
|
|
71
|
+
* @throws If the data type is not registered as a `ComplexType`.
|
|
72
72
|
*/
|
|
73
73
|
get dataTypeClass() {
|
|
74
74
|
if (!this._dataTypeClass)
|
|
@@ -76,9 +76,9 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
76
76
|
return this._dataTypeClass;
|
|
77
77
|
}
|
|
78
78
|
/**
|
|
79
|
-
*
|
|
79
|
+
* Returns the SQB `EntityMetadata` for the entity class.
|
|
80
80
|
*
|
|
81
|
-
* @throws
|
|
81
|
+
* @throws If the class is not decorated with `@Entity()`.
|
|
82
82
|
*/
|
|
83
83
|
get entityMetadata() {
|
|
84
84
|
if (!this._entityMetadata) {
|
|
@@ -104,10 +104,9 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
104
104
|
return super.for(context, overwriteProperties, overwriteContext);
|
|
105
105
|
}
|
|
106
106
|
/**
|
|
107
|
-
*
|
|
107
|
+
* Returns the resource name used in error messages and API metadata.
|
|
108
108
|
*
|
|
109
|
-
* @
|
|
110
|
-
* @throws {Error} If the collection name is not defined.
|
|
109
|
+
* @throws If neither `resourceName` nor the data type name is available.
|
|
111
110
|
*/
|
|
112
111
|
getResourceName() {
|
|
113
112
|
const out = typeof this.resourceName === 'function'
|
|
@@ -118,11 +117,12 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
118
117
|
throw new Error('resourceName is not defined');
|
|
119
118
|
}
|
|
120
119
|
/**
|
|
121
|
-
*
|
|
120
|
+
* Returns the input codec for the given operation (e.g. `'create'`, `'update'`).
|
|
122
121
|
*
|
|
123
|
-
* @param operation - The operation
|
|
122
|
+
* @param operation - The operation name.
|
|
124
123
|
*/
|
|
125
124
|
getInputCodec(operation) {
|
|
125
|
+
const dataType = this.dataType;
|
|
126
126
|
const cacheKey = operation + (this._dataTypeScope ? ':' + this._dataTypeScope : '');
|
|
127
127
|
let validator = this._inputCodecs[cacheKey];
|
|
128
128
|
if (validator)
|
|
@@ -133,15 +133,17 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
133
133
|
};
|
|
134
134
|
if (operation === 'update')
|
|
135
135
|
options.partial = 'deep';
|
|
136
|
-
const dataType = this.dataType;
|
|
137
136
|
validator = dataType.generateCodec('decode', options);
|
|
138
137
|
this._inputCodecs[cacheKey] = validator;
|
|
139
138
|
return validator;
|
|
140
139
|
}
|
|
141
140
|
/**
|
|
142
|
-
*
|
|
141
|
+
* Returns the output codec for the given operation.
|
|
142
|
+
*
|
|
143
|
+
* @param operation - The operation name.
|
|
143
144
|
*/
|
|
144
145
|
getOutputCodec(operation) {
|
|
146
|
+
const dataType = this.dataType;
|
|
145
147
|
const cacheKey = operation + (this._dataTypeScope ? ':' + this._dataTypeScope : '');
|
|
146
148
|
let validator = this._outputCodecs[cacheKey];
|
|
147
149
|
if (validator)
|
|
@@ -151,16 +153,15 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
151
153
|
partial: 'deep',
|
|
152
154
|
scope: this._dataTypeScope,
|
|
153
155
|
};
|
|
154
|
-
const dataType = this.dataType;
|
|
155
156
|
validator = dataType.generateCodec('decode', options);
|
|
156
157
|
this._outputCodecs[cacheKey] = validator;
|
|
157
158
|
return validator;
|
|
158
159
|
}
|
|
159
160
|
/**
|
|
160
|
-
*
|
|
161
|
+
* Inserts a new record into the database and returns the created document.
|
|
161
162
|
*
|
|
162
|
-
* @param command
|
|
163
|
-
* @returns
|
|
163
|
+
* @param command - The create command.
|
|
164
|
+
* @returns The created document.
|
|
164
165
|
* @protected
|
|
165
166
|
*/
|
|
166
167
|
async _create(command) {
|
|
@@ -177,10 +178,9 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
177
178
|
throw new InternalServerError(`Unknown error while creating document for "${this.getResourceName()}"`);
|
|
178
179
|
}
|
|
179
180
|
/**
|
|
180
|
-
*
|
|
181
|
+
* Inserts a new record into the database without returning it.
|
|
181
182
|
*
|
|
182
|
-
* @param command
|
|
183
|
-
* @returns - A promise that resolves to the created resource
|
|
183
|
+
* @param command - The create command.
|
|
184
184
|
* @protected
|
|
185
185
|
*/
|
|
186
186
|
async _createOnly(command) {
|
|
@@ -193,55 +193,54 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
193
193
|
return await repo.createOnly(data, options);
|
|
194
194
|
}
|
|
195
195
|
/**
|
|
196
|
-
* Returns the count of records
|
|
196
|
+
* Returns the count of records matching the command options.
|
|
197
197
|
*
|
|
198
|
-
* @param command
|
|
199
|
-
* @return - A promise that resolves to the count of records
|
|
198
|
+
* @param command - The count command.
|
|
200
199
|
* @protected
|
|
201
200
|
*/
|
|
202
201
|
async _count(command) {
|
|
203
202
|
const filter = command.options?.filter
|
|
204
|
-
? SQBAdapter.
|
|
203
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
205
204
|
: undefined;
|
|
206
205
|
return this._dbCount({ ...command.options, filter });
|
|
207
206
|
}
|
|
208
207
|
/**
|
|
209
|
-
* Deletes
|
|
208
|
+
* Deletes the record identified by `command.documentId`.
|
|
210
209
|
*
|
|
211
|
-
* @param command
|
|
212
|
-
* @
|
|
210
|
+
* @param command - The delete command.
|
|
211
|
+
* @returns The number of records deleted.
|
|
213
212
|
* @protected
|
|
214
213
|
*/
|
|
215
214
|
async _delete(command) {
|
|
216
215
|
isNotNullish(command.documentId, { label: 'documentId' });
|
|
217
216
|
const filter = command.options?.filter
|
|
218
|
-
? SQBAdapter.
|
|
217
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
219
218
|
: undefined;
|
|
220
219
|
return this._dbDelete(command.documentId, { ...command.options, filter });
|
|
221
220
|
}
|
|
222
221
|
/**
|
|
223
|
-
* Deletes
|
|
222
|
+
* Deletes all records matching the command filter.
|
|
224
223
|
*
|
|
225
|
-
* @param command
|
|
226
|
-
* @
|
|
224
|
+
* @param command - The deleteMany command.
|
|
225
|
+
* @returns The number of records deleted.
|
|
227
226
|
* @protected
|
|
228
227
|
*/
|
|
229
228
|
async _deleteMany(command) {
|
|
230
229
|
const filter = command.options?.filter
|
|
231
|
-
? SQBAdapter.
|
|
230
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
232
231
|
: undefined;
|
|
233
232
|
return await this._dbDeleteMany({ ...command.options, filter });
|
|
234
233
|
}
|
|
235
234
|
/**
|
|
236
|
-
* Checks
|
|
235
|
+
* Checks whether the record identified by `command.documentId` exists.
|
|
237
236
|
*
|
|
238
|
-
* @param command
|
|
237
|
+
* @param command - The exists command.
|
|
239
238
|
* @protected
|
|
240
239
|
*/
|
|
241
240
|
async _exists(command) {
|
|
242
241
|
isNotNullish(command.documentId, { label: 'documentId' });
|
|
243
242
|
const filter = command.options?.filter
|
|
244
|
-
? SQBAdapter.
|
|
243
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
245
244
|
: undefined;
|
|
246
245
|
return await this._dbExists(command.documentId, {
|
|
247
246
|
...command.options,
|
|
@@ -249,30 +248,29 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
249
248
|
});
|
|
250
249
|
}
|
|
251
250
|
/**
|
|
252
|
-
* Checks
|
|
251
|
+
* Checks whether any record matching the command filter exists.
|
|
253
252
|
*
|
|
254
|
-
* @param command
|
|
255
|
-
* @return - A Promise that resolves to a boolean indicating whether the record exists or not.
|
|
253
|
+
* @param command - The existsOne command.
|
|
256
254
|
* @protected
|
|
257
255
|
*/
|
|
258
256
|
async _existsOne(command) {
|
|
259
257
|
const filter = command.options?.filter
|
|
260
|
-
? SQBAdapter.
|
|
258
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
261
259
|
: undefined;
|
|
262
260
|
return await this._dbExistsOne({ ...command.options, filter });
|
|
263
261
|
}
|
|
264
262
|
/**
|
|
265
|
-
* Finds
|
|
263
|
+
* Finds the record identified by `command.documentId`.
|
|
266
264
|
*
|
|
267
|
-
* @param command
|
|
268
|
-
* @
|
|
265
|
+
* @param command - The findById command.
|
|
266
|
+
* @returns The found record, or `undefined` if not found.
|
|
269
267
|
* @protected
|
|
270
268
|
*/
|
|
271
269
|
async _findById(command) {
|
|
272
270
|
isNotNullish(command.documentId, { label: 'documentId' });
|
|
273
271
|
const decode = this.getOutputCodec('find');
|
|
274
272
|
const filter = command.options?.filter
|
|
275
|
-
? SQBAdapter.
|
|
273
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
276
274
|
: undefined;
|
|
277
275
|
const out = await this._dbFindById(command.documentId, {
|
|
278
276
|
...command.options,
|
|
@@ -281,31 +279,31 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
281
279
|
return out ? decode(out) : undefined;
|
|
282
280
|
}
|
|
283
281
|
/**
|
|
284
|
-
* Finds
|
|
282
|
+
* Finds the first record matching the command filter.
|
|
285
283
|
*
|
|
286
|
-
* @param command
|
|
287
|
-
* @
|
|
284
|
+
* @param command - The findOne command.
|
|
285
|
+
* @returns The found record, or `undefined` if not found.
|
|
288
286
|
* @protected
|
|
289
287
|
*/
|
|
290
288
|
async _findOne(command) {
|
|
291
289
|
const decode = this.getOutputCodec('find');
|
|
292
290
|
const filter = command.options?.filter
|
|
293
|
-
? SQBAdapter.
|
|
291
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
294
292
|
: undefined;
|
|
295
293
|
const out = await this._dbFindOne({ ...command.options, filter });
|
|
296
294
|
return out ? decode(out) : undefined;
|
|
297
295
|
}
|
|
298
296
|
/**
|
|
299
|
-
* Finds
|
|
297
|
+
* Finds all records matching the command filter.
|
|
300
298
|
*
|
|
301
|
-
* @param command
|
|
302
|
-
* @
|
|
299
|
+
* @param command - The findMany command.
|
|
300
|
+
* @returns An array of matching records.
|
|
303
301
|
* @protected
|
|
304
302
|
*/
|
|
305
303
|
async _findMany(command) {
|
|
306
304
|
const decode = this.getOutputCodec('find');
|
|
307
305
|
const filter = command.options?.filter
|
|
308
|
-
? SQBAdapter.
|
|
306
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
309
307
|
: undefined;
|
|
310
308
|
const out = await this._dbFindMany({ ...command.options, filter });
|
|
311
309
|
if (out?.length) {
|
|
@@ -314,10 +312,10 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
314
312
|
return out;
|
|
315
313
|
}
|
|
316
314
|
/**
|
|
317
|
-
* Updates
|
|
315
|
+
* Updates the record identified by `command.documentId` and returns it.
|
|
318
316
|
*
|
|
319
|
-
* @param command
|
|
320
|
-
* @returns
|
|
317
|
+
* @param command - The update command.
|
|
318
|
+
* @returns The updated record, or `undefined` if not found.
|
|
321
319
|
* @protected
|
|
322
320
|
*/
|
|
323
321
|
async _update(command) {
|
|
@@ -327,7 +325,7 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
327
325
|
const inputCodec = this.getInputCodec('update');
|
|
328
326
|
const data = inputCodec(input);
|
|
329
327
|
const filter = command.options?.filter
|
|
330
|
-
? SQBAdapter.
|
|
328
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
331
329
|
: undefined;
|
|
332
330
|
const out = await this._dbUpdate(documentId, data, { ...options, filter });
|
|
333
331
|
const outputCodec = this.getOutputCodec('update');
|
|
@@ -335,10 +333,10 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
335
333
|
return outputCodec(out);
|
|
336
334
|
}
|
|
337
335
|
/**
|
|
338
|
-
* Updates
|
|
336
|
+
* Updates the record identified by `command.documentId` without returning it.
|
|
339
337
|
*
|
|
340
|
-
* @param command
|
|
341
|
-
* @returns
|
|
338
|
+
* @param command - The updateOnly command.
|
|
339
|
+
* @returns The number of records modified.
|
|
342
340
|
* @protected
|
|
343
341
|
*/
|
|
344
342
|
async _updateOnly(command) {
|
|
@@ -348,15 +346,15 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
348
346
|
const inputCodec = this.getInputCodec('update');
|
|
349
347
|
const data = inputCodec(input);
|
|
350
348
|
const filter = command.options?.filter
|
|
351
|
-
? SQBAdapter.
|
|
349
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
352
350
|
: undefined;
|
|
353
351
|
return await this._dbUpdateOnly(documentId, data, { ...options, filter });
|
|
354
352
|
}
|
|
355
353
|
/**
|
|
356
|
-
* Updates
|
|
354
|
+
* Updates all records matching the command filter.
|
|
357
355
|
*
|
|
358
|
-
* @param command
|
|
359
|
-
* @
|
|
356
|
+
* @param command - The updateMany command.
|
|
357
|
+
* @returns The number of records modified.
|
|
360
358
|
* @protected
|
|
361
359
|
*/
|
|
362
360
|
async _updateMany(command) {
|
|
@@ -364,15 +362,15 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
364
362
|
const inputCodec = this.getInputCodec('update');
|
|
365
363
|
const data = inputCodec(command.input);
|
|
366
364
|
const filter = command.options?.filter
|
|
367
|
-
? SQBAdapter.
|
|
365
|
+
? SQBAdapter.prepareFilter(command.options.filter)
|
|
368
366
|
: undefined;
|
|
369
367
|
return await this._dbUpdateMany(data, { ...command.options, filter });
|
|
370
368
|
}
|
|
371
369
|
/**
|
|
372
|
-
* Acquires a connection and performs Repository.create
|
|
370
|
+
* Acquires a connection and performs `Repository.create`.
|
|
373
371
|
*
|
|
374
|
-
* @param input - The document to insert
|
|
375
|
-
* @param options - Optional settings
|
|
372
|
+
* @param input - The document to insert.
|
|
373
|
+
* @param options - Optional settings.
|
|
376
374
|
* @protected
|
|
377
375
|
*/
|
|
378
376
|
async _dbCreate(input, options) {
|
|
@@ -381,170 +379,169 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
381
379
|
return await repo.create(input, options);
|
|
382
380
|
}
|
|
383
381
|
/**
|
|
384
|
-
* Acquires a connection and performs Repository.count
|
|
382
|
+
* Acquires a connection and performs `Repository.count`.
|
|
385
383
|
*
|
|
386
|
-
* @param options -
|
|
384
|
+
* @param options - Optional settings.
|
|
387
385
|
* @protected
|
|
388
386
|
*/
|
|
389
387
|
async _dbCount(options) {
|
|
390
388
|
const conn = await this.getConnection();
|
|
391
389
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
392
390
|
if (options?.filter)
|
|
393
|
-
options.filter = SQBAdapter.
|
|
391
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
394
392
|
return await repo.count(options);
|
|
395
393
|
}
|
|
396
394
|
/**
|
|
397
|
-
* Acquires a connection and performs Repository.delete
|
|
395
|
+
* Acquires a connection and performs `Repository.delete`.
|
|
398
396
|
*
|
|
399
|
-
* @param id -
|
|
400
|
-
* @param options - Optional settings
|
|
397
|
+
* @param id - The key field value identifying the record.
|
|
398
|
+
* @param options - Optional settings.
|
|
401
399
|
* @protected
|
|
402
400
|
*/
|
|
403
401
|
async _dbDelete(id, options) {
|
|
404
402
|
const conn = await this.getConnection();
|
|
405
403
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
406
404
|
if (options?.filter)
|
|
407
|
-
options.filter = SQBAdapter.
|
|
405
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
408
406
|
return (await repo.delete(id, options)) ? 1 : 0;
|
|
409
407
|
}
|
|
410
408
|
/**
|
|
411
|
-
* Acquires a connection and performs Repository.deleteMany
|
|
409
|
+
* Acquires a connection and performs `Repository.deleteMany`.
|
|
412
410
|
*
|
|
413
|
-
* @param options - Optional settings
|
|
411
|
+
* @param options - Optional settings.
|
|
414
412
|
* @protected
|
|
415
413
|
*/
|
|
416
414
|
async _dbDeleteMany(options) {
|
|
417
415
|
const conn = await this.getConnection();
|
|
418
416
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
419
417
|
if (options?.filter)
|
|
420
|
-
options.filter = SQBAdapter.
|
|
418
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
421
419
|
return await repo.deleteMany(options);
|
|
422
420
|
}
|
|
423
421
|
/**
|
|
424
|
-
* Acquires a connection and performs Repository.exists
|
|
422
|
+
* Acquires a connection and performs `Repository.exists`.
|
|
425
423
|
*
|
|
426
|
-
* @param id -
|
|
427
|
-
* @param options - Optional settings
|
|
424
|
+
* @param id - The key field value identifying the record.
|
|
425
|
+
* @param options - Optional settings.
|
|
428
426
|
* @protected
|
|
429
427
|
*/
|
|
430
428
|
async _dbExists(id, options) {
|
|
431
429
|
const conn = await this.getConnection();
|
|
432
430
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
433
431
|
if (options?.filter)
|
|
434
|
-
options.filter = SQBAdapter.
|
|
432
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
435
433
|
return await repo.exists(id, options);
|
|
436
434
|
}
|
|
437
435
|
/**
|
|
438
|
-
* Acquires a connection and performs Repository.existsOne
|
|
436
|
+
* Acquires a connection and performs `Repository.existsOne`.
|
|
439
437
|
*
|
|
440
|
-
* @param options - Optional settings
|
|
438
|
+
* @param options - Optional settings.
|
|
441
439
|
* @protected
|
|
442
440
|
*/
|
|
443
441
|
async _dbExistsOne(options) {
|
|
444
442
|
const conn = await this.getConnection();
|
|
445
443
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
446
444
|
if (options?.filter)
|
|
447
|
-
options.filter = SQBAdapter.
|
|
445
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
448
446
|
return await repo.existsOne(options);
|
|
449
447
|
}
|
|
450
448
|
/**
|
|
451
|
-
* Acquires a connection and performs Repository.findById
|
|
449
|
+
* Acquires a connection and performs `Repository.findById`.
|
|
452
450
|
*
|
|
453
|
-
* @param id -
|
|
454
|
-
* @param options - Optional settings
|
|
451
|
+
* @param id - The key field value identifying the record.
|
|
452
|
+
* @param options - Optional settings.
|
|
455
453
|
* @protected
|
|
456
454
|
*/
|
|
457
455
|
async _dbFindById(id, options) {
|
|
458
456
|
const conn = await this.getConnection();
|
|
459
457
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
460
458
|
if (options?.filter)
|
|
461
|
-
options.filter = SQBAdapter.
|
|
459
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
462
460
|
return await repo.findById(id, options);
|
|
463
461
|
}
|
|
464
462
|
/**
|
|
465
|
-
* Acquires a connection and performs Repository.findOne
|
|
463
|
+
* Acquires a connection and performs `Repository.findOne`.
|
|
466
464
|
*
|
|
467
|
-
* @param options - Optional settings
|
|
465
|
+
* @param options - Optional settings.
|
|
468
466
|
* @protected
|
|
469
467
|
*/
|
|
470
468
|
async _dbFindOne(options) {
|
|
471
469
|
const conn = await this.getConnection();
|
|
472
470
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
473
471
|
if (options?.filter)
|
|
474
|
-
options.filter = SQBAdapter.
|
|
472
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
475
473
|
return await repo.findOne({ ...options, offset: options?.skip });
|
|
476
474
|
}
|
|
477
475
|
/**
|
|
478
|
-
* Acquires a connection and performs Repository.findMany
|
|
476
|
+
* Acquires a connection and performs `Repository.findMany`.
|
|
479
477
|
*
|
|
480
|
-
* @param options - Optional settings
|
|
478
|
+
* @param options - Optional settings.
|
|
481
479
|
* @protected
|
|
482
480
|
*/
|
|
483
481
|
async _dbFindMany(options) {
|
|
484
482
|
const conn = await this.getConnection();
|
|
485
483
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
486
484
|
if (options?.filter)
|
|
487
|
-
options.filter = SQBAdapter.
|
|
485
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
488
486
|
return await repo.findMany({ ...options, offset: options?.skip });
|
|
489
487
|
}
|
|
490
488
|
/**
|
|
491
|
-
* Acquires a connection and performs Repository.update
|
|
489
|
+
* Acquires a connection and performs `Repository.update`.
|
|
492
490
|
*
|
|
493
|
-
* @param id -
|
|
494
|
-
* @param data - The update values
|
|
495
|
-
* @param options - Optional settings
|
|
491
|
+
* @param id - The key field value identifying the record.
|
|
492
|
+
* @param data - The update values.
|
|
493
|
+
* @param options - Optional settings.
|
|
496
494
|
* @protected
|
|
497
495
|
*/
|
|
498
496
|
async _dbUpdate(id, data, options) {
|
|
499
497
|
const conn = await this.getConnection();
|
|
500
498
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
501
499
|
if (options?.filter)
|
|
502
|
-
options.filter = SQBAdapter.
|
|
500
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
503
501
|
return await repo.update(id, data, options);
|
|
504
502
|
}
|
|
505
503
|
/**
|
|
506
|
-
* Acquires a connection and performs Repository.updateOnly
|
|
504
|
+
* Acquires a connection and performs `Repository.updateOnly`.
|
|
507
505
|
*
|
|
508
|
-
* @param id -
|
|
509
|
-
* @param data - The update values
|
|
510
|
-
* @param options - Optional settings
|
|
506
|
+
* @param id - The key field value identifying the record.
|
|
507
|
+
* @param data - The update values.
|
|
508
|
+
* @param options - Optional settings.
|
|
511
509
|
* @protected
|
|
512
510
|
*/
|
|
513
511
|
async _dbUpdateOnly(id, data, options) {
|
|
514
512
|
const conn = await this.getConnection();
|
|
515
513
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
516
514
|
if (options?.filter)
|
|
517
|
-
options.filter = SQBAdapter.
|
|
515
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
518
516
|
return (await repo.updateOnly(id, data, options)) ? 1 : 0;
|
|
519
517
|
}
|
|
520
518
|
/**
|
|
521
|
-
* Acquires a connection and performs Repository.updateMany
|
|
519
|
+
* Acquires a connection and performs `Repository.updateMany`.
|
|
522
520
|
*
|
|
523
|
-
* @param data - The update values
|
|
524
|
-
* @param options - Optional settings
|
|
521
|
+
* @param data - The update values.
|
|
522
|
+
* @param options - Optional settings.
|
|
525
523
|
* @protected
|
|
526
524
|
*/
|
|
527
525
|
async _dbUpdateMany(data, options) {
|
|
528
526
|
const conn = await this.getConnection();
|
|
529
527
|
const repo = conn.getRepository(this.dataTypeClass);
|
|
530
528
|
if (options?.filter)
|
|
531
|
-
options.filter = SQBAdapter.
|
|
529
|
+
options.filter = SQBAdapter.prepareFilter(options.filter);
|
|
532
530
|
return await repo.updateMany(data, options);
|
|
533
531
|
}
|
|
534
532
|
/**
|
|
535
|
-
*
|
|
536
|
-
*
|
|
533
|
+
* Builds the common filter for the given command.
|
|
534
|
+
* Used primarily for multi-tenant isolation and similar cross-cutting concerns.
|
|
537
535
|
*
|
|
538
536
|
* @protected
|
|
539
|
-
* @returns
|
|
540
|
-
* that resolves to the common filter, or undefined if not available.
|
|
537
|
+
* @returns The resolved filter input, or `undefined` if none is configured.
|
|
541
538
|
*/
|
|
542
539
|
_getCommonFilter(command) {
|
|
543
540
|
const commonFilter = Array.isArray(this.commonFilter)
|
|
544
541
|
? this.commonFilter
|
|
545
542
|
: [this.commonFilter];
|
|
546
543
|
const mapped = commonFilter.map(f => typeof f === 'function' ? f(command, this) : f);
|
|
547
|
-
return mapped.length > 1 ?
|
|
544
|
+
return mapped.length > 1 ? sql.And(...mapped) : mapped[0];
|
|
548
545
|
}
|
|
549
546
|
async _executeCommand(command, commandFn) {
|
|
550
547
|
let proto;
|
|
@@ -559,7 +556,7 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
559
556
|
if (!(proto instanceof SqbEntityService))
|
|
560
557
|
break;
|
|
561
558
|
}
|
|
562
|
-
|
|
559
|
+
/* Call before[X] hooks */
|
|
563
560
|
if (command.crud === 'create')
|
|
564
561
|
await this._beforeCreate(command);
|
|
565
562
|
else if (command.crud === 'update' && command.byId) {
|
|
@@ -574,12 +571,12 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
574
571
|
else if (command.crud === 'delete' && !command.byId) {
|
|
575
572
|
await this._beforeDeleteMany(command);
|
|
576
573
|
}
|
|
577
|
-
|
|
574
|
+
/* Call command function */
|
|
578
575
|
return commandFn();
|
|
579
576
|
};
|
|
580
577
|
try {
|
|
581
578
|
const result = await next();
|
|
582
|
-
|
|
579
|
+
/* Call after[X] hooks */
|
|
583
580
|
if (command.crud === 'create')
|
|
584
581
|
await this._afterCreate(command, result);
|
|
585
582
|
else if (command.crud === 'update' && command.byId) {
|
|
@@ -598,7 +595,7 @@ export class SqbEntityService extends SqbServiceBase {
|
|
|
598
595
|
}
|
|
599
596
|
catch (e) {
|
|
600
597
|
Error.captureStackTrace(e, this._executeCommand);
|
|
601
|
-
await this.onError?.(e, this);
|
|
598
|
+
await this.onError?.(e, command, this);
|
|
602
599
|
throw e;
|
|
603
600
|
}
|
|
604
601
|
}
|