@opra/sqb 0.33.13 → 1.0.0-alpha.10

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 (43) hide show
  1. package/cjs/{transform-filter.js → adapter-utils/parse-filter.js} +37 -12
  2. package/cjs/augmentation/datatype-factory.augmentation.js +79 -0
  3. package/cjs/augmentation/mixin-type.augmentation.js +5 -3
  4. package/cjs/index.js +3 -4
  5. package/cjs/sqb-adapter.js +71 -100
  6. package/cjs/sqb-collection-service.js +297 -0
  7. package/cjs/sqb-entity-service.js +446 -25
  8. package/cjs/sqb-singleton-service.js +181 -0
  9. package/esm/{transform-filter.js → adapter-utils/parse-filter.js} +36 -11
  10. package/esm/augmentation/datatype-factory.augmentation.js +77 -0
  11. package/esm/augmentation/mapped-type.augmentation.js +1 -1
  12. package/esm/augmentation/mixin-type.augmentation.js +6 -4
  13. package/esm/index.js +3 -4
  14. package/esm/sqb-adapter.js +71 -100
  15. package/esm/sqb-collection-service.js +293 -0
  16. package/esm/sqb-entity-service.js +446 -25
  17. package/esm/sqb-singleton-service.js +177 -0
  18. package/package.json +16 -11
  19. package/types/adapter-utils/parse-filter.d.ts +10 -0
  20. package/types/index.d.ts +3 -4
  21. package/types/sqb-adapter.d.ts +10 -8
  22. package/types/sqb-collection-service.d.ts +233 -0
  23. package/types/sqb-entity-service.d.ts +418 -18
  24. package/types/sqb-singleton-service.d.ts +137 -0
  25. package/cjs/augmentation/api-document-factory.augmentation.js +0 -20
  26. package/cjs/augmentation/type-document-factory.augmentation.js +0 -99
  27. package/cjs/sqb-collection.js +0 -80
  28. package/cjs/sqb-entity-service-base.js +0 -170
  29. package/cjs/sqb-singleton.js +0 -44
  30. package/cjs/transform-key-values.js +0 -14
  31. package/esm/augmentation/api-document-factory.augmentation.js +0 -18
  32. package/esm/augmentation/type-document-factory.augmentation.js +0 -97
  33. package/esm/sqb-collection.js +0 -76
  34. package/esm/sqb-entity-service-base.js +0 -166
  35. package/esm/sqb-singleton.js +0 -40
  36. package/esm/transform-key-values.js +0 -11
  37. package/types/augmentation/type-document-factory.augmentation.d.ts +0 -1
  38. package/types/sqb-collection.d.ts +0 -31
  39. package/types/sqb-entity-service-base.d.ts +0 -31
  40. package/types/sqb-singleton.d.ts +0 -18
  41. package/types/transform-filter.d.ts +0 -3
  42. package/types/transform-key-values.d.ts +0 -3
  43. /package/types/augmentation/{api-document-factory.augmentation.d.ts → datatype-factory.augmentation.d.ts} +0 -0
@@ -1,41 +1,462 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SqbEntityService = void 0;
4
- const sqb_entity_service_base_js_1 = require("./sqb-entity-service-base.js");
5
- class SqbEntityService extends sqb_entity_service_base_js_1.SqbEntityServiceBase {
6
- constructor(typeClass, options) {
7
- super(typeClass, options);
8
- this.typeClass = typeClass;
4
+ const common_1 = require("@opra/common");
5
+ const core_1 = require("@opra/core");
6
+ const connect_1 = require("@sqb/connect");
7
+ const sqb_adapter_js_1 = require("./sqb-adapter.js");
8
+ /**
9
+ * @class SqbEntityService
10
+ * @template T - The data type class type of the resource
11
+ */
12
+ class SqbEntityService extends core_1.ServiceBase {
13
+ /**
14
+ * Constructs a new instance
15
+ *
16
+ * @param dataType - The data type of the returning results
17
+ * @param [options] - The options for the service.
18
+ * @constructor
19
+ */
20
+ constructor(dataType, options) {
21
+ super();
22
+ this._inputCodecs = {};
23
+ this._outputCodecs = {};
24
+ this._dataType_ = dataType;
25
+ this.db = options?.db;
26
+ this.$resourceName = options?.resourceName;
27
+ this.$commonFilter = this.$commonFilter || options?.commonFilter;
28
+ this.$interceptor = this.$interceptor || options?.interceptor;
9
29
  }
10
- async count(options) {
11
- return super._count(options);
30
+ /**
31
+ * Retrieves the OPRA data type
32
+ *
33
+ * @throws {NotAcceptableError} If the data type is not a ComplexType.
34
+ */
35
+ get dataType() {
36
+ if (!this._dataType)
37
+ this._dataType = this.context.document.node.getComplexType(this._dataType_);
38
+ return this._dataType;
12
39
  }
13
- async create(data, options) {
14
- return super._create(data, options);
40
+ /**
41
+ * Retrieves the Class of the data type
42
+ *
43
+ * @throws {NotAcceptableError} If the data type is not a ComplexType.
44
+ */
45
+ get dataTypeClass() {
46
+ if (!this._dataTypeClass)
47
+ this._dataTypeClass = this.entityMetadata.ctor;
48
+ return this._dataTypeClass;
15
49
  }
16
- async delete(keyValue, options) {
17
- return super._delete(keyValue, options);
50
+ /**
51
+ * Retrieves the SQB entity metadata object
52
+ *
53
+ * @throws {TypeError} If metadata is not available
54
+ */
55
+ get entityMetadata() {
56
+ if (!this._entityMetadata) {
57
+ const t = this.dataType.ctor;
58
+ const metadata = connect_1.EntityMetadata.get(t);
59
+ if (!metadata)
60
+ throw new TypeError(`Class (${t}) is not decorated with $Entity() decorator`);
61
+ this._entityMetadata = metadata;
62
+ }
63
+ return this._entityMetadata;
18
64
  }
19
- async deleteMany(options) {
20
- return super._deleteMany(options);
65
+ /**
66
+ * Retrieves the resource name.
67
+ *
68
+ * @returns {string} The resource name.
69
+ * @throws {Error} If the collection name is not defined.
70
+ */
71
+ getResourceName() {
72
+ const out = typeof this.$resourceName === 'function' ? this.$resourceName(this) : this.$resourceName || this.dataType.name;
73
+ if (out)
74
+ return out;
75
+ throw new Error('resourceName is not defined');
21
76
  }
22
- async find(keyValue, options) {
23
- return super._find(keyValue, options);
77
+ /**
78
+ * Retrieves the codec for the specified operation.
79
+ *
80
+ * @param operation - The operation to retrieve the encoder for. Valid values are 'create' and 'update'.
81
+ */
82
+ getInputCodec(operation) {
83
+ let validator = this._inputCodecs[operation];
84
+ if (validator)
85
+ return validator;
86
+ const options = { projection: '*' };
87
+ if (operation === 'update')
88
+ options.partial = 'deep';
89
+ const dataType = this.dataType;
90
+ validator = dataType.generateCodec('decode', options);
91
+ this._inputCodecs[operation] = validator;
92
+ return validator;
24
93
  }
25
- async findOne(options) {
26
- return super._findOne(options);
94
+ /**
95
+ * Retrieves the codec.
96
+ */
97
+ getOutputCodec(operation) {
98
+ let validator = this._outputCodecs[operation];
99
+ if (validator)
100
+ return validator;
101
+ const options = { projection: '*', partial: 'deep' };
102
+ const dataType = this.dataType;
103
+ validator = dataType.generateCodec('decode', options);
104
+ this._outputCodecs[operation] = validator;
105
+ return validator;
27
106
  }
28
- async findMany(options) {
29
- return super._findMany(options);
107
+ /**
108
+ * Insert a new record into database
109
+ *
110
+ * @param {PartialDTO<T>} input - The input data
111
+ * @param {SqbEntityService.CreateOptions} [options] - The options object
112
+ * @returns {Promise<PartialDTO<T>>} A promise that resolves to the created resource
113
+ * @throws {InternalServerError} if an unknown error occurs while creating the resource
114
+ * @protected
115
+ */
116
+ async _create(input, options) {
117
+ const inputCodec = this.getInputCodec('create');
118
+ const outputCodec = this.getOutputCodec('create');
119
+ const data = inputCodec(input);
120
+ const out = await this._dbCreate(data, options);
121
+ if (out)
122
+ return outputCodec(out);
123
+ throw new common_1.InternalServerError(`Unknown error while creating document for "${this.getResourceName()}"`);
30
124
  }
31
- async exists(options) {
32
- return super._exists(options);
125
+ /**
126
+ * Returns the count of records based on the provided options
127
+ *
128
+ * @param {SqbEntityService.CountOptions} options - The options for the count operation.
129
+ * @return {Promise<number>} - A promise that resolves to the count of records
130
+ * @protected
131
+ */
132
+ async _count(options) {
133
+ return this._dbCount(options);
33
134
  }
34
- async update(keyValue, data, options) {
35
- return super._update(keyValue, data, options);
135
+ /**
136
+ * Deletes a record from the collection.
137
+ *
138
+ * @param {SQBAdapter.IdOrIds} id - The ID of the document to delete.
139
+ * @param {SqbEntityService.DeleteOptions} [options] - Optional delete options.
140
+ * @return {Promise<number>} - A Promise that resolves to the number of documents deleted.
141
+ * @protected
142
+ */
143
+ async _delete(id, options) {
144
+ return this._dbDelete(id, options);
36
145
  }
37
- async updateMany(data, options) {
38
- return super._updateMany(data, options);
146
+ /**
147
+ * Deletes multiple documents from the collection that meet the specified filter criteria.
148
+ *
149
+ * @param {SqbEntityService.DeleteManyOptions} options - The options for the delete operation.
150
+ * @return {Promise<number>} - A promise that resolves to the number of documents deleted.
151
+ * @protected
152
+ */
153
+ async _deleteMany(options) {
154
+ return await this._dbDeleteMany(options);
155
+ }
156
+ /**
157
+ * Checks if a record with the given id exists.
158
+ *
159
+ * @param {SQBAdapter.IdOrIds} id - The id of the object to check.
160
+ * @param {SqbEntityService.ExistsOptions} [options] - The options for the query (optional).
161
+ * @return {Promise<boolean>} - A Promise that resolves to a boolean indicating whether the record exists or not.
162
+ * @protected
163
+ */
164
+ async _exists(id, options) {
165
+ return await this._dbExists(id, options);
166
+ }
167
+ /**
168
+ * Checks if a record with the given arguments exists.
169
+ *
170
+ * @param {SqbEntityService.ExistsOneOptions} [options] - The options for the query (optional).
171
+ * @return {Promise<boolean>} - A Promise that resolves to a boolean indicating whether the record exists or not.
172
+ * @protected
173
+ */
174
+ async _existsOne(options) {
175
+ return await this._dbExistsOne(options);
176
+ }
177
+ /**
178
+ * Finds a record by ID.
179
+ *
180
+ * @param {SQBAdapter.Id} id - The ID of the record.
181
+ * @param {SqbEntityService.FindOneOptions} [options] - The options for the find query.
182
+ * @return {Promise<PartialDTO<T | undefined>>} - A promise resolving to the found document, or undefined if not found.
183
+ * @protected
184
+ */
185
+ async _findById(id, options) {
186
+ const decode = this.getOutputCodec('find');
187
+ const out = await this._dbFindById(id, options);
188
+ return out ? decode(out) : undefined;
189
+ }
190
+ /**
191
+ * Finds a record in the collection that matches the specified options.
192
+ *
193
+ * @param {SqbEntityService.FindOneOptions} [options] - The options for the query.
194
+ * @return {Promise<PartialDTO<T> | undefined>} A promise that resolves with the found document or undefined if no document is found.
195
+ * @protected
196
+ */
197
+ async _findOne(options) {
198
+ const decode = this.getOutputCodec('find');
199
+ const out = await this._dbFindOne(options);
200
+ return out ? decode(out) : undefined;
201
+ }
202
+ /**
203
+ * Finds multiple records in collection.
204
+ *
205
+ * @param {SqbEntityService.FindManyOptions} [options] - The options for the find operation.
206
+ * @return A Promise that resolves to an array of partial outputs of type T.
207
+ * @protected
208
+ */
209
+ async _findMany(options) {
210
+ const decode = this.getOutputCodec('find');
211
+ const out = await this._dbFindMany(options);
212
+ if (out?.length) {
213
+ return out.map(x => decode(x));
214
+ }
215
+ return out;
216
+ }
217
+ /**
218
+ * Updates a record with the given id in the collection.
219
+ *
220
+ * @param {SQBAdapter.IdOrIds} id - The id of the document to update.
221
+ * @param {PatchDTO<T>} input - The partial input object containing the fields to update.
222
+ * @param {SqbEntityService.UpdateOptions} [options] - The options for the update operation.
223
+ * @returns {Promise<PartialDTO<T> | undefined>} A promise that resolves to the updated document or
224
+ * undefined if the document was not found.
225
+ * @protected
226
+ */
227
+ async _update(id, input, options) {
228
+ const inputCodec = this.getInputCodec('update');
229
+ const data = inputCodec(input);
230
+ const out = await this._dbUpdate(id, data, options);
231
+ const outputCodec = this.getOutputCodec('update');
232
+ if (out)
233
+ return outputCodec(out);
234
+ }
235
+ /**
236
+ * Updates a record in the collection with the specified ID and returns updated record count
237
+ *
238
+ * @param {any} id - The ID of the document to update.
239
+ * @param {PatchDTO<T>} input - The partial input data to update the document with.
240
+ * @param {SqbEntityService.UpdateOptions} options - The options for updating the document.
241
+ * @returns {Promise<number>} - A promise that resolves to the number of documents modified.
242
+ * @protected
243
+ */
244
+ async _updateOnly(id, input, options) {
245
+ const inputCodec = this.getInputCodec('create');
246
+ const data = inputCodec(input);
247
+ return await this._dbUpdateOnly(id, data, options);
248
+ }
249
+ /**
250
+ * Updates multiple records in the collection based on the specified input and options.
251
+ *
252
+ * @param {PatchDTO<T>} input - The partial input to update the documents with.
253
+ * @param {SqbEntityService.UpdateManyOptions} options - The options for updating the documents.
254
+ * @return {Promise<number>} - A promise that resolves to the number of documents matched and modified.
255
+ * @protected
256
+ */
257
+ async _updateMany(input, options) {
258
+ const inputCodec = this.getInputCodec('update');
259
+ const data = inputCodec(input);
260
+ return await this._dbUpdateMany(data, options);
261
+ }
262
+ /**
263
+ * Acquires a connection and performs Repository.create operation
264
+ *
265
+ * @param input - The document to insert
266
+ * @param options - Optional settings for the command
267
+ * @protected
268
+ */
269
+ async _dbCreate(input, options) {
270
+ const conn = await this.getConnection();
271
+ const repo = conn.getRepository(this.dataTypeClass);
272
+ return await repo.create(input, options);
273
+ }
274
+ /**
275
+ * Acquires a connection and performs Repository.count operation
276
+ *
277
+ * @param options - The options for counting documents.
278
+ * @protected
279
+ */
280
+ async _dbCount(options) {
281
+ const conn = await this.getConnection();
282
+ const repo = conn.getRepository(this.dataTypeClass);
283
+ if (options?.filter)
284
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
285
+ return await repo.count(options);
286
+ }
287
+ /**
288
+ * Acquires a connection and performs Repository.delete operation
289
+ *
290
+ * @param id - Value of the key field used to select the record
291
+ * @param options - Optional settings for the command
292
+ * @protected
293
+ */
294
+ async _dbDelete(id, options) {
295
+ const conn = await this.getConnection();
296
+ const repo = conn.getRepository(this.dataTypeClass);
297
+ if (options?.filter)
298
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
299
+ return (await repo.delete(id, options)) ? 1 : 0;
300
+ }
301
+ /**
302
+ * Acquires a connection and performs Repository.deleteMany operation
303
+ *
304
+ * @param options - Optional settings for the command
305
+ * @protected
306
+ */
307
+ async _dbDeleteMany(options) {
308
+ const conn = await this.getConnection();
309
+ const repo = conn.getRepository(this.dataTypeClass);
310
+ if (options?.filter)
311
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
312
+ return await repo.deleteMany(options);
313
+ }
314
+ /**
315
+ * Acquires a connection and performs Repository.exists operation
316
+ *
317
+ * @param id - Value of the key field used to select the record
318
+ * @param options - Optional settings for the command
319
+ * @protected
320
+ */
321
+ async _dbExists(id, options) {
322
+ const conn = await this.getConnection();
323
+ const repo = conn.getRepository(this.dataTypeClass);
324
+ if (options?.filter)
325
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
326
+ return await repo.exists(id, options);
327
+ }
328
+ /**
329
+ * Acquires a connection and performs Repository.existsOne operation
330
+ *
331
+ * @param options - Optional settings for the command
332
+ * @protected
333
+ */
334
+ async _dbExistsOne(options) {
335
+ const conn = await this.getConnection();
336
+ const repo = conn.getRepository(this.dataTypeClass);
337
+ if (options?.filter)
338
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
339
+ return await repo.existsOne(options);
340
+ }
341
+ /**
342
+ * Acquires a connection and performs Repository.findById operation
343
+ *
344
+ * @param id - Value of the key field used to select the record
345
+ * @param options - Optional settings for the command
346
+ * @protected
347
+ */
348
+ async _dbFindById(id, options) {
349
+ const conn = await this.getConnection();
350
+ const repo = conn.getRepository(this.dataTypeClass);
351
+ if (options?.filter)
352
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
353
+ return await repo.findById(id, options);
354
+ }
355
+ /**
356
+ * Acquires a connection and performs Repository.findOne operation
357
+ *
358
+ * @param options - Optional settings for the command
359
+ * @protected
360
+ */
361
+ async _dbFindOne(options) {
362
+ const conn = await this.getConnection();
363
+ const repo = conn.getRepository(this.dataTypeClass);
364
+ if (options?.filter)
365
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
366
+ return await repo.findOne(options);
367
+ }
368
+ /**
369
+ * Acquires a connection and performs Repository.findMany operation
370
+ *
371
+ * @param options - Optional settings for the command
372
+ * @protected
373
+ */
374
+ async _dbFindMany(options) {
375
+ const conn = await this.getConnection();
376
+ const repo = conn.getRepository(this.dataTypeClass);
377
+ if (options?.filter)
378
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
379
+ return await repo.findMany(options);
380
+ }
381
+ /**
382
+ * Acquires a connection and performs Repository.update operation
383
+ *
384
+ * @param id - Value of the key field used to select the record
385
+ * @param data - The update values to be applied to the document
386
+ * @param options - Optional settings for the command
387
+ * @protected
388
+ */
389
+ async _dbUpdate(id, data, options) {
390
+ const conn = await this.getConnection();
391
+ const repo = conn.getRepository(this.dataTypeClass);
392
+ if (options?.filter)
393
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
394
+ return await repo.update(id, data, options);
395
+ }
396
+ /**
397
+ * Acquires a connection and performs Repository.updateOnly operation
398
+ *
399
+ * @param id - Value of the key field used to select the record
400
+ * @param data - The update values to be applied to the document
401
+ * @param options - Optional settings for the command
402
+ * @protected
403
+ */
404
+ async _dbUpdateOnly(id, data, options) {
405
+ const conn = await this.getConnection();
406
+ const repo = conn.getRepository(this.dataTypeClass);
407
+ if (options?.filter)
408
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
409
+ return await repo.updateOnly(id, data, options);
410
+ }
411
+ /**
412
+ * Acquires a connection and performs Repository.updateMany operation
413
+ *
414
+ * @param data - The update values to be applied to the document
415
+ * @param options - Optional settings for the command
416
+ * @protected
417
+ */
418
+ async _dbUpdateMany(data, options) {
419
+ const conn = await this.getConnection();
420
+ const repo = conn.getRepository(this.dataTypeClass);
421
+ if (options?.filter)
422
+ options.filter = sqb_adapter_js_1.SQBAdapter.parseFilter(options.filter);
423
+ return await repo.updateMany(data, options);
424
+ }
425
+ /**
426
+ * Retrieves the database connection.
427
+ *
428
+ * @protected
429
+ *
430
+ * @throws {Error} If the context or database is not set.
431
+ */
432
+ getConnection() {
433
+ const db = typeof this.db === 'function' ? this.db(this) : this.db;
434
+ if (!db)
435
+ throw new Error(`Database not set!`);
436
+ return db;
437
+ }
438
+ /**
439
+ * Retrieves the common filter used for querying documents.
440
+ * This method is mostly used for security issues like securing multi-tenant applications.
441
+ *
442
+ * @protected
443
+ * @returns {FilterInput | Promise<FilterInput> | undefined} The common filter or a Promise
444
+ * that resolves to the common filter, or undefined if not available.
445
+ */
446
+ _getCommonFilter(args) {
447
+ return typeof this.$commonFilter === 'function' ? this.$commonFilter(args, this) : this.$commonFilter;
448
+ }
449
+ async _intercept(callback, args) {
450
+ try {
451
+ if (this.$interceptor)
452
+ return this.$interceptor(callback, args, this);
453
+ return callback();
454
+ }
455
+ catch (e) {
456
+ Error.captureStackTrace(e, this._intercept);
457
+ await this.$onError?.(e, this);
458
+ throw e;
459
+ }
39
460
  }
40
461
  }
41
462
  exports.SqbEntityService = SqbEntityService;
@@ -0,0 +1,181 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SqbSingletonService = void 0;
4
+ const common_1 = require("@opra/common");
5
+ const connect_1 = require("@sqb/connect");
6
+ const sqb_adapter_js_1 = require("./sqb-adapter.js");
7
+ const sqb_entity_service_js_1 = require("./sqb-entity-service.js");
8
+ /**
9
+ * @class SqbSingletonService
10
+ * @template T - The data type class type of the resource
11
+ */
12
+ class SqbSingletonService extends sqb_entity_service_js_1.SqbEntityService {
13
+ /**
14
+ * Constructs a new instance
15
+ *
16
+ * @param {Type | string} dataType - The data type of the array elements.
17
+ * @param {SqbSingletonService.Options} [options] - The options for the array service.
18
+ * @constructor
19
+ */
20
+ constructor(dataType, options) {
21
+ super(dataType, options);
22
+ this.id = this.id || options?.id || 1;
23
+ }
24
+ /**
25
+ * Asserts the existence of a resource based on the given options.
26
+ *
27
+ * @returns {Promise<void>} A Promise that resolves when the resource exists.
28
+ * @throws {ResourceNotAvailableError} If the resource does not exist.
29
+ */
30
+ async assert(options) {
31
+ if (!(await this.exists(options)))
32
+ throw new common_1.ResourceNotAvailableError(this.getResourceName());
33
+ }
34
+ /**
35
+ * Inserts a single record into the database.
36
+ *
37
+ * @param {PartialDTO<T>} input - The input data
38
+ * @param {SqbSingletonService.CreateOptions} [options] - The options object
39
+ * @returns {Promise<PartialDTO<T>>} A promise that resolves to the created resource
40
+ * @throws {Error} if an unknown error occurs while creating the resource
41
+ */
42
+ async create(input, options) {
43
+ const info = {
44
+ crud: 'create',
45
+ method: 'create',
46
+ byId: false,
47
+ input,
48
+ options,
49
+ };
50
+ return this._intercept(async () => {
51
+ const primaryFields = connect_1.EntityMetadata.getPrimaryIndexColumns(this.entityMetadata);
52
+ const data = { ...input };
53
+ if (primaryFields.length > 1) {
54
+ if (typeof primaryFields !== 'object') {
55
+ throw new TypeError(`"${this.entityMetadata.name}" should has multiple primary key fields. So you should provide and object that contains key fields`);
56
+ }
57
+ for (const field of primaryFields) {
58
+ data[field.name] = this.id[field.name];
59
+ }
60
+ }
61
+ else
62
+ data[primaryFields[0].name] = this.id;
63
+ return await this._create(data, options);
64
+ }, info);
65
+ }
66
+ /**
67
+ * Deletes the singleton record
68
+ *
69
+ * @param {SqbSingletonService.DeleteOptions} [options] - The options object
70
+ * @return {Promise<number>} - A Promise that resolves to the number of records deleted
71
+ */
72
+ async delete(options) {
73
+ const info = {
74
+ crud: 'delete',
75
+ method: 'delete',
76
+ byId: true,
77
+ documentId: this.id,
78
+ options,
79
+ };
80
+ return this._intercept(async () => {
81
+ const filter = sqb_adapter_js_1.SQBAdapter.parseFilter([await this._getCommonFilter(info), options?.filter]);
82
+ return this._delete(this.id, { ...options, filter });
83
+ }, info);
84
+ }
85
+ /**
86
+ * Checks if the singleton record exists.
87
+ *
88
+ * @param {SqbSingletonService.ExistsOptions} [options] - The options for the query (optional).
89
+ * @return {Promise<boolean>} - A Promise that resolves to a boolean indicating whether the record exists or not.
90
+ */
91
+ async exists(options) {
92
+ const info = {
93
+ crud: 'read',
94
+ method: 'exists',
95
+ byId: true,
96
+ documentId: this.id,
97
+ options,
98
+ };
99
+ return this._intercept(async () => {
100
+ const filter = sqb_adapter_js_1.SQBAdapter.parseFilter([await this._getCommonFilter(info), options?.filter]);
101
+ return this._exists(this.id, { ...options, filter });
102
+ }, info);
103
+ }
104
+ /**
105
+ * Finds the singleton record. Returns `undefined` if not found
106
+ *
107
+ * @param {SqbSingletonService.FindOneOptions} options - The options for the query.
108
+ * @return {Promise<PartialDTO<T> | undefined>} A promise that resolves with the found document or undefined if no document is found.
109
+ */
110
+ async find(options) {
111
+ const info = {
112
+ crud: 'read',
113
+ method: 'findById',
114
+ byId: true,
115
+ documentId: this.id,
116
+ options,
117
+ };
118
+ return this._intercept(async () => {
119
+ const filter = sqb_adapter_js_1.SQBAdapter.parseFilter([await this._getCommonFilter(info), options?.filter]);
120
+ return this._findById(this.id, { ...options, filter });
121
+ }, info);
122
+ }
123
+ /**
124
+ * Retrieves the singleton record. Throws error if not found.
125
+ *
126
+ * @param {SqbSingletonService.FindOptions} [options] - Optional options for the `find` operation.
127
+ * @returns {Promise<PartialDTO<T>>} - A promise that resolves to the retrieved document,
128
+ * or rejects with a ResourceNotFoundError if the document does not exist.
129
+ * @throws {ResourceNotAvailableError} - If the document does not exist.
130
+ */
131
+ async get(options) {
132
+ const out = await this.find(options);
133
+ if (!out)
134
+ throw new common_1.ResourceNotAvailableError(this.getResourceName());
135
+ return out;
136
+ }
137
+ /**
138
+ * Updates the singleton.
139
+ *
140
+ * @param {PatchDTO<T>} input - The partial input object containing the fields to update.
141
+ * @param {SqbSingletonService.UpdateOptions} [options] - The options for the update operation.
142
+ * @returns {Promise<PartialDTO<T> | undefined>} A promise that resolves to the updated document or
143
+ * undefined if the document was not found.
144
+ */
145
+ async update(input, options) {
146
+ const info = {
147
+ crud: 'update',
148
+ method: 'update',
149
+ documentId: this.id,
150
+ byId: true,
151
+ input,
152
+ options,
153
+ };
154
+ return this._intercept(async () => {
155
+ const filter = sqb_adapter_js_1.SQBAdapter.parseFilter([await this._getCommonFilter(info), options?.filter]);
156
+ return this._update(this.id, input, { ...options, filter });
157
+ }, info);
158
+ }
159
+ /**
160
+ * Updates the singleton and returns updated record count
161
+ *
162
+ * @param {PatchDTO<T>} input - The partial input data to update the document with.
163
+ * @param {SqbSingletonService.UpdateOptions} options - The options for updating the document.
164
+ * @returns {Promise<number>} - A promise that resolves to the number of documents modified.
165
+ */
166
+ async updateOnly(input, options) {
167
+ const info = {
168
+ crud: 'update',
169
+ method: 'update',
170
+ documentId: this.id,
171
+ byId: true,
172
+ input,
173
+ options,
174
+ };
175
+ return this._intercept(async () => {
176
+ const filter = sqb_adapter_js_1.SQBAdapter.parseFilter([await this._getCommonFilter(info), options?.filter]);
177
+ return this._updateOnly(this.id, input, { ...options, filter });
178
+ }, info);
179
+ }
180
+ }
181
+ exports.SqbSingletonService = SqbSingletonService;