@opra/mongodb 1.0.0-alpha.2 → 1.0.0-alpha.20

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.
@@ -2,8 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MongoNestedService = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const lodash_omit_1 = tslib_1.__importDefault(require("lodash.omit"));
6
5
  const common_1 = require("@opra/common");
6
+ const lodash_omit_1 = tslib_1.__importDefault(require("lodash.omit"));
7
+ const valgen_1 = require("valgen");
7
8
  const mongo_adapter_js_1 = require("./mongo-adapter.js");
8
9
  const mongo_service_js_1 = require("./mongo-service.js");
9
10
  /**
@@ -25,7 +26,19 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
25
26
  this.fieldName = fieldName;
26
27
  this.nestedKey = options?.nestedKey || '_id';
27
28
  this.defaultLimit = options?.defaultLimit || 10;
28
- this.$nestedFilter = options?.$nestedFilter;
29
+ this.nestedFilter = options?.nestedFilter;
30
+ }
31
+ /**
32
+ * Retrieves the data type of the array field
33
+ *
34
+ * @returns {ComplexType} The complex data type of the field.
35
+ * @throws {NotAcceptableError} If the data type is not a ComplexType.
36
+ */
37
+ get dataType() {
38
+ const t = super.dataType.getField(this.fieldName).type;
39
+ if (!(t instanceof common_1.ComplexType))
40
+ throw new common_1.NotAcceptableError(`Data type "${t.name}" is not a ComplexType`);
41
+ return t;
29
42
  }
30
43
  /**
31
44
  * Asserts whether a resource with the specified parentId and id exists.
@@ -38,8 +51,9 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
38
51
  * @throws {ResourceNotAvailableError} - If the resource does not exist.
39
52
  */
40
53
  async assert(documentId, id, options) {
41
- if (!(await this.exists(documentId, id, options)))
54
+ if (!(await this.exists(documentId, id, options))) {
42
55
  throw new common_1.ResourceNotAvailableError(this.getResourceName() + '.' + this.nestedKey, documentId + '/' + id);
56
+ }
43
57
  }
44
58
  /**
45
59
  * Adds a single item into the array field.
@@ -51,24 +65,21 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
51
65
  * @throws {ResourceNotAvailableError} - If the parent document is not found.
52
66
  */
53
67
  async create(documentId, input, options) {
54
- const id = input._id || this._generateId();
55
- if (id != null)
56
- input._id = id;
57
- const info = {
68
+ const command = {
58
69
  crud: 'create',
59
70
  method: 'create',
60
71
  byId: false,
61
72
  documentId,
62
- nestedId: id,
63
73
  input,
64
74
  options,
65
75
  };
66
- return this._intercept(() => this._create(documentId, input, options), info);
76
+ return this._executeCommand(command, () => this._create(command));
67
77
  }
68
- async _create(documentId, input, options) {
69
- const encode = this.getEncoder('create');
70
- const doc = encode(input);
71
- doc._id = doc._id || this._generateId();
78
+ async _create(command) {
79
+ const inputCodec = this.getInputCodec('create');
80
+ const { documentId, options } = command;
81
+ const doc = inputCodec(command.input);
82
+ doc._id = doc._id || this._generateId(command);
72
83
  const docFilter = mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, ['_id']);
73
84
  const r = await this._dbUpdateOne(docFilter, {
74
85
  $push: { [this.fieldName]: doc },
@@ -76,12 +87,20 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
76
87
  if (r.matchedCount) {
77
88
  if (!options)
78
89
  return doc;
79
- const id = doc[this.nestedKey];
80
- const out = await this._findById(documentId, id, {
81
- ...options,
82
- filter: undefined,
83
- skip: undefined,
84
- });
90
+ const findCommand = {
91
+ crud: 'read',
92
+ method: 'findById',
93
+ byId: true,
94
+ documentId,
95
+ nestedId: doc[this.nestedKey],
96
+ options: {
97
+ ...options,
98
+ sort: undefined,
99
+ filter: undefined,
100
+ skip: undefined,
101
+ },
102
+ };
103
+ const out = await this._findById(findCommand);
85
104
  if (out)
86
105
  return out;
87
106
  }
@@ -95,20 +114,22 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
95
114
  * @returns {Promise<number>} - A promise that resolves to the count of documents.
96
115
  */
97
116
  async count(documentId, options) {
98
- const info = {
117
+ const command = {
99
118
  crud: 'read',
100
119
  method: 'count',
101
120
  byId: false,
102
121
  documentId,
103
122
  options,
104
123
  };
105
- return this._intercept(async () => {
106
- const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info)]);
107
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(info), options?.filter]);
108
- return this._count(documentId, { ...options, filter, documentFilter });
109
- }, info);
124
+ return this._executeCommand(command, async () => {
125
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
126
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(command), command.options?.filter]);
127
+ command.options = { ...command.options, filter, documentFilter };
128
+ return this._count(command);
129
+ });
110
130
  }
111
- async _count(documentId, options) {
131
+ async _count(command) {
132
+ const { documentId, options } = command;
112
133
  const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
113
134
  mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, ['_id']),
114
135
  options?.documentFilter,
@@ -141,7 +162,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
141
162
  * @return {Promise<number>} - A Promise that resolves to the number of elements deleted (1 if successful, 0 if not).
142
163
  */
143
164
  async delete(documentId, nestedId, options) {
144
- const info = {
165
+ const command = {
145
166
  crud: 'delete',
146
167
  method: 'delete',
147
168
  byId: true,
@@ -149,13 +170,17 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
149
170
  nestedId,
150
171
  options,
151
172
  };
152
- return this._intercept(async () => {
153
- const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info)]);
154
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(info), options?.filter]);
155
- return this._delete(documentId, nestedId, { ...options, filter, documentFilter });
156
- }, info);
173
+ return this._executeCommand(command, async () => {
174
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
175
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(command), command.options?.filter]);
176
+ command.options = { ...command.options, filter, documentFilter };
177
+ return this._delete(command);
178
+ });
157
179
  }
158
- async _delete(documentId, nestedId, options) {
180
+ async _delete(command) {
181
+ const { documentId, nestedId, options } = command;
182
+ (0, valgen_1.isNotNullish)(documentId, { label: 'documentId' });
183
+ (0, valgen_1.isNotNullish)(documentId, { label: 'nestedId' });
159
184
  const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
160
185
  mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, ['_id']),
161
186
  options?.documentFilter,
@@ -174,20 +199,22 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
174
199
  * @returns {Promise<number>} - A Promise that resolves to the number of items deleted.
175
200
  */
176
201
  async deleteMany(documentId, options) {
177
- const info = {
202
+ const command = {
178
203
  crud: 'delete',
179
204
  method: 'deleteMany',
180
205
  byId: false,
181
206
  documentId,
182
207
  options,
183
208
  };
184
- return this._intercept(async () => {
185
- const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info)]);
186
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(info), options?.filter]);
187
- return this._deleteMany(documentId, { ...options, filter, documentFilter });
188
- }, info);
209
+ return this._executeCommand(command, async () => {
210
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
211
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(command), command.options?.filter]);
212
+ command.options = { ...command.options, filter, documentFilter };
213
+ return this._deleteMany(command);
214
+ });
189
215
  }
190
- async _deleteMany(documentId, options) {
216
+ async _deleteMany(command) {
217
+ const { documentId, options } = command;
191
218
  const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
192
219
  mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, ['_id']),
193
220
  options?.documentFilter,
@@ -211,7 +238,24 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
211
238
  * @returns {Promise<boolean>} - A promise that resolves to a boolean indicating if the record exists or not.
212
239
  */
213
240
  async exists(documentId, nestedId, options) {
214
- return !!(await this.findById(documentId, nestedId, { ...options, projection: ['_id'] }));
241
+ const command = {
242
+ crud: 'read',
243
+ method: 'exists',
244
+ byId: true,
245
+ documentId,
246
+ nestedId,
247
+ options,
248
+ };
249
+ return this._executeCommand(command, async () => {
250
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
251
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
252
+ await this._getNestedFilter(command),
253
+ documentFilter,
254
+ command.options?.filter,
255
+ ]);
256
+ command.options = { ...command.options, filter };
257
+ return !!(await this._findById(command));
258
+ });
215
259
  }
216
260
  /**
217
261
  * Checks if an object with the given arguments exists.
@@ -221,7 +265,20 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
221
265
  * @return {Promise<boolean>} - A Promise that resolves to a boolean indicating whether the object exists or not.
222
266
  */
223
267
  async existsOne(documentId, options) {
224
- return !!(await this.findOne(documentId, { ...options, projection: ['_id'] }));
268
+ const command = {
269
+ crud: 'read',
270
+ method: 'exists',
271
+ byId: false,
272
+ documentId,
273
+ options,
274
+ };
275
+ return this._executeCommand(command, async () => {
276
+ const documentFilter = await this._getDocumentFilter(command);
277
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([documentFilter, command.options?.filter]);
278
+ const findCommand = command;
279
+ findCommand.options = { ...command.options, filter, documentFilter, projection: ['_id'] };
280
+ return !!(await this._findOne(findCommand));
281
+ });
225
282
  }
226
283
  /**
227
284
  * Finds an element in array field by its parent ID and ID.
@@ -232,7 +289,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
232
289
  * @returns {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the found document or undefined if not found.
233
290
  */
234
291
  async findById(documentId, nestedId, options) {
235
- const info = {
292
+ const command = {
236
293
  crud: 'read',
237
294
  method: 'findById',
238
295
  byId: true,
@@ -240,24 +297,32 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
240
297
  nestedId,
241
298
  options,
242
299
  };
243
- return this._intercept(async () => {
244
- const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info)]);
245
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(info), options?.filter]);
246
- return this._findById(documentId, nestedId, { ...options, filter, documentFilter });
247
- }, info);
300
+ return this._executeCommand(command, async () => {
301
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
302
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(command), command.options?.filter]);
303
+ command.options = { ...command.options, filter, documentFilter };
304
+ return this._findById(command);
305
+ });
248
306
  }
249
- async _findById(documentId, nestedId, options) {
307
+ async _findById(command) {
308
+ const { documentId, nestedId, options } = command;
309
+ (0, valgen_1.isNotNullish)(documentId, { label: 'documentId' });
310
+ (0, valgen_1.isNotNullish)(nestedId, { label: 'nestedId' });
250
311
  const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
251
312
  mongo_adapter_js_1.MongoAdapter.prepareKeyValues(nestedId, [this.nestedKey]),
252
313
  options?.filter,
253
314
  ]);
254
- const rows = await this._findMany(documentId, {
255
- ...options,
256
- filter,
257
- limit: 1,
258
- skip: undefined,
259
- sort: undefined,
260
- });
315
+ const findManyCommand = {
316
+ ...command,
317
+ options: {
318
+ ...options,
319
+ filter,
320
+ limit: 1,
321
+ skip: undefined,
322
+ sort: undefined,
323
+ },
324
+ };
325
+ const rows = await this._findMany(findManyCommand);
261
326
  return rows?.[0];
262
327
  }
263
328
  /**
@@ -268,24 +333,31 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
268
333
  * @returns {Promise<PartialDTO<T> | undefined>} A promise that resolves to the first matching document, or `undefined` if no match is found.
269
334
  */
270
335
  async findOne(documentId, options) {
271
- const info = {
336
+ const command = {
272
337
  crud: 'read',
273
338
  method: 'findOne',
274
339
  byId: false,
275
340
  documentId,
276
341
  options,
277
342
  };
278
- return this._intercept(async () => {
279
- const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info)]);
280
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(info), options?.filter]);
281
- return this._findOne(documentId, { ...options, filter, documentFilter });
282
- }, info);
283
- }
284
- async _findOne(documentId, options) {
285
- const rows = await this._findMany(documentId, {
286
- ...options,
287
- limit: 1,
343
+ return this._executeCommand(command, async () => {
344
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
345
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(command), command.options?.filter]);
346
+ command.options = { ...command.options, filter, documentFilter };
347
+ return this._findOne(command);
288
348
  });
349
+ }
350
+ async _findOne(command) {
351
+ const { documentId, options } = command;
352
+ (0, valgen_1.isNotNullish)(documentId, { label: 'documentId' });
353
+ const findManyCommand = {
354
+ ...command,
355
+ options: {
356
+ ...options,
357
+ limit: 1,
358
+ },
359
+ };
360
+ const rows = await this._findMany(findManyCommand);
289
361
  return rows?.[0];
290
362
  }
291
363
  /**
@@ -296,28 +368,31 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
296
368
  * @returns {Promise<PartialDTO<T>[]>} - The found documents.
297
369
  */
298
370
  async findMany(documentId, options) {
299
- const args = {
371
+ const command = {
300
372
  crud: 'read',
301
373
  method: 'findMany',
302
374
  byId: false,
303
375
  documentId,
304
376
  options,
305
377
  };
306
- return this._intercept(async () => {
307
- const documentFilter = await this._getDocumentFilter(args);
308
- const nestedFilter = await this._getNestedFilter(args);
309
- return this._findMany(documentId, {
310
- ...options,
311
- documentFilter,
378
+ return this._executeCommand(command, async () => {
379
+ const documentFilter = await this._getDocumentFilter(command);
380
+ const nestedFilter = await this._getNestedFilter(command);
381
+ command.options = {
382
+ ...command.options,
312
383
  nestedFilter,
313
- limit: options?.limit || this.defaultLimit,
314
- });
315
- }, args);
384
+ documentFilter,
385
+ limit: command.options?.limit || this.defaultLimit,
386
+ };
387
+ return this._findMany(command);
388
+ });
316
389
  }
317
- async _findMany(documentId, options) {
390
+ async _findMany(command) {
391
+ const { documentId, options } = command;
392
+ (0, valgen_1.isNotNullish)(documentId, { label: 'documentId' });
318
393
  const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
319
394
  mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, ['_id']),
320
- options.documentFilter,
395
+ options?.documentFilter,
321
396
  ]);
322
397
  const mongoOptions = {
323
398
  ...(0, lodash_omit_1.default)(options, ['documentFilter', 'nestedFilter', 'projection', 'sort', 'skip', 'limit', 'filter', 'count']),
@@ -328,7 +403,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
328
403
  { $unwind: { path: '$' + this.fieldName } },
329
404
  { $replaceRoot: { newRoot: '$' + this.fieldName } },
330
405
  ];
331
- if (options?.filter || options.nestedFilter) {
406
+ if (options?.filter || options?.nestedFilter) {
332
407
  const optionsFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([options?.filter, options.nestedFilter]);
333
408
  stages.push({ $match: optionsFilter });
334
409
  }
@@ -340,14 +415,14 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
340
415
  stages.push({ $sort: sort });
341
416
  }
342
417
  stages.push({ $limit: limit });
343
- const dataType = this.getDataType();
418
+ const dataType = this.dataType;
344
419
  const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection);
345
420
  if (projection)
346
421
  stages.push({ $project: projection });
347
- const decode = this.getDecoder();
348
422
  const cursor = await this._dbAggregate(stages, mongoOptions);
349
423
  try {
350
- const out = await (await cursor.toArray()).map((r) => decode(r));
424
+ const outputCodec = this.getOutputCodec('find');
425
+ const out = await (await cursor.toArray()).map((r) => outputCodec(r));
351
426
  return out;
352
427
  }
353
428
  finally {
@@ -363,28 +438,31 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
363
438
  * @returns {Promise<PartialDTO<T>[]>} - The found documents.
364
439
  */
365
440
  async findManyWithCount(documentId, options) {
366
- const args = {
441
+ const command = {
367
442
  crud: 'read',
368
443
  method: 'findMany',
369
444
  byId: false,
370
445
  documentId,
371
446
  options,
372
447
  };
373
- return this._intercept(async () => {
374
- const documentFilter = await this._getDocumentFilter(args);
375
- const nestedFilter = await this._getNestedFilter(args);
376
- return this._findManyWithCount(documentId, {
377
- ...options,
378
- documentFilter,
448
+ return this._executeCommand(command, async () => {
449
+ const documentFilter = await this._getDocumentFilter(command);
450
+ const nestedFilter = await this._getNestedFilter(command);
451
+ command.options = {
452
+ ...command.options,
379
453
  nestedFilter,
380
- limit: options?.limit || this.defaultLimit,
381
- });
382
- }, args);
454
+ documentFilter,
455
+ limit: command.options?.limit || this.defaultLimit,
456
+ };
457
+ return this._findManyWithCount(command);
458
+ });
383
459
  }
384
- async _findManyWithCount(documentId, options) {
460
+ async _findManyWithCount(command) {
461
+ const { documentId, options } = command;
462
+ (0, valgen_1.isNotNullish)(documentId, { label: 'documentId' });
385
463
  const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
386
464
  mongo_adapter_js_1.MongoAdapter.prepareKeyValues(documentId, ['_id']),
387
- options.documentFilter,
465
+ options?.documentFilter,
388
466
  ]);
389
467
  const mongoOptions = {
390
468
  ...(0, lodash_omit_1.default)(options, ['pick', 'include', 'omit', 'sort', 'skip', 'limit', 'filter', 'count']),
@@ -402,8 +480,8 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
402
480
  },
403
481
  },
404
482
  ];
405
- if (options?.filter || options.nestedFilter) {
406
- const optionsFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([options?.filter, options.nestedFilter]);
483
+ if (options?.filter || options?.nestedFilter) {
484
+ const optionsFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([options?.filter, options?.nestedFilter]);
407
485
  dataStages.push({ $match: optionsFilter });
408
486
  }
409
487
  if (options?.skip)
@@ -414,19 +492,19 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
414
492
  dataStages.push({ $sort: sort });
415
493
  }
416
494
  dataStages.push({ $limit: limit });
417
- const dataType = this.getDataType();
495
+ const dataType = this.dataType;
418
496
  const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection);
419
497
  if (projection)
420
498
  dataStages.push({ $project: projection });
421
- const decode = this.getDecoder();
422
499
  const cursor = await this._dbAggregate(stages, {
423
500
  ...mongoOptions,
424
501
  });
425
502
  try {
426
503
  const facetResult = await cursor.toArray();
504
+ const outputCodec = this.getOutputCodec('find');
427
505
  return {
428
506
  count: facetResult[0].count[0].totalMatches || 0,
429
- items: facetResult[0].data.map((r) => decode(r)),
507
+ items: facetResult[0].data.map((r) => outputCodec(r)),
430
508
  };
431
509
  }
432
510
  finally {
@@ -445,8 +523,9 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
445
523
  */
446
524
  async get(documentId, nestedId, options) {
447
525
  const out = await this.findById(documentId, nestedId, options);
448
- if (!out)
526
+ if (!out) {
449
527
  throw new common_1.ResourceNotAvailableError(this.getResourceName() + '.' + this.nestedKey, documentId + '/' + nestedId);
528
+ }
450
529
  return out;
451
530
  }
452
531
  /**
@@ -455,21 +534,44 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
455
534
  * @param {AnyId} documentId - The ID of the document to update.
456
535
  * @param {AnyId} nestedId - The ID of the item to update within the document.
457
536
  * @param {PatchDTO<T>} input - The new data to update the item with.
458
- * @param {MongoNestedService.UpdateOptions<T>} [options] - Additional update options.
537
+ * @param {MongoNestedService.UpdateOneOptions<T>} [options] - Additional update options.
459
538
  * @returns {Promise<PartialDTO<T> | undefined>} The updated item or undefined if it does not exist.
460
539
  * @throws {Error} If an error occurs while updating the item.
461
540
  */
462
541
  async update(documentId, nestedId, input, options) {
463
- const r = await this.updateOnly(documentId, nestedId, input, options);
464
- if (!r)
465
- return;
466
- const out = await this._findById(documentId, nestedId, {
467
- ...options,
468
- sort: undefined,
542
+ const command = {
543
+ crud: 'update',
544
+ method: 'update',
545
+ byId: true,
546
+ documentId,
547
+ nestedId,
548
+ input,
549
+ options,
550
+ };
551
+ return this._executeCommand(command, async () => {
552
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
553
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(command), command.options?.filter]);
554
+ command.options = {
555
+ ...command.options,
556
+ filter,
557
+ documentFilter,
558
+ };
559
+ const r = await this._updateOnly(command);
560
+ if (r) {
561
+ const findCommand = {
562
+ crud: 'read',
563
+ method: 'findById',
564
+ byId: true,
565
+ documentId,
566
+ nestedId,
567
+ options: { ...options, sort: undefined },
568
+ };
569
+ const out = this._findById(findCommand);
570
+ if (out)
571
+ return out;
572
+ }
573
+ throw new common_1.ResourceNotAvailableError(this.getResourceName() + '.' + this.nestedKey, documentId + '/' + nestedId);
469
574
  });
470
- if (out)
471
- return out;
472
- throw new common_1.ResourceNotAvailableError(this.getResourceName() + '.' + this.nestedKey, documentId + '/' + nestedId);
473
575
  }
474
576
  /**
475
577
  * Update an array element with new data. Returns 1 if document updated 0 otherwise.
@@ -477,29 +579,45 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
477
579
  * @param {MongoAdapter.AnyId} documentId - The ID of the parent document.
478
580
  * @param {MongoAdapter.AnyId} nestedId - The ID of the document to update.
479
581
  * @param {PatchDTO<T>} input - The partial input object containing the fields to update.
480
- * @param {MongoNestedService.UpdateOptions<T>} [options] - Optional update options.
582
+ * @param {MongoNestedService.UpdateOneOptions<T>} [options] - Optional update options.
481
583
  * @returns {Promise<number>} - A promise that resolves to the number of elements updated.
482
584
  */
483
585
  async updateOnly(documentId, nestedId, input, options) {
484
- const info = {
586
+ const command = {
485
587
  crud: 'update',
486
588
  method: 'update',
487
589
  byId: true,
488
590
  documentId,
489
591
  nestedId,
592
+ input,
490
593
  options,
491
594
  };
492
- return this._intercept(async () => {
493
- const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info)]);
494
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(info), options?.filter]);
495
- return this._updateOnly(documentId, nestedId, input, { ...options, filter, documentFilter });
496
- }, info);
595
+ return this._executeCommand(command, async () => {
596
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
597
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(command), command.options?.filter]);
598
+ command.options = {
599
+ ...command.options,
600
+ filter,
601
+ documentFilter,
602
+ };
603
+ return await this._updateOnly(command);
604
+ });
497
605
  }
498
- async _updateOnly(documentId, nestedId, input, options) {
606
+ async _updateOnly(command) {
607
+ const { documentId, nestedId, options } = command;
608
+ (0, valgen_1.isNotNullish)(documentId, { label: 'documentId' });
609
+ (0, valgen_1.isNotNullish)(nestedId, { label: 'nestedId' });
499
610
  let filter = mongo_adapter_js_1.MongoAdapter.prepareKeyValues(nestedId, [this.nestedKey]);
500
611
  if (options?.filter)
501
612
  filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([filter, options?.filter]);
502
- return await this._updateMany(documentId, input, { ...options, filter });
613
+ const updateManyCommand = {
614
+ ...command,
615
+ options: {
616
+ ...command.options,
617
+ filter,
618
+ },
619
+ };
620
+ return await this._updateMany(updateManyCommand);
503
621
  }
504
622
  /**
505
623
  * Updates multiple array elements in document
@@ -510,7 +628,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
510
628
  * @returns {Promise<number>} - A promise that resolves to the number of documents updated.
511
629
  */
512
630
  async updateMany(documentId, input, options) {
513
- const info = {
631
+ const command = {
514
632
  crud: 'update',
515
633
  method: 'updateMany',
516
634
  documentId,
@@ -518,15 +636,19 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
518
636
  input,
519
637
  options,
520
638
  };
521
- return this._intercept(async () => {
522
- const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info)]);
523
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(info), options?.filter]);
524
- return this._updateMany(documentId, input, { ...options, filter, documentFilter });
525
- }, info);
639
+ return this._executeCommand(command, async () => {
640
+ const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command)]);
641
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(command), command.options?.filter]);
642
+ command.options = { ...command.options, filter, documentFilter };
643
+ return this._updateMany(command);
644
+ });
526
645
  }
527
- async _updateMany(documentId, input, options) {
528
- const encode = this.getEncoder('update');
529
- const doc = encode(input, { coerce: true });
646
+ async _updateMany(command) {
647
+ const { documentId, input } = command;
648
+ (0, valgen_1.isNotNullish)(documentId, { label: 'documentId' });
649
+ let options = command.options;
650
+ const inputCodec = this.getInputCodec('update');
651
+ const doc = inputCodec(input);
530
652
  if (!Object.keys(doc).length)
531
653
  return 0;
532
654
  const matchFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
@@ -543,22 +665,18 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
543
665
  fieldPrefix: this.fieldName + (options?.filter ? '.$[elem].' : '.$[].'),
544
666
  });
545
667
  const r = await this._dbUpdateOne(matchFilter, update, options);
546
- if (options?.count)
547
- return await this._count(documentId, options);
668
+ if (options?.count) {
669
+ const countCommand = {
670
+ crud: 'read',
671
+ method: 'count',
672
+ byId: false,
673
+ documentId,
674
+ options,
675
+ };
676
+ return await this._count(countCommand);
677
+ }
548
678
  return r.modifiedCount || 0;
549
679
  }
550
- /**
551
- * Retrieves the data type of the array field
552
- *
553
- * @returns {ComplexType} The complex data type of the field.
554
- * @throws {NotAcceptableError} If the data type is not a ComplexType.
555
- */
556
- getDataType() {
557
- const t = super.getDataType().getField(this.fieldName).type;
558
- if (!(t instanceof common_1.ComplexType))
559
- throw new common_1.NotAcceptableError(`Data type "${t.name}" is not a ComplexType`);
560
- return t;
561
- }
562
680
  /**
563
681
  * Retrieves the common filter used for querying array elements.
564
682
  * This method is mostly used for security issues like securing multi-tenant applications.
@@ -568,7 +686,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
568
686
  * that resolves to the common filter, or undefined if not available.
569
687
  */
570
688
  _getNestedFilter(args) {
571
- return typeof this.$nestedFilter === 'function' ? this.$nestedFilter(args, this) : this.$nestedFilter;
689
+ return typeof this.nestedFilter === 'function' ? this.nestedFilter(args, this) : this.nestedFilter;
572
690
  }
573
691
  }
574
692
  exports.MongoNestedService = MongoNestedService;