@opra/mongodb 1.3.0 → 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.
- package/cjs/adapter/mongo-patch-generator.js +53 -8
- package/cjs/index.js +1 -0
- package/cjs/services/mongo-collection-service.js +2 -4
- package/cjs/services/mongo-entity-service.js +10 -4
- package/cjs/services/mongo-nested-service.js +2 -2
- package/cjs/services/mongo-service.js +1 -1
- package/cjs/services/mongo-singleton-service.js +1 -1
- package/cjs/types.js +2 -0
- package/esm/adapter/mongo-patch-generator.js +53 -8
- package/esm/index.js +1 -0
- package/esm/services/mongo-collection-service.js +2 -4
- package/esm/services/mongo-entity-service.js +10 -4
- package/esm/services/mongo-nested-service.js +2 -2
- package/esm/services/mongo-service.js +1 -1
- package/esm/services/mongo-singleton-service.js +1 -1
- package/esm/types.js +1 -0
- package/package.json +4 -4
- package/types/adapter/mongo-patch-generator.d.ts +5 -3
- package/types/index.d.cts +1 -0
- package/types/index.d.ts +1 -0
- package/types/services/mongo-collection-service.d.ts +9 -8
- package/types/services/mongo-entity-service.d.ts +4 -3
- package/types/services/mongo-nested-service.d.ts +11 -10
- package/types/services/mongo-singleton-service.d.ts +7 -6
- package/types/types.d.ts +23 -0
|
@@ -14,14 +14,19 @@ class MongoPatchGenerator {
|
|
|
14
14
|
update.$unset = ctx.$unset;
|
|
15
15
|
if (ctx.$set)
|
|
16
16
|
update.$set = ctx.$set;
|
|
17
|
+
if (ctx.$push)
|
|
18
|
+
update.$push = ctx.$push;
|
|
17
19
|
return {
|
|
18
20
|
update,
|
|
19
21
|
arrayFilters: ctx.arrayFilters,
|
|
20
22
|
};
|
|
21
23
|
}
|
|
22
24
|
_processComplexType(ctx, dataType, path, input) {
|
|
23
|
-
if (input
|
|
24
|
-
this.
|
|
25
|
+
if (input._$push) {
|
|
26
|
+
this._processPush(ctx, dataType, path, input._$push);
|
|
27
|
+
}
|
|
28
|
+
if (input._$pull) {
|
|
29
|
+
this._processPull(ctx, dataType, path, input._$pull);
|
|
25
30
|
}
|
|
26
31
|
const keys = Object.keys(input);
|
|
27
32
|
const pathDot = path + (path ? '.' : '');
|
|
@@ -40,20 +45,24 @@ class MongoPatchGenerator {
|
|
|
40
45
|
value = input[key];
|
|
41
46
|
field = dataType.fields.get(key);
|
|
42
47
|
if (!field) {
|
|
43
|
-
if (dataType.additionalFields
|
|
48
|
+
if (dataType.additionalFields) {
|
|
44
49
|
if (value === null) {
|
|
45
50
|
ctx.$unset = ctx.$unset || {};
|
|
46
51
|
ctx.$unset[pathDot + key] = 1;
|
|
47
52
|
}
|
|
48
53
|
else {
|
|
49
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
|
+
}
|
|
50
60
|
ctx.$set[pathDot + key] = value;
|
|
51
61
|
}
|
|
52
62
|
}
|
|
53
63
|
continue;
|
|
54
64
|
}
|
|
55
|
-
if (field.readonly)
|
|
56
|
-
continue;
|
|
65
|
+
// if (field.readonly) continue;
|
|
57
66
|
if (value === null) {
|
|
58
67
|
ctx.$unset = ctx.$unset || {};
|
|
59
68
|
ctx.$unset[pathDot + field.name] = 1;
|
|
@@ -78,8 +87,8 @@ class MongoPatchGenerator {
|
|
|
78
87
|
/** Remove key field from object */
|
|
79
88
|
delete v[keyField];
|
|
80
89
|
/** Add array filter */
|
|
81
|
-
ctx.arrayFilters = ctx.arrayFilters ||
|
|
82
|
-
ctx.arrayFilters[`${arrayFilterName}.${keyField}`]
|
|
90
|
+
ctx.arrayFilters = ctx.arrayFilters || [];
|
|
91
|
+
ctx.arrayFilters.push({ [`${arrayFilterName}.${keyField}`]: keyValue });
|
|
83
92
|
/** Process each object in array */
|
|
84
93
|
this._processComplexType(ctx, field.type, pathDot + field.name + `.$[${arrayFilterName}]`, v);
|
|
85
94
|
}
|
|
@@ -96,7 +105,43 @@ class MongoPatchGenerator {
|
|
|
96
105
|
ctx.$set[pathDot + field.name] = value;
|
|
97
106
|
}
|
|
98
107
|
}
|
|
99
|
-
|
|
108
|
+
_processPush(ctx, dataType, path, input) {
|
|
109
|
+
let field;
|
|
110
|
+
let key;
|
|
111
|
+
let value;
|
|
112
|
+
const pathDot = path + (path ? '.' : '');
|
|
113
|
+
const keys = Object.keys(input);
|
|
114
|
+
let keyField;
|
|
115
|
+
for (key of keys) {
|
|
116
|
+
value = input[key];
|
|
117
|
+
field = dataType.fields.get(key);
|
|
118
|
+
if (!(field && field.isArray))
|
|
119
|
+
continue;
|
|
120
|
+
ctx.$push = ctx.$push || {};
|
|
121
|
+
if (field.type instanceof common_1.ComplexType) {
|
|
122
|
+
keyField = field.keyField || field.type.keyField;
|
|
123
|
+
if (keyField) {
|
|
124
|
+
if (Array.isArray(value)) {
|
|
125
|
+
value.forEach(v => {
|
|
126
|
+
if (!v[keyField]) {
|
|
127
|
+
throw new TypeError(`You must provide a key value of ${field.type.name} for $push operation.`);
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
ctx.$push[pathDot + key] = { $each: value };
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
if (!value[keyField]) {
|
|
134
|
+
throw new TypeError(`You must provide a key value of ${field.type.name} for $push operation.`);
|
|
135
|
+
}
|
|
136
|
+
ctx.$push[pathDot + key] = value;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
ctx.$push[pathDot + key] = Array.isArray(value) ? { $each: value } : value;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
_processPull(ctx, dataType, path, input) {
|
|
100
145
|
let field;
|
|
101
146
|
let key;
|
|
102
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 {
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
@@ -11,14 +11,19 @@ export class MongoPatchGenerator {
|
|
|
11
11
|
update.$unset = ctx.$unset;
|
|
12
12
|
if (ctx.$set)
|
|
13
13
|
update.$set = ctx.$set;
|
|
14
|
+
if (ctx.$push)
|
|
15
|
+
update.$push = ctx.$push;
|
|
14
16
|
return {
|
|
15
17
|
update,
|
|
16
18
|
arrayFilters: ctx.arrayFilters,
|
|
17
19
|
};
|
|
18
20
|
}
|
|
19
21
|
_processComplexType(ctx, dataType, path, input) {
|
|
20
|
-
if (input
|
|
21
|
-
this.
|
|
22
|
+
if (input._$push) {
|
|
23
|
+
this._processPush(ctx, dataType, path, input._$push);
|
|
24
|
+
}
|
|
25
|
+
if (input._$pull) {
|
|
26
|
+
this._processPull(ctx, dataType, path, input._$pull);
|
|
22
27
|
}
|
|
23
28
|
const keys = Object.keys(input);
|
|
24
29
|
const pathDot = path + (path ? '.' : '');
|
|
@@ -37,20 +42,24 @@ export class MongoPatchGenerator {
|
|
|
37
42
|
value = input[key];
|
|
38
43
|
field = dataType.fields.get(key);
|
|
39
44
|
if (!field) {
|
|
40
|
-
if (dataType.additionalFields
|
|
45
|
+
if (dataType.additionalFields) {
|
|
41
46
|
if (value === null) {
|
|
42
47
|
ctx.$unset = ctx.$unset || {};
|
|
43
48
|
ctx.$unset[pathDot + key] = 1;
|
|
44
49
|
}
|
|
45
50
|
else {
|
|
46
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
|
+
}
|
|
47
57
|
ctx.$set[pathDot + key] = value;
|
|
48
58
|
}
|
|
49
59
|
}
|
|
50
60
|
continue;
|
|
51
61
|
}
|
|
52
|
-
if (field.readonly)
|
|
53
|
-
continue;
|
|
62
|
+
// if (field.readonly) continue;
|
|
54
63
|
if (value === null) {
|
|
55
64
|
ctx.$unset = ctx.$unset || {};
|
|
56
65
|
ctx.$unset[pathDot + field.name] = 1;
|
|
@@ -75,8 +84,8 @@ export class MongoPatchGenerator {
|
|
|
75
84
|
/** Remove key field from object */
|
|
76
85
|
delete v[keyField];
|
|
77
86
|
/** Add array filter */
|
|
78
|
-
ctx.arrayFilters = ctx.arrayFilters ||
|
|
79
|
-
ctx.arrayFilters[`${arrayFilterName}.${keyField}`]
|
|
87
|
+
ctx.arrayFilters = ctx.arrayFilters || [];
|
|
88
|
+
ctx.arrayFilters.push({ [`${arrayFilterName}.${keyField}`]: keyValue });
|
|
80
89
|
/** Process each object in array */
|
|
81
90
|
this._processComplexType(ctx, field.type, pathDot + field.name + `.$[${arrayFilterName}]`, v);
|
|
82
91
|
}
|
|
@@ -93,7 +102,43 @@ export class MongoPatchGenerator {
|
|
|
93
102
|
ctx.$set[pathDot + field.name] = value;
|
|
94
103
|
}
|
|
95
104
|
}
|
|
96
|
-
|
|
105
|
+
_processPush(ctx, dataType, path, input) {
|
|
106
|
+
let field;
|
|
107
|
+
let key;
|
|
108
|
+
let value;
|
|
109
|
+
const pathDot = path + (path ? '.' : '');
|
|
110
|
+
const keys = Object.keys(input);
|
|
111
|
+
let keyField;
|
|
112
|
+
for (key of keys) {
|
|
113
|
+
value = input[key];
|
|
114
|
+
field = dataType.fields.get(key);
|
|
115
|
+
if (!(field && field.isArray))
|
|
116
|
+
continue;
|
|
117
|
+
ctx.$push = ctx.$push || {};
|
|
118
|
+
if (field.type instanceof ComplexType) {
|
|
119
|
+
keyField = field.keyField || field.type.keyField;
|
|
120
|
+
if (keyField) {
|
|
121
|
+
if (Array.isArray(value)) {
|
|
122
|
+
value.forEach(v => {
|
|
123
|
+
if (!v[keyField]) {
|
|
124
|
+
throw new TypeError(`You must provide a key value of ${field.type.name} for $push operation.`);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
ctx.$push[pathDot + key] = { $each: value };
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
if (!value[keyField]) {
|
|
131
|
+
throw new TypeError(`You must provide a key value of ${field.type.name} for $push operation.`);
|
|
132
|
+
}
|
|
133
|
+
ctx.$push[pathDot + key] = value;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
ctx.$push[pathDot + key] = Array.isArray(value) ? { $each: value } : value;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
_processPull(ctx, dataType, path, input) {
|
|
97
142
|
let field;
|
|
98
143
|
let key;
|
|
99
144
|
let value;
|
package/esm/index.js
CHANGED
|
@@ -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 {
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
+
"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.
|
|
14
|
-
"@opra/core": "^1.
|
|
15
|
-
"@opra/http": "^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",
|
|
@@ -4,16 +4,18 @@ import type { PatchDTO } from 'ts-gems';
|
|
|
4
4
|
interface Context {
|
|
5
5
|
$set?: Record<string, any>;
|
|
6
6
|
$unset?: Record<string, any>;
|
|
7
|
+
$push?: Record<string, any>;
|
|
7
8
|
$pull?: Record<string, any>;
|
|
8
|
-
arrayFilters?: Record<string, any
|
|
9
|
+
arrayFilters?: Record<string, any>[];
|
|
9
10
|
}
|
|
10
11
|
export declare class MongoPatchGenerator {
|
|
11
12
|
generatePatch<T extends object>(dataType: ComplexType, doc: PatchDTO<T>, options?: MongoPatchGenerator.Options): {
|
|
12
13
|
update: UpdateFilter<T>;
|
|
13
|
-
arrayFilters?: Record<string, any
|
|
14
|
+
arrayFilters?: Record<string, any>[];
|
|
14
15
|
};
|
|
15
16
|
protected _processComplexType(ctx: Context, dataType: ComplexType, path: string, input: any): void;
|
|
16
|
-
protected
|
|
17
|
+
protected _processPush(ctx: Context, dataType: ComplexType, path: string, input: any): void;
|
|
18
|
+
protected _processPull(ctx: Context, dataType: ComplexType, path: string, input: any): void;
|
|
17
19
|
}
|
|
18
20
|
export declare namespace MongoPatchGenerator {
|
|
19
21
|
interface Options {
|
package/types/index.d.cts
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import mongodb, { type UpdateFilter } from 'mongodb';
|
|
2
|
-
import type { PartialDTO,
|
|
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 {
|
|
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:
|
|
177
|
-
update(id: MongoAdapter.AnyId, input:
|
|
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 {
|
|
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:
|
|
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 {
|
|
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:
|
|
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,
|
|
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?:
|
|
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?:
|
|
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,
|
|
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:
|
|
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:
|
|
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 {
|
|
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:
|
|
280
|
-
update(documentId: MongoAdapter.AnyId, nestedId: MongoAdapter.AnyId, input:
|
|
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 {
|
|
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:
|
|
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 {
|
|
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:
|
|
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,
|
|
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 {
|
|
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:
|
|
107
|
-
update(input:
|
|
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 {
|
|
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:
|
|
117
|
+
updateOnly(input: MongoPatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<number>;
|
|
117
118
|
}
|
package/types/types.d.ts
ADDED
|
@@ -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 {};
|