@opra/mongodb 1.0.0-alpha.2 → 1.0.0-alpha.21
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,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MongoEntityService = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
-
const lodash_omit_1 = tslib_1.__importDefault(require("lodash.omit"));
|
|
6
|
-
const assert = tslib_1.__importStar(require("node:assert"));
|
|
7
5
|
const common_1 = require("@opra/common");
|
|
6
|
+
const lodash_omit_1 = tslib_1.__importDefault(require("lodash.omit"));
|
|
7
|
+
const valgen_1 = require("valgen");
|
|
8
8
|
const mongo_adapter_js_1 = require("./mongo-adapter.js");
|
|
9
9
|
const mongo_service_js_1 = require("./mongo-service.js");
|
|
10
10
|
/**
|
|
@@ -25,19 +25,27 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
25
25
|
/**
|
|
26
26
|
* Creates a new document in the MongoDB collection.
|
|
27
27
|
*
|
|
28
|
-
* @param {
|
|
29
|
-
* @param {MongoEntityService.CreateOptions} options
|
|
28
|
+
* @param {MongoEntityService.CreateCommand} command
|
|
30
29
|
* @protected
|
|
31
30
|
*/
|
|
32
|
-
async _create(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
async _create(command) {
|
|
32
|
+
(0, valgen_1.isNotNullish)(command.input, { label: 'input' });
|
|
33
|
+
(0, valgen_1.isNotNullish)(command.input._id, { label: 'input._id' });
|
|
34
|
+
const inputCodec = this.getInputCodec('create');
|
|
35
|
+
const doc = inputCodec(command.input);
|
|
36
|
+
const { options } = command;
|
|
36
37
|
const r = await this._dbInsertOne(doc, options);
|
|
37
38
|
if (r.insertedId) {
|
|
38
|
-
if (!options)
|
|
39
|
+
if (!command.options)
|
|
39
40
|
return doc;
|
|
40
|
-
const
|
|
41
|
+
const findCommand = {
|
|
42
|
+
...command,
|
|
43
|
+
crud: 'read',
|
|
44
|
+
byId: true,
|
|
45
|
+
documentId: doc._id,
|
|
46
|
+
options: (0, lodash_omit_1.default)(options, 'filter'),
|
|
47
|
+
};
|
|
48
|
+
const out = await this._findById(findCommand);
|
|
41
49
|
if (out)
|
|
42
50
|
return out;
|
|
43
51
|
}
|
|
@@ -47,92 +55,103 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
47
55
|
/**
|
|
48
56
|
* Returns the count of documents in the collection based on the provided options.
|
|
49
57
|
*
|
|
50
|
-
* @param {MongoEntityService.
|
|
51
|
-
* @
|
|
58
|
+
* @param {MongoEntityService.CountCommand<T>} command
|
|
59
|
+
* @protected
|
|
52
60
|
*/
|
|
53
|
-
async _count(
|
|
61
|
+
async _count(command) {
|
|
62
|
+
const { options } = command;
|
|
54
63
|
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter(options?.filter);
|
|
55
64
|
return this._dbCountDocuments(filter, (0, lodash_omit_1.default)(options, 'filter'));
|
|
56
65
|
}
|
|
57
66
|
/**
|
|
58
67
|
* Deletes a document from the collection.
|
|
59
68
|
*
|
|
60
|
-
* @param {
|
|
61
|
-
* @
|
|
62
|
-
* @return {Promise<number>} - A Promise that resolves to the number of documents deleted.
|
|
69
|
+
* @param {MongoEntityService.DeleteCommand<T>} command
|
|
70
|
+
* @protected
|
|
63
71
|
*/
|
|
64
|
-
async _delete(
|
|
65
|
-
|
|
66
|
-
const
|
|
72
|
+
async _delete(command) {
|
|
73
|
+
(0, valgen_1.isNotNullish)(command.documentId, { label: 'documentId' });
|
|
74
|
+
const { options } = command;
|
|
75
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
76
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(command.documentId, ['_id']),
|
|
77
|
+
options?.filter,
|
|
78
|
+
]);
|
|
67
79
|
const r = await this._dbDeleteOne(filter, options);
|
|
68
80
|
return r.deletedCount;
|
|
69
81
|
}
|
|
70
82
|
/**
|
|
71
83
|
* Deletes multiple documents from the collection that meet the specified filter criteria.
|
|
72
84
|
*
|
|
73
|
-
* @param {MongoEntityService.
|
|
74
|
-
* @
|
|
85
|
+
* @param {MongoEntityService.DeleteCommand<T>} command
|
|
86
|
+
* @protected
|
|
75
87
|
*/
|
|
76
|
-
async _deleteMany(
|
|
88
|
+
async _deleteMany(command) {
|
|
89
|
+
const { options } = command;
|
|
77
90
|
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter(options?.filter);
|
|
78
91
|
const r = await this._dbDeleteMany(filter, (0, lodash_omit_1.default)(options, 'filter'));
|
|
79
92
|
return r.deletedCount;
|
|
80
93
|
}
|
|
81
94
|
/**
|
|
82
95
|
* The distinct command returns a list of distinct values for the given key across a collection.
|
|
83
|
-
*
|
|
84
|
-
* @param {MongoEntityService.
|
|
96
|
+
*
|
|
97
|
+
* @param {MongoEntityService.DistinctCommand<T>} command
|
|
85
98
|
* @protected
|
|
86
99
|
*/
|
|
87
|
-
async _distinct(
|
|
100
|
+
async _distinct(command) {
|
|
101
|
+
const { options, field } = command;
|
|
88
102
|
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter(options?.filter);
|
|
89
103
|
return await this._dbDistinct(field, filter, (0, lodash_omit_1.default)(options, 'filter'));
|
|
90
104
|
}
|
|
91
105
|
/**
|
|
92
106
|
* Finds a document by its ID.
|
|
93
107
|
*
|
|
94
|
-
* @param {
|
|
95
|
-
* @param {MongoEntityService.FindOneOptions<T>} [options] - The options for the find query.
|
|
96
|
-
* @return {Promise<PartialDTO<T | undefined>>} - A promise resolving to the found document, or undefined if not found.
|
|
108
|
+
* @param { MongoEntityService.FindOneCommand<T>} command
|
|
97
109
|
*/
|
|
98
|
-
async _findById(
|
|
99
|
-
|
|
110
|
+
async _findById(command) {
|
|
111
|
+
(0, valgen_1.isNotNullish)(command.documentId, { label: 'documentId' });
|
|
112
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
113
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(command.documentId, ['_id']),
|
|
114
|
+
command.options?.filter,
|
|
115
|
+
]);
|
|
116
|
+
const { options } = command;
|
|
100
117
|
const mongoOptions = {
|
|
101
118
|
...options,
|
|
102
|
-
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.
|
|
119
|
+
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
103
120
|
limit: undefined,
|
|
104
121
|
skip: undefined,
|
|
105
122
|
sort: undefined,
|
|
106
123
|
};
|
|
107
|
-
const decode = this.getDecoder();
|
|
108
124
|
const out = await this._dbFindOne(filter, mongoOptions);
|
|
109
|
-
|
|
125
|
+
const outputCodec = this.getOutputCodec('find');
|
|
126
|
+
if (out)
|
|
127
|
+
return outputCodec(out);
|
|
110
128
|
}
|
|
111
129
|
/**
|
|
112
130
|
* Finds a document in the collection that matches the specified options.
|
|
113
131
|
*
|
|
114
|
-
* @param {MongoEntityService.
|
|
115
|
-
* @return {Promise<PartialDTO<T> | undefined>} A promise that resolves with the found document or undefined if no document is found.
|
|
132
|
+
* @param {MongoEntityService.FindOneCommand<T>} command
|
|
116
133
|
*/
|
|
117
|
-
async _findOne(
|
|
134
|
+
async _findOne(command) {
|
|
135
|
+
const { options } = command;
|
|
118
136
|
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter(options?.filter);
|
|
119
137
|
const mongoOptions = {
|
|
120
138
|
...(0, lodash_omit_1.default)(options, 'filter'),
|
|
121
139
|
sort: options?.sort ? mongo_adapter_js_1.MongoAdapter.prepareSort(options.sort) : undefined,
|
|
122
|
-
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.
|
|
140
|
+
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
123
141
|
limit: undefined,
|
|
124
142
|
};
|
|
125
|
-
const decode = this.getDecoder();
|
|
126
143
|
const out = await this._dbFindOne(filter, mongoOptions);
|
|
127
|
-
|
|
144
|
+
const outputCodec = this.getOutputCodec('find');
|
|
145
|
+
if (out)
|
|
146
|
+
return outputCodec(out);
|
|
128
147
|
}
|
|
129
148
|
/**
|
|
130
149
|
* Finds multiple documents in the MongoDB collection.
|
|
131
150
|
*
|
|
132
|
-
* @param {MongoEntityService.
|
|
133
|
-
* @return A Promise that resolves to an array of partial outputs of type T.
|
|
151
|
+
* @param {MongoEntityService.FindManyCommand<T>} command
|
|
134
152
|
*/
|
|
135
|
-
async _findMany(
|
|
153
|
+
async _findMany(command) {
|
|
154
|
+
const { options } = command;
|
|
136
155
|
const mongoOptions = {
|
|
137
156
|
...(0, lodash_omit_1.default)(options, ['projection', 'sort', 'skip', 'limit', 'filter']),
|
|
138
157
|
};
|
|
@@ -151,16 +170,16 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
151
170
|
stages.push({ $sort: sort });
|
|
152
171
|
}
|
|
153
172
|
stages.push({ $limit: limit });
|
|
154
|
-
const dataType = this.
|
|
173
|
+
const dataType = this.dataType;
|
|
155
174
|
const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection);
|
|
156
175
|
if (projection)
|
|
157
176
|
stages.push({ $project: projection });
|
|
158
|
-
const decode = this.getDecoder();
|
|
159
177
|
const cursor = await this._dbAggregate(stages, mongoOptions);
|
|
160
178
|
/** Execute db command */
|
|
161
179
|
try {
|
|
162
180
|
/** Fetch the cursor and decode the result objects */
|
|
163
|
-
|
|
181
|
+
const outputCodec = this.getOutputCodec('find');
|
|
182
|
+
return (await cursor.toArray()).map((r) => outputCodec(r));
|
|
164
183
|
}
|
|
165
184
|
finally {
|
|
166
185
|
if (!cursor.closed)
|
|
@@ -171,10 +190,10 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
171
190
|
* Finds multiple documents in the collection and returns both records (max limit)
|
|
172
191
|
* and total count that matched the given criteria
|
|
173
192
|
*
|
|
174
|
-
* @param {MongoEntityService.
|
|
175
|
-
* @return A Promise that resolves to an array of partial outputs of type T.
|
|
193
|
+
* @param {MongoEntityService.FindManyCommand<T>} command
|
|
176
194
|
*/
|
|
177
|
-
async _findManyWithCount(
|
|
195
|
+
async _findManyWithCount(command) {
|
|
196
|
+
const { options } = command;
|
|
178
197
|
const mongoOptions = {
|
|
179
198
|
...(0, lodash_omit_1.default)(options, ['projection', 'sort', 'skip', 'limit', 'filter']),
|
|
180
199
|
};
|
|
@@ -205,11 +224,11 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
205
224
|
dataStages.push({ $sort: sort });
|
|
206
225
|
}
|
|
207
226
|
dataStages.push({ $limit: limit });
|
|
208
|
-
const dataType = this.
|
|
227
|
+
const dataType = this.dataType;
|
|
209
228
|
const projection = mongo_adapter_js_1.MongoAdapter.prepareProjection(dataType, options?.projection);
|
|
210
229
|
if (projection)
|
|
211
230
|
dataStages.push({ $project: projection });
|
|
212
|
-
const
|
|
231
|
+
const outputCodec = this.getOutputCodec('find');
|
|
213
232
|
/** Execute db command */
|
|
214
233
|
const cursor = await this._dbAggregate(stages, mongoOptions);
|
|
215
234
|
try {
|
|
@@ -217,7 +236,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
217
236
|
const facetResult = await cursor.toArray();
|
|
218
237
|
return {
|
|
219
238
|
count: facetResult[0].count[0]?.totalMatches || 0,
|
|
220
|
-
items: facetResult[0].data?.map((r) =>
|
|
239
|
+
items: facetResult[0].data?.map((r) => outputCodec(r)),
|
|
221
240
|
};
|
|
222
241
|
}
|
|
223
242
|
finally {
|
|
@@ -228,68 +247,72 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
228
247
|
/**
|
|
229
248
|
* Updates a document with the given id in the collection.
|
|
230
249
|
*
|
|
231
|
-
* @param {
|
|
232
|
-
* @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input object containing the fields to update.
|
|
233
|
-
* @param {MongoEntityService.UpdateOptions<T>} [options] - The options for the update operation.
|
|
234
|
-
* @returns {Promise<PartialDTO<T> | undefined>} A promise that resolves to the updated document or
|
|
235
|
-
* undefined if the document was not found.
|
|
250
|
+
* @param {MongoEntityService.UpdateOneCommand<T>} command
|
|
236
251
|
*/
|
|
237
|
-
async _update(
|
|
238
|
-
|
|
239
|
-
const
|
|
240
|
-
|
|
252
|
+
async _update(command) {
|
|
253
|
+
(0, valgen_1.isNotNullish)(command.documentId, { label: 'documentId' });
|
|
254
|
+
const { input, inputRaw, options } = command;
|
|
255
|
+
(0, valgen_1.isNotNullish)(input || inputRaw, { label: 'input' });
|
|
256
|
+
if (input && inputRaw) {
|
|
241
257
|
throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
|
|
258
|
+
}
|
|
242
259
|
let update;
|
|
243
|
-
if (
|
|
244
|
-
const
|
|
245
|
-
const doc =
|
|
260
|
+
if (input) {
|
|
261
|
+
const inputCodec = this.getInputCodec('update');
|
|
262
|
+
const doc = inputCodec(input);
|
|
246
263
|
delete doc._id;
|
|
247
264
|
update = mongo_adapter_js_1.MongoAdapter.preparePatch(doc);
|
|
248
265
|
update.$set = update.$set || {};
|
|
249
266
|
}
|
|
250
267
|
else
|
|
251
|
-
update =
|
|
252
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
268
|
+
update = inputRaw;
|
|
269
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
270
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(command.documentId, ['_id']),
|
|
271
|
+
options?.filter,
|
|
272
|
+
]);
|
|
253
273
|
const mongoOptions = {
|
|
254
274
|
...options,
|
|
255
275
|
includeResultMetadata: false,
|
|
256
276
|
upsert: undefined,
|
|
257
|
-
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.
|
|
277
|
+
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
258
278
|
};
|
|
259
|
-
const decode = this.getDecoder();
|
|
260
279
|
const out = await this._dbFindOneAndUpdate(filter, update, mongoOptions);
|
|
261
|
-
|
|
280
|
+
const outputCodec = this.getOutputCodec('update');
|
|
281
|
+
if (out)
|
|
282
|
+
return outputCodec(out);
|
|
262
283
|
}
|
|
263
284
|
/**
|
|
264
285
|
* Updates a document in the collection with the specified ID.
|
|
265
286
|
*
|
|
266
|
-
* @param {
|
|
267
|
-
* @param {PatchDTO<T>|UpdateFilter<T>} input - The partial input data to update the document with.
|
|
268
|
-
* @param {MongoEntityService.UpdateOptions<T>} [options] - The options for updating the document.
|
|
269
|
-
* @returns {Promise<number>} - A promise that resolves to the number of documents modified.
|
|
287
|
+
* @param {MongoEntityService.UpdateOneCommand<T>} command
|
|
270
288
|
*/
|
|
271
|
-
async _updateOnly(
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
|
|
289
|
+
async _updateOnly(command) {
|
|
290
|
+
(0, valgen_1.isNotNullish)(command.documentId, { label: 'documentId' });
|
|
291
|
+
const { input, inputRaw, options } = command;
|
|
292
|
+
(0, valgen_1.isNotNullish)(input || inputRaw, { label: 'input' });
|
|
293
|
+
if (input && inputRaw) {
|
|
275
294
|
throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
|
|
295
|
+
}
|
|
276
296
|
let update;
|
|
277
|
-
if (
|
|
278
|
-
const
|
|
279
|
-
const doc =
|
|
297
|
+
if (input) {
|
|
298
|
+
const inputCodec = this.getInputCodec('update');
|
|
299
|
+
const doc = inputCodec(input);
|
|
280
300
|
delete doc._id;
|
|
281
301
|
update = mongo_adapter_js_1.MongoAdapter.preparePatch(doc);
|
|
282
302
|
if (!Object.keys(doc).length)
|
|
283
303
|
return 0;
|
|
284
304
|
}
|
|
285
305
|
else
|
|
286
|
-
update =
|
|
287
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
306
|
+
update = inputRaw;
|
|
307
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([
|
|
308
|
+
mongo_adapter_js_1.MongoAdapter.prepareKeyValues(command.documentId, ['_id']),
|
|
309
|
+
options?.filter,
|
|
310
|
+
]);
|
|
288
311
|
const mongoOptions = {
|
|
289
312
|
...options,
|
|
290
313
|
includeResultMetadata: false,
|
|
291
314
|
upsert: undefined,
|
|
292
|
-
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.
|
|
315
|
+
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
293
316
|
};
|
|
294
317
|
const out = await this._dbUpdateOne(filter, update, mongoOptions);
|
|
295
318
|
return out.matchedCount;
|
|
@@ -297,26 +320,26 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
297
320
|
/**
|
|
298
321
|
* Updates multiple documents in the collection based on the specified input and options.
|
|
299
322
|
*
|
|
300
|
-
* @param {
|
|
301
|
-
* @param {MongoEntityService.UpdateManyOptions<T>} [options] - The options for updating the documents.
|
|
302
|
-
* @return {Promise<number>} - A promise that resolves to the number of documents matched and modified.
|
|
323
|
+
* @param {MongoEntityService.UpdateManyCommand<T>} command
|
|
303
324
|
*/
|
|
304
|
-
async _updateMany(
|
|
305
|
-
|
|
306
|
-
const
|
|
307
|
-
|
|
325
|
+
async _updateMany(command) {
|
|
326
|
+
(0, valgen_1.isNotNullish)(command.input, { label: 'input' });
|
|
327
|
+
const { input, inputRaw, options } = command;
|
|
328
|
+
(0, valgen_1.isNotNullish)(input || inputRaw, { label: 'input' });
|
|
329
|
+
if (input && inputRaw) {
|
|
308
330
|
throw new TypeError('You must pass one of MongoDB UpdateFilter or a partial document, not both');
|
|
331
|
+
}
|
|
309
332
|
let update;
|
|
310
|
-
if (
|
|
311
|
-
const
|
|
312
|
-
const doc =
|
|
333
|
+
if (input) {
|
|
334
|
+
const inputCodec = this.getInputCodec('update');
|
|
335
|
+
const doc = inputCodec(input);
|
|
313
336
|
delete doc._id;
|
|
314
337
|
update = mongo_adapter_js_1.MongoAdapter.preparePatch(doc);
|
|
315
338
|
if (!Object.keys(doc).length)
|
|
316
339
|
return 0;
|
|
317
340
|
}
|
|
318
341
|
else
|
|
319
|
-
update =
|
|
342
|
+
update = inputRaw;
|
|
320
343
|
const mongoOptions = {
|
|
321
344
|
...(0, lodash_omit_1.default)(options, 'filter'),
|
|
322
345
|
upsert: undefined,
|