@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.
- package/cjs/adapter-utils/prepare-filter.js +3 -1
- package/cjs/adapter-utils/prepare-key-values.js +5 -4
- package/cjs/adapter-utils/prepare-patch.js +3 -2
- package/cjs/adapter-utils/prepare-projection.js +2 -3
- package/cjs/adapter-utils/prepare-sort.js +1 -1
- package/cjs/index.js +1 -1
- package/cjs/mongo-adapter.js +9 -4
- package/cjs/mongo-collection-service.js +111 -94
- package/cjs/mongo-entity-service.js +116 -93
- package/cjs/mongo-nested-service.js +262 -144
- package/cjs/mongo-service.js +62 -50
- package/cjs/mongo-singleton-service.js +62 -42
- package/esm/adapter-utils/prepare-filter.js +2 -0
- package/esm/adapter-utils/prepare-key-values.js +4 -3
- package/esm/adapter-utils/prepare-patch.js +2 -1
- package/esm/index.js +1 -1
- package/esm/mongo-adapter.js +9 -4
- package/esm/mongo-collection-service.js +111 -94
- package/esm/mongo-entity-service.js +116 -93
- package/esm/mongo-nested-service.js +262 -144
- package/esm/mongo-service.js +62 -50
- package/esm/mongo-singleton-service.js +62 -42
- package/package.json +12 -6
- package/types/adapter-utils/prepare-projection.d.ts +1 -1
- package/types/index.d.ts +1 -1
- package/types/mongo-adapter.d.ts +1 -1
- package/types/mongo-collection-service.d.ts +32 -62
- package/types/mongo-entity-service.d.ts +73 -47
- package/types/mongo-nested-service.d.ts +63 -28
- package/types/mongo-service.d.ts +44 -41
- package/types/mongo-singleton-service.d.ts +19 -29
|
@@ -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
|
|
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
|
|
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.
|
|
76
|
+
return this._executeCommand(command, () => this._create(command));
|
|
67
77
|
}
|
|
68
|
-
async _create(
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
doc
|
|
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
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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
|
|
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.
|
|
106
|
-
const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
107
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(
|
|
108
|
-
|
|
109
|
-
|
|
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(
|
|
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
|
|
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.
|
|
153
|
-
const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
154
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(
|
|
155
|
-
|
|
156
|
-
|
|
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(
|
|
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
|
|
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.
|
|
185
|
-
const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
186
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(
|
|
187
|
-
|
|
188
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
244
|
-
const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
245
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(
|
|
246
|
-
|
|
247
|
-
|
|
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(
|
|
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
|
|
255
|
-
...
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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
|
|
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.
|
|
279
|
-
const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
280
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(
|
|
281
|
-
|
|
282
|
-
|
|
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
|
|
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.
|
|
307
|
-
const documentFilter = await this._getDocumentFilter(
|
|
308
|
-
const nestedFilter = await this._getNestedFilter(
|
|
309
|
-
|
|
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
|
-
|
|
314
|
-
|
|
315
|
-
|
|
384
|
+
documentFilter,
|
|
385
|
+
limit: command.options?.limit || this.defaultLimit,
|
|
386
|
+
};
|
|
387
|
+
return this._findMany(command);
|
|
388
|
+
});
|
|
316
389
|
}
|
|
317
|
-
async _findMany(
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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.
|
|
374
|
-
const documentFilter = await this._getDocumentFilter(
|
|
375
|
-
const nestedFilter = await this._getNestedFilter(
|
|
376
|
-
|
|
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
|
-
|
|
381
|
-
|
|
382
|
-
|
|
454
|
+
documentFilter,
|
|
455
|
+
limit: command.options?.limit || this.defaultLimit,
|
|
456
|
+
};
|
|
457
|
+
return this._findManyWithCount(command);
|
|
458
|
+
});
|
|
383
459
|
}
|
|
384
|
-
async _findManyWithCount(
|
|
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
|
|
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
|
|
406
|
-
const optionsFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([options?.filter, options
|
|
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.
|
|
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) =>
|
|
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.
|
|
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
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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.
|
|
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
|
|
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.
|
|
493
|
-
const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
494
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(
|
|
495
|
-
|
|
496
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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.
|
|
522
|
-
const documentFilter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
523
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getNestedFilter(
|
|
524
|
-
|
|
525
|
-
|
|
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(
|
|
528
|
-
const
|
|
529
|
-
|
|
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
|
-
|
|
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
|
|
689
|
+
return typeof this.nestedFilter === 'function' ? this.nestedFilter(args, this) : this.nestedFilter;
|
|
572
690
|
}
|
|
573
691
|
}
|
|
574
692
|
exports.MongoNestedService = MongoNestedService;
|