@opra/mongodb 1.3.1 → 1.4.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.
@@ -22,11 +22,11 @@ class MongoPatchGenerator {
22
22
  };
23
23
  }
24
24
  _processComplexType(ctx, dataType, path, input) {
25
- if (input.$add) {
26
- this._processAdd(ctx, dataType, path, input.$add);
25
+ if (input._$push) {
26
+ this._processPush(ctx, dataType, path, input._$push);
27
27
  }
28
- if (input.$remove) {
29
- this._processRemove(ctx, dataType, path, input.$remove);
28
+ if (input._$pull) {
29
+ this._processPull(ctx, dataType, path, input._$pull);
30
30
  }
31
31
  const keys = Object.keys(input);
32
32
  const pathDot = path + (path ? '.' : '');
@@ -45,20 +45,24 @@ class MongoPatchGenerator {
45
45
  value = input[key];
46
46
  field = dataType.fields.get(key);
47
47
  if (!field) {
48
- if (dataType.additionalFields === true) {
48
+ if (dataType.additionalFields) {
49
49
  if (value === null) {
50
50
  ctx.$unset = ctx.$unset || {};
51
51
  ctx.$unset[pathDot + key] = 1;
52
52
  }
53
53
  else {
54
54
  ctx.$set = ctx.$set || {};
55
+ if (dataType.additionalFields instanceof common_1.ComplexType) {
56
+ /** Process nested object */
57
+ this._processComplexType(ctx, dataType.additionalFields, pathDot + key, value);
58
+ continue;
59
+ }
55
60
  ctx.$set[pathDot + key] = value;
56
61
  }
57
62
  }
58
63
  continue;
59
64
  }
60
- if (field.readonly)
61
- continue;
65
+ // if (field.readonly) continue;
62
66
  if (value === null) {
63
67
  ctx.$unset = ctx.$unset || {};
64
68
  ctx.$unset[pathDot + field.name] = 1;
@@ -83,8 +87,8 @@ class MongoPatchGenerator {
83
87
  /** Remove key field from object */
84
88
  delete v[keyField];
85
89
  /** Add array filter */
86
- ctx.arrayFilters = ctx.arrayFilters || {};
87
- ctx.arrayFilters[`${arrayFilterName}.${keyField}`] = keyValue;
90
+ ctx.arrayFilters = ctx.arrayFilters || [];
91
+ ctx.arrayFilters.push({ [`${arrayFilterName}.${keyField}`]: keyValue });
88
92
  /** Process each object in array */
89
93
  this._processComplexType(ctx, field.type, pathDot + field.name + `.$[${arrayFilterName}]`, v);
90
94
  }
@@ -101,7 +105,7 @@ class MongoPatchGenerator {
101
105
  ctx.$set[pathDot + field.name] = value;
102
106
  }
103
107
  }
104
- _processAdd(ctx, dataType, path, input) {
108
+ _processPush(ctx, dataType, path, input) {
105
109
  let field;
106
110
  let key;
107
111
  let value;
@@ -120,14 +124,14 @@ class MongoPatchGenerator {
120
124
  if (Array.isArray(value)) {
121
125
  value.forEach(v => {
122
126
  if (!v[keyField]) {
123
- throw new TypeError(`You must provide a key value of ${field.type.name} for $add operation.`);
127
+ throw new TypeError(`You must provide a key value of ${field.type.name} for $push operation.`);
124
128
  }
125
129
  });
126
130
  ctx.$push[pathDot + key] = { $each: value };
127
131
  }
128
132
  else {
129
133
  if (!value[keyField]) {
130
- throw new TypeError(`You must provide a key value of ${field.type.name} for $add operation.`);
134
+ throw new TypeError(`You must provide a key value of ${field.type.name} for $push operation.`);
131
135
  }
132
136
  ctx.$push[pathDot + key] = value;
133
137
  }
@@ -137,7 +141,7 @@ class MongoPatchGenerator {
137
141
  ctx.$push[pathDot + key] = Array.isArray(value) ? { $each: value } : value;
138
142
  }
139
143
  }
140
- _processRemove(ctx, dataType, path, input) {
144
+ _processPull(ctx, dataType, path, input) {
141
145
  let field;
142
146
  let key;
143
147
  let value;
package/cjs/index.js CHANGED
@@ -8,3 +8,4 @@ tslib_1.__exportStar(require("./services/mongo-entity-service.js"), exports);
8
8
  tslib_1.__exportStar(require("./services/mongo-nested-service.js"), exports);
9
9
  tslib_1.__exportStar(require("./services/mongo-service.js"), exports);
10
10
  tslib_1.__exportStar(require("./services/mongo-singleton-service.js"), exports);
11
+ tslib_1.__exportStar(require("./types.js"), exports);
@@ -44,8 +44,6 @@ class MongoCollectionService extends mongo_entity_service_js_1.MongoEntityServic
44
44
  input._id = input._id == null || input._id === '' ? this._generateId(command) : input._id;
45
45
  return this._executeCommand(command, async () => {
46
46
  const r = await this._create(command);
47
- if (!command.options?.projection)
48
- return r;
49
47
  const findCommand = {
50
48
  ...command,
51
49
  crud: 'read',
@@ -303,7 +301,7 @@ class MongoCollectionService extends mongo_entity_service_js_1.MongoEntityServic
303
301
  * Updates a document in the collection with the specified ID.
304
302
  *
305
303
  * @param {MongoAdapter.AnyId} id - The ID of the document to update.
306
- * @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input data to update the document with.
304
+ * @param {MongoPatchDTO<T>|UpdateFilter<T>} input - The partial input data to update the document with.
307
305
  * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The options for updating the document.
308
306
  * @returns {Promise<number>} - A promise that resolves to the number of documents modified.
309
307
  */
@@ -330,7 +328,7 @@ class MongoCollectionService extends mongo_entity_service_js_1.MongoEntityServic
330
328
  /**
331
329
  * Updates multiple documents in the collection based on the specified input and options.
332
330
  *
333
- * @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input to update the documents with.
331
+ * @param {MongoPatchDTO<T>|UpdateFilter<T>} input - The partial input to update the documents with.
334
332
  * @param {MongoEntityService.UpdateManyOptions<T>} options - The options for updating the documents.
335
333
  * @return {Promise<number>} - A promise that resolves to the number of documents matched and modified.
336
334
  */
@@ -284,12 +284,13 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
284
284
  */
285
285
  async _update(command) {
286
286
  (0, valgen_1.isNotNullish)(command.documentId, { label: 'documentId' });
287
- const { input, inputRaw, options } = command;
287
+ const { input, inputRaw } = command;
288
288
  (0, valgen_1.isNotNullish)(input || inputRaw, { label: 'input' });
289
289
  if (input && inputRaw) {
290
290
  throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
291
291
  }
292
292
  const update = this._prepareUpdate(command);
293
+ const options = command.options;
293
294
  const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
294
295
  mongo_adapter_js_1.MongoAdapter.prepareKeyValues(command.documentId, ['_id']),
295
296
  options?.filter,
@@ -315,12 +316,13 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
315
316
  */
316
317
  async _updateOnly(command) {
317
318
  (0, valgen_1.isNotNullish)(command.documentId, { label: 'documentId' });
318
- const { input, inputRaw, options } = command;
319
+ const { input, inputRaw } = command;
319
320
  (0, valgen_1.isNotNullish)(input || inputRaw, { label: 'input' });
320
321
  if (input && inputRaw) {
321
322
  throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
322
323
  }
323
324
  const update = this._prepareUpdate(command);
325
+ const options = command.options;
324
326
  const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
325
327
  mongo_adapter_js_1.MongoAdapter.prepareKeyValues(command.documentId, ['_id']),
326
328
  options?.filter,
@@ -340,12 +342,13 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
340
342
  */
341
343
  async _updateMany(command) {
342
344
  (0, valgen_1.isNotNullish)(command.input, { label: 'input' });
343
- const { input, inputRaw, options } = command;
345
+ const { input, inputRaw } = command;
344
346
  (0, valgen_1.isNotNullish)(input || inputRaw, { label: 'input' });
345
347
  if (input && inputRaw) {
346
348
  throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
347
349
  }
348
350
  const update = this._prepareUpdate(command);
351
+ const options = command.options;
349
352
  const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter(options?.filter);
350
353
  const db = this.getDatabase();
351
354
  const collection = await this.getCollection(db);
@@ -396,6 +399,9 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
396
399
  const inputCodec = this._getInputCodec('update');
397
400
  const doc = inputCodec(input);
398
401
  delete doc._id;
402
+ if (doc._$push) {
403
+ doc._$push = inputCodec(doc._$push);
404
+ }
399
405
  return this._generatePatch(command, doc);
400
406
  }
401
407
  _generatePatch(command, doc) {
@@ -404,7 +410,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
404
410
  command.options = command.options || {};
405
411
  if (arrayFilters) {
406
412
  command.options.arrayFilters = command.options.arrayFilters || [];
407
- command.options.arrayFilters.push(arrayFilters);
413
+ command.options.arrayFilters.push(...arrayFilters);
408
414
  }
409
415
  return update;
410
416
  }
@@ -606,7 +606,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
606
606
  *
607
607
  * @param {MongoAdapter.AnyId} documentId - The ID of the parent document.
608
608
  * @param {MongoAdapter.AnyId} nestedId - The ID of the document to update.
609
- * @param {PatchDTO<T>} input - The partial input object containing the fields to update.
609
+ * @param {MongoPatchDTO<T>} input - The partial input object containing the fields to update.
610
610
  * @param {MongoNestedService.UpdateOneOptions<T>} [options] - Optional update options.
611
611
  * @returns {Promise<number>} - A promise that resolves to the number of elements updated.
612
612
  */
@@ -651,7 +651,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
651
651
  * Updates multiple array elements in document
652
652
  *
653
653
  * @param {MongoAdapter.AnyId} documentId - The ID of the document to update.
654
- * @param {PatchDTO<T>} input - The updated data for the document(s).
654
+ * @param {MongoPatchDTO<T>} input - The updated data for the document(s).
655
655
  * @param {MongoNestedService.UpdateManyOptions<T>} [options] - Additional options for the update operation.
656
656
  * @returns {Promise<number>} - A promise that resolves to the number of documents updated.
657
657
  */
@@ -248,7 +248,7 @@ class MongoService extends core_1.ServiceBase {
248
248
  let validator = this._outputCodecs[operation];
249
249
  if (validator)
250
250
  return validator;
251
- const options = { projection: '*', partial: 'deep' };
251
+ const options = { projection: '*', partial: 'deep', ignoreHiddenFields: true };
252
252
  const dataType = this.dataType;
253
253
  validator = dataType.generateCodec('decode', options);
254
254
  this._outputCodecs[operation] = validator;
@@ -174,7 +174,7 @@ class MongoSingletonService extends mongo_entity_service_js_1.MongoEntityService
174
174
  /**
175
175
  * Updates a document in the MongoDB collection
176
176
  *
177
- * @param {PatchDTO<T>} input - The partial input to update the document.
177
+ * @param {MongoPatchDTO<T>} input - The partial input to update the document.
178
178
  * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
179
179
  *
180
180
  * @return {Promise<number>} - A promise that resolves to the updated document or undefined if not found.
package/cjs/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -19,11 +19,11 @@ export class MongoPatchGenerator {
19
19
  };
20
20
  }
21
21
  _processComplexType(ctx, dataType, path, input) {
22
- if (input.$add) {
23
- this._processAdd(ctx, dataType, path, input.$add);
22
+ if (input._$push) {
23
+ this._processPush(ctx, dataType, path, input._$push);
24
24
  }
25
- if (input.$remove) {
26
- this._processRemove(ctx, dataType, path, input.$remove);
25
+ if (input._$pull) {
26
+ this._processPull(ctx, dataType, path, input._$pull);
27
27
  }
28
28
  const keys = Object.keys(input);
29
29
  const pathDot = path + (path ? '.' : '');
@@ -42,20 +42,24 @@ export class MongoPatchGenerator {
42
42
  value = input[key];
43
43
  field = dataType.fields.get(key);
44
44
  if (!field) {
45
- if (dataType.additionalFields === true) {
45
+ if (dataType.additionalFields) {
46
46
  if (value === null) {
47
47
  ctx.$unset = ctx.$unset || {};
48
48
  ctx.$unset[pathDot + key] = 1;
49
49
  }
50
50
  else {
51
51
  ctx.$set = ctx.$set || {};
52
+ if (dataType.additionalFields instanceof ComplexType) {
53
+ /** Process nested object */
54
+ this._processComplexType(ctx, dataType.additionalFields, pathDot + key, value);
55
+ continue;
56
+ }
52
57
  ctx.$set[pathDot + key] = value;
53
58
  }
54
59
  }
55
60
  continue;
56
61
  }
57
- if (field.readonly)
58
- continue;
62
+ // if (field.readonly) continue;
59
63
  if (value === null) {
60
64
  ctx.$unset = ctx.$unset || {};
61
65
  ctx.$unset[pathDot + field.name] = 1;
@@ -80,8 +84,8 @@ export class MongoPatchGenerator {
80
84
  /** Remove key field from object */
81
85
  delete v[keyField];
82
86
  /** Add array filter */
83
- ctx.arrayFilters = ctx.arrayFilters || {};
84
- ctx.arrayFilters[`${arrayFilterName}.${keyField}`] = keyValue;
87
+ ctx.arrayFilters = ctx.arrayFilters || [];
88
+ ctx.arrayFilters.push({ [`${arrayFilterName}.${keyField}`]: keyValue });
85
89
  /** Process each object in array */
86
90
  this._processComplexType(ctx, field.type, pathDot + field.name + `.$[${arrayFilterName}]`, v);
87
91
  }
@@ -98,7 +102,7 @@ export class MongoPatchGenerator {
98
102
  ctx.$set[pathDot + field.name] = value;
99
103
  }
100
104
  }
101
- _processAdd(ctx, dataType, path, input) {
105
+ _processPush(ctx, dataType, path, input) {
102
106
  let field;
103
107
  let key;
104
108
  let value;
@@ -117,14 +121,14 @@ export class MongoPatchGenerator {
117
121
  if (Array.isArray(value)) {
118
122
  value.forEach(v => {
119
123
  if (!v[keyField]) {
120
- throw new TypeError(`You must provide a key value of ${field.type.name} for $add operation.`);
124
+ throw new TypeError(`You must provide a key value of ${field.type.name} for $push operation.`);
121
125
  }
122
126
  });
123
127
  ctx.$push[pathDot + key] = { $each: value };
124
128
  }
125
129
  else {
126
130
  if (!value[keyField]) {
127
- throw new TypeError(`You must provide a key value of ${field.type.name} for $add operation.`);
131
+ throw new TypeError(`You must provide a key value of ${field.type.name} for $push operation.`);
128
132
  }
129
133
  ctx.$push[pathDot + key] = value;
130
134
  }
@@ -134,7 +138,7 @@ export class MongoPatchGenerator {
134
138
  ctx.$push[pathDot + key] = Array.isArray(value) ? { $each: value } : value;
135
139
  }
136
140
  }
137
- _processRemove(ctx, dataType, path, input) {
141
+ _processPull(ctx, dataType, path, input) {
138
142
  let field;
139
143
  let key;
140
144
  let value;
package/esm/index.js CHANGED
@@ -5,3 +5,4 @@ export * from './services/mongo-entity-service.js';
5
5
  export * from './services/mongo-nested-service.js';
6
6
  export * from './services/mongo-service.js';
7
7
  export * from './services/mongo-singleton-service.js';
8
+ export * from './types.js';
@@ -41,8 +41,6 @@ export class MongoCollectionService extends MongoEntityService {
41
41
  input._id = input._id == null || input._id === '' ? this._generateId(command) : input._id;
42
42
  return this._executeCommand(command, async () => {
43
43
  const r = await this._create(command);
44
- if (!command.options?.projection)
45
- return r;
46
44
  const findCommand = {
47
45
  ...command,
48
46
  crud: 'read',
@@ -300,7 +298,7 @@ export class MongoCollectionService extends MongoEntityService {
300
298
  * Updates a document in the collection with the specified ID.
301
299
  *
302
300
  * @param {MongoAdapter.AnyId} id - The ID of the document to update.
303
- * @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input data to update the document with.
301
+ * @param {MongoPatchDTO<T>|UpdateFilter<T>} input - The partial input data to update the document with.
304
302
  * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The options for updating the document.
305
303
  * @returns {Promise<number>} - A promise that resolves to the number of documents modified.
306
304
  */
@@ -327,7 +325,7 @@ export class MongoCollectionService extends MongoEntityService {
327
325
  /**
328
326
  * Updates multiple documents in the collection based on the specified input and options.
329
327
  *
330
- * @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input to update the documents with.
328
+ * @param {MongoPatchDTO<T>|UpdateFilter<T>} input - The partial input to update the documents with.
331
329
  * @param {MongoEntityService.UpdateManyOptions<T>} options - The options for updating the documents.
332
330
  * @return {Promise<number>} - A promise that resolves to the number of documents matched and modified.
333
331
  */
@@ -281,12 +281,13 @@ export class MongoEntityService extends MongoService {
281
281
  */
282
282
  async _update(command) {
283
283
  isNotNullish(command.documentId, { label: 'documentId' });
284
- const { input, inputRaw, options } = command;
284
+ const { input, inputRaw } = command;
285
285
  isNotNullish(input || inputRaw, { label: 'input' });
286
286
  if (input && inputRaw) {
287
287
  throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
288
288
  }
289
289
  const update = this._prepareUpdate(command);
290
+ const options = command.options;
290
291
  const filter = MongoAdapter.prepareFilter([
291
292
  MongoAdapter.prepareKeyValues(command.documentId, ['_id']),
292
293
  options?.filter,
@@ -312,12 +313,13 @@ export class MongoEntityService extends MongoService {
312
313
  */
313
314
  async _updateOnly(command) {
314
315
  isNotNullish(command.documentId, { label: 'documentId' });
315
- const { input, inputRaw, options } = command;
316
+ const { input, inputRaw } = command;
316
317
  isNotNullish(input || inputRaw, { label: 'input' });
317
318
  if (input && inputRaw) {
318
319
  throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
319
320
  }
320
321
  const update = this._prepareUpdate(command);
322
+ const options = command.options;
321
323
  const filter = MongoAdapter.prepareFilter([
322
324
  MongoAdapter.prepareKeyValues(command.documentId, ['_id']),
323
325
  options?.filter,
@@ -337,12 +339,13 @@ export class MongoEntityService extends MongoService {
337
339
  */
338
340
  async _updateMany(command) {
339
341
  isNotNullish(command.input, { label: 'input' });
340
- const { input, inputRaw, options } = command;
342
+ const { input, inputRaw } = command;
341
343
  isNotNullish(input || inputRaw, { label: 'input' });
342
344
  if (input && inputRaw) {
343
345
  throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
344
346
  }
345
347
  const update = this._prepareUpdate(command);
348
+ const options = command.options;
346
349
  const filter = MongoAdapter.prepareFilter(options?.filter);
347
350
  const db = this.getDatabase();
348
351
  const collection = await this.getCollection(db);
@@ -393,6 +396,9 @@ export class MongoEntityService extends MongoService {
393
396
  const inputCodec = this._getInputCodec('update');
394
397
  const doc = inputCodec(input);
395
398
  delete doc._id;
399
+ if (doc._$push) {
400
+ doc._$push = inputCodec(doc._$push);
401
+ }
396
402
  return this._generatePatch(command, doc);
397
403
  }
398
404
  _generatePatch(command, doc) {
@@ -401,7 +407,7 @@ export class MongoEntityService extends MongoService {
401
407
  command.options = command.options || {};
402
408
  if (arrayFilters) {
403
409
  command.options.arrayFilters = command.options.arrayFilters || [];
404
- command.options.arrayFilters.push(arrayFilters);
410
+ command.options.arrayFilters.push(...arrayFilters);
405
411
  }
406
412
  return update;
407
413
  }
@@ -603,7 +603,7 @@ export class MongoNestedService extends MongoService {
603
603
  *
604
604
  * @param {MongoAdapter.AnyId} documentId - The ID of the parent document.
605
605
  * @param {MongoAdapter.AnyId} nestedId - The ID of the document to update.
606
- * @param {PatchDTO<T>} input - The partial input object containing the fields to update.
606
+ * @param {MongoPatchDTO<T>} input - The partial input object containing the fields to update.
607
607
  * @param {MongoNestedService.UpdateOneOptions<T>} [options] - Optional update options.
608
608
  * @returns {Promise<number>} - A promise that resolves to the number of elements updated.
609
609
  */
@@ -648,7 +648,7 @@ export class MongoNestedService extends MongoService {
648
648
  * Updates multiple array elements in document
649
649
  *
650
650
  * @param {MongoAdapter.AnyId} documentId - The ID of the document to update.
651
- * @param {PatchDTO<T>} input - The updated data for the document(s).
651
+ * @param {MongoPatchDTO<T>} input - The updated data for the document(s).
652
652
  * @param {MongoNestedService.UpdateManyOptions<T>} [options] - Additional options for the update operation.
653
653
  * @returns {Promise<number>} - A promise that resolves to the number of documents updated.
654
654
  */
@@ -245,7 +245,7 @@ export class MongoService extends ServiceBase {
245
245
  let validator = this._outputCodecs[operation];
246
246
  if (validator)
247
247
  return validator;
248
- const options = { projection: '*', partial: 'deep' };
248
+ const options = { projection: '*', partial: 'deep', ignoreHiddenFields: true };
249
249
  const dataType = this.dataType;
250
250
  validator = dataType.generateCodec('decode', options);
251
251
  this._outputCodecs[operation] = validator;
@@ -171,7 +171,7 @@ export class MongoSingletonService extends MongoEntityService {
171
171
  /**
172
172
  * Updates a document in the MongoDB collection
173
173
  *
174
- * @param {PatchDTO<T>} input - The partial input to update the document.
174
+ * @param {MongoPatchDTO<T>} input - The partial input to update the document.
175
175
  * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
176
176
  *
177
177
  * @return {Promise<number>} - A promise that resolves to the updated document or undefined if not found.
package/esm/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/mongodb",
3
- "version": "1.3.1",
3
+ "version": "1.4.0",
4
4
  "description": "Opra MongoDB adapter package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -10,9 +10,9 @@
10
10
  "valgen": "^5.12.0"
11
11
  },
12
12
  "peerDependencies": {
13
- "@opra/common": "^1.3.1",
14
- "@opra/core": "^1.3.1",
15
- "@opra/http": "^1.3.1",
13
+ "@opra/common": "^1.4.0",
14
+ "@opra/core": "^1.4.0",
15
+ "@opra/http": "^1.4.0",
16
16
  "mongodb": ">= 6.0.0"
17
17
  },
18
18
  "type": "module",
@@ -6,16 +6,16 @@ interface Context {
6
6
  $unset?: Record<string, any>;
7
7
  $push?: Record<string, any>;
8
8
  $pull?: Record<string, any>;
9
- arrayFilters?: Record<string, any>;
9
+ arrayFilters?: Record<string, any>[];
10
10
  }
11
11
  export declare class MongoPatchGenerator {
12
12
  generatePatch<T extends object>(dataType: ComplexType, doc: PatchDTO<T>, options?: MongoPatchGenerator.Options): {
13
13
  update: UpdateFilter<T>;
14
- arrayFilters?: Record<string, any>;
14
+ arrayFilters?: Record<string, any>[];
15
15
  };
16
16
  protected _processComplexType(ctx: Context, dataType: ComplexType, path: string, input: any): void;
17
- protected _processAdd(ctx: Context, dataType: ComplexType, path: string, input: any): void;
18
- protected _processRemove(ctx: Context, dataType: ComplexType, path: string, input: any): void;
17
+ protected _processPush(ctx: Context, dataType: ComplexType, path: string, input: any): void;
18
+ protected _processPull(ctx: Context, dataType: ComplexType, path: string, input: any): void;
19
19
  }
20
20
  export declare namespace MongoPatchGenerator {
21
21
  interface Options {
package/types/index.d.cts CHANGED
@@ -5,3 +5,4 @@ export * from './services/mongo-entity-service.js';
5
5
  export * from './services/mongo-nested-service.js';
6
6
  export * from './services/mongo-service.js';
7
7
  export * from './services/mongo-singleton-service.js';
8
+ export * from './types.js';
package/types/index.d.ts CHANGED
@@ -5,3 +5,4 @@ export * from './services/mongo-entity-service.js';
5
5
  export * from './services/mongo-nested-service.js';
6
6
  export * from './services/mongo-service.js';
7
7
  export * from './services/mongo-singleton-service.js';
8
+ export * from './types.js';
@@ -1,6 +1,7 @@
1
1
  import mongodb, { type UpdateFilter } from 'mongodb';
2
- import type { PartialDTO, PatchDTO, RequiredSome, Type } from 'ts-gems';
2
+ import type { PartialDTO, RequiredSome, Type } from 'ts-gems';
3
3
  import { MongoAdapter } from '../adapter/mongo-adapter.js';
4
+ import type { MongoPatchDTO } from '../types.js';
4
5
  import { MongoEntityService } from './mongo-entity-service.js';
5
6
  /**
6
7
  *
@@ -168,28 +169,28 @@ export declare class MongoCollectionService<T extends mongodb.Document> extends
168
169
  * Updates a document with the given id in the collection.
169
170
  *
170
171
  * @param {MongoAdapter.AnyId} id - The id of the document to update.
171
- * @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input object containing the fields to update.
172
+ * @param {MongoPatchDTO<T>|UpdateFilter<T>} input - The partial input object containing the fields to update.
172
173
  * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The options for the update operation.
173
174
  * @returns {Promise<PartialDTO<T> | undefined>} A promise that resolves to the updated document or
174
175
  * undefined if the document was not found.
175
176
  */
176
- update(id: MongoAdapter.AnyId, input: PatchDTO<T> | UpdateFilter<T>, options: RequiredSome<MongoEntityService.UpdateOneOptions<T>, 'projection'>): Promise<PartialDTO<T> | undefined>;
177
- update(id: MongoAdapter.AnyId, input: PatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<T | undefined>;
177
+ update(id: MongoAdapter.AnyId, input: MongoPatchDTO<T> | UpdateFilter<T>, options: RequiredSome<MongoEntityService.UpdateOneOptions<T>, 'projection'>): Promise<PartialDTO<T> | undefined>;
178
+ update(id: MongoAdapter.AnyId, input: MongoPatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<T | undefined>;
178
179
  /**
179
180
  * Updates a document in the collection with the specified ID.
180
181
  *
181
182
  * @param {MongoAdapter.AnyId} id - The ID of the document to update.
182
- * @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input data to update the document with.
183
+ * @param {MongoPatchDTO<T>|UpdateFilter<T>} input - The partial input data to update the document with.
183
184
  * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The options for updating the document.
184
185
  * @returns {Promise<number>} - A promise that resolves to the number of documents modified.
185
186
  */
186
- updateOnly(id: MongoAdapter.AnyId, input: PatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<number>;
187
+ updateOnly(id: MongoAdapter.AnyId, input: MongoPatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<number>;
187
188
  /**
188
189
  * Updates multiple documents in the collection based on the specified input and options.
189
190
  *
190
- * @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input to update the documents with.
191
+ * @param {MongoPatchDTO<T>|UpdateFilter<T>} input - The partial input to update the documents with.
191
192
  * @param {MongoEntityService.UpdateManyOptions<T>} options - The options for updating the documents.
192
193
  * @return {Promise<number>} - A promise that resolves to the number of documents matched and modified.
193
194
  */
194
- updateMany(input: PatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateManyOptions<T>): Promise<number>;
195
+ updateMany(input: MongoPatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateManyOptions<T>): Promise<number>;
195
196
  }
@@ -1,5 +1,6 @@
1
1
  import mongodb, { type UpdateFilter } from 'mongodb';
2
- import type { PartialDTO, PatchDTO, StrictOmit, Type } from 'ts-gems';
2
+ import type { PartialDTO, StrictOmit, Type } from 'ts-gems';
3
+ import type { MongoPatchDTO } from '../types.js';
3
4
  import { MongoService } from './mongo-service.js';
4
5
  /**
5
6
  *
@@ -70,13 +71,13 @@ export declare namespace MongoEntityService {
70
71
  }
71
72
  interface UpdateOneCommand<T> extends StrictOmit<CommandInfo, 'nestedId'> {
72
73
  crud: 'update';
73
- input?: PatchDTO<T>;
74
+ input?: MongoPatchDTO<T>;
74
75
  inputRaw?: mongodb.UpdateFilter<T>;
75
76
  options?: UpdateOneOptions<T>;
76
77
  }
77
78
  interface UpdateManyCommand<T> extends StrictOmit<CommandInfo, 'nestedId'> {
78
79
  crud: 'update';
79
- input?: PatchDTO<T>;
80
+ input?: MongoPatchDTO<T>;
80
81
  inputRaw?: mongodb.UpdateFilter<T>;
81
82
  options?: UpdateManyOptions<T>;
82
83
  }
@@ -1,7 +1,8 @@
1
1
  import { ComplexType } from '@opra/common';
2
2
  import mongodb from 'mongodb';
3
- import type { DTO, PartialDTO, PatchDTO, RequiredSome, StrictOmit, Type } from 'ts-gems';
3
+ import type { DTO, PartialDTO, RequiredSome, StrictOmit, Type } from 'ts-gems';
4
4
  import { MongoAdapter } from '../adapter/mongo-adapter.js';
5
+ import type { MongoPatchDTO } from '../types.js';
5
6
  import type { MongoEntityService } from './mongo-entity-service.js';
6
7
  import { MongoService } from './mongo-service.js';
7
8
  /**
@@ -72,12 +73,12 @@ export declare namespace MongoNestedService {
72
73
  }
73
74
  interface UpdateOneCommand<T> extends RequiredSome<CommandInfo, 'documentId'> {
74
75
  crud: 'update';
75
- input: PatchDTO<T> | mongodb.UpdateFilter<T>;
76
+ input: MongoPatchDTO<T> | mongodb.UpdateFilter<T>;
76
77
  options?: MongoNestedService.UpdateOneOptions<T>;
77
78
  }
78
79
  interface UpdateManyCommand<T> extends RequiredSome<CommandInfo, 'documentId'> {
79
80
  crud: 'update';
80
- input: PatchDTO<T> | mongodb.UpdateFilter<T>;
81
+ input: MongoPatchDTO<T> | mongodb.UpdateFilter<T>;
81
82
  options?: MongoNestedService.UpdateManyOptions<T>;
82
83
  }
83
84
  }
@@ -271,33 +272,33 @@ export declare class MongoNestedService<T extends mongodb.Document> extends Mong
271
272
  *
272
273
  * @param {AnyId} documentId - The ID of the document to update.
273
274
  * @param {AnyId} nestedId - The ID of the item to update within the document.
274
- * @param {PatchDTO<T>} input - The new data to update the item with.
275
+ * @param {MongoPatchDTO<T>} input - The new data to update the item with.
275
276
  * @param {MongoNestedService.UpdateOneOptions<T>} [options] - Additional update options.
276
277
  * @returns {Promise<PartialDTO<T> | undefined>} The updated item or undefined if it does not exist.
277
278
  * @throws {Error} If an error occurs while updating the item.
278
279
  */
279
- update(documentId: MongoAdapter.AnyId, nestedId: MongoAdapter.AnyId, input: PatchDTO<T>, options: RequiredSome<MongoNestedService.UpdateOneOptions<T>, 'projection'>): Promise<PartialDTO<T> | undefined>;
280
- update(documentId: MongoAdapter.AnyId, nestedId: MongoAdapter.AnyId, input: PatchDTO<T>, options?: MongoNestedService.UpdateOneOptions<T>): Promise<T | undefined>;
280
+ update(documentId: MongoAdapter.AnyId, nestedId: MongoAdapter.AnyId, input: MongoPatchDTO<T>, options: RequiredSome<MongoNestedService.UpdateOneOptions<T>, 'projection'>): Promise<PartialDTO<T> | undefined>;
281
+ update(documentId: MongoAdapter.AnyId, nestedId: MongoAdapter.AnyId, input: MongoPatchDTO<T>, options?: MongoNestedService.UpdateOneOptions<T>): Promise<T | undefined>;
281
282
  /**
282
283
  * Update an array element with new data. Returns 1 if document updated 0 otherwise.
283
284
  *
284
285
  * @param {MongoAdapter.AnyId} documentId - The ID of the parent document.
285
286
  * @param {MongoAdapter.AnyId} nestedId - The ID of the document to update.
286
- * @param {PatchDTO<T>} input - The partial input object containing the fields to update.
287
+ * @param {MongoPatchDTO<T>} input - The partial input object containing the fields to update.
287
288
  * @param {MongoNestedService.UpdateOneOptions<T>} [options] - Optional update options.
288
289
  * @returns {Promise<number>} - A promise that resolves to the number of elements updated.
289
290
  */
290
- updateOnly(documentId: MongoAdapter.AnyId, nestedId: MongoAdapter.AnyId, input: PatchDTO<T>, options?: MongoNestedService.UpdateOneOptions<T>): Promise<number>;
291
+ updateOnly(documentId: MongoAdapter.AnyId, nestedId: MongoAdapter.AnyId, input: MongoPatchDTO<T>, options?: MongoNestedService.UpdateOneOptions<T>): Promise<number>;
291
292
  protected _updateOnly(command: MongoNestedService.UpdateOneCommand<T>): Promise<number>;
292
293
  /**
293
294
  * Updates multiple array elements in document
294
295
  *
295
296
  * @param {MongoAdapter.AnyId} documentId - The ID of the document to update.
296
- * @param {PatchDTO<T>} input - The updated data for the document(s).
297
+ * @param {MongoPatchDTO<T>} input - The updated data for the document(s).
297
298
  * @param {MongoNestedService.UpdateManyOptions<T>} [options] - Additional options for the update operation.
298
299
  * @returns {Promise<number>} - A promise that resolves to the number of documents updated.
299
300
  */
300
- updateMany(documentId: MongoAdapter.AnyId, input: PatchDTO<T>, options?: MongoNestedService.UpdateManyOptions<T>): Promise<number>;
301
+ updateMany(documentId: MongoAdapter.AnyId, input: MongoPatchDTO<T>, options?: MongoNestedService.UpdateManyOptions<T>): Promise<number>;
301
302
  protected _updateMany(command: MongoNestedService.UpdateManyCommand<T>): Promise<number>;
302
303
  /**
303
304
  * Retrieves the common filter used for querying array elements.
@@ -1,6 +1,7 @@
1
1
  import mongodb, { type UpdateFilter } from 'mongodb';
2
- import type { PartialDTO, PatchDTO, RequiredSome, Type } from 'ts-gems';
2
+ import type { PartialDTO, RequiredSome, Type } from 'ts-gems';
3
3
  import { MongoAdapter } from '../adapter/mongo-adapter.js';
4
+ import type { MongoPatchDTO } from '../types.js';
4
5
  import { MongoEntityService } from './mongo-entity-service.js';
5
6
  /**
6
7
  *
@@ -98,20 +99,20 @@ export declare class MongoSingletonService<T extends mongodb.Document> extends M
98
99
  /**
99
100
  * Updates a document in the MongoDB collection
100
101
  *
101
- * @param {PatchDTO<T>} input - The partial input to update the document.
102
+ * @param {MongoPatchDTO<T>} input - The partial input to update the document.
102
103
  * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
103
104
  *
104
105
  * @return {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the updated document or undefined if not found.
105
106
  */
106
- update(input: PatchDTO<T> | UpdateFilter<T>, options: RequiredSome<MongoEntityService.UpdateOneOptions<T>, 'projection'>): Promise<PartialDTO<T> | undefined>;
107
- update(input: PatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<T | undefined>;
107
+ update(input: MongoPatchDTO<T> | UpdateFilter<T>, options: RequiredSome<MongoEntityService.UpdateOneOptions<T>, 'projection'>): Promise<PartialDTO<T> | undefined>;
108
+ update(input: MongoPatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<T | undefined>;
108
109
  /**
109
110
  * Updates a document in the MongoDB collection
110
111
  *
111
- * @param {PatchDTO<T>} input - The partial input to update the document.
112
+ * @param {MongoPatchDTO<T>} input - The partial input to update the document.
112
113
  * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
113
114
  *
114
115
  * @return {Promise<number>} - A promise that resolves to the updated document or undefined if not found.
115
116
  */
116
- updateOnly(input: PatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<number>;
117
+ updateOnly(input: MongoPatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<number>;
117
118
  }
@@ -0,0 +1,23 @@
1
+ import type { DTO, IfNoDeepValue } from 'ts-gems';
2
+ export type MongoPatchDTO<T> = _MongoPatchDTO<DTO<T>> & PatchOperators<T>;
3
+ /**
4
+ * Returns given type as a Data Transfer Object (DTO) interface, Removes symbol keys and function properties.
5
+ * @template T - The type of the data being transferred.
6
+ */
7
+ type _MongoPatchDTO<T> = {
8
+ [K in keyof T]?: Exclude<T[K], undefined> extends (infer U)[] ? _MongoPatchDTO<U>[] | null : IfNoDeepValue<NonNullable<T[K]>> extends true ? T[K] | null : // Deep process objects
9
+ (_MongoPatchDTO<NonNullable<T[K]>> & PatchOperators<T>) | null;
10
+ };
11
+ /**
12
+ * Pick all array properties in T
13
+ */
14
+ type PickArrays<T> = {
15
+ [K in keyof T as NonNullable<T[K]> extends any[] ? K : never]: T[K];
16
+ };
17
+ type PatchOperators<T> = {
18
+ _$push?: PickArrays<Partial<T>>;
19
+ _$pull?: {
20
+ [K in keyof PickArrays<T>]?: (string | number | boolean)[];
21
+ };
22
+ };
23
+ export {};