@opra/mongodb 1.0.0-alpha.9 → 1.0.0-beta.2
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 +1 -1
- package/cjs/adapter-utils/prepare-key-values.js +1 -1
- package/cjs/adapter-utils/prepare-patch.js +1 -1
- package/cjs/adapter-utils/prepare-projection.js +6 -7
- package/cjs/adapter-utils/prepare-sort.js +1 -1
- package/cjs/index.js +1 -0
- package/cjs/mongo-adapter.js +4 -4
- package/cjs/mongo-collection-service.js +123 -141
- package/cjs/mongo-entity-service.js +259 -131
- package/cjs/mongo-nested-service.js +416 -211
- package/cjs/mongo-service.js +79 -239
- package/cjs/mongo-singleton-service.js +101 -63
- package/esm/adapter-utils/prepare-projection.js +4 -4
- package/esm/index.js +1 -0
- package/esm/mongo-adapter.js +4 -4
- package/esm/mongo-collection-service.js +122 -141
- package/esm/mongo-entity-service.js +259 -131
- package/esm/mongo-nested-service.js +416 -211
- package/esm/mongo-service.js +79 -239
- package/esm/mongo-singleton-service.js +100 -63
- package/esm/package.json +3 -0
- package/package.json +27 -33
- package/types/adapter-utils/prepare-filter.d.ts +2 -2
- package/types/adapter-utils/prepare-projection.d.ts +1 -1
- package/types/index.d.cts +6 -0
- package/types/index.d.ts +1 -0
- package/types/mongo-adapter.d.ts +1 -1
- package/types/mongo-collection-service.d.ts +44 -64
- package/types/mongo-entity-service.d.ts +91 -53
- package/types/mongo-nested-service.d.ts +107 -43
- package/types/mongo-service.d.ts +55 -153
- package/types/mongo-singleton-service.d.ts +33 -30
package/cjs/mongo-service.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.MongoService = void 0;
|
|
|
4
4
|
const common_1 = require("@opra/common");
|
|
5
5
|
const core_1 = require("@opra/core");
|
|
6
6
|
const mongodb_1 = require("mongodb");
|
|
7
|
+
const mongo_adapter_js_1 = require("./mongo-adapter.js");
|
|
7
8
|
/**
|
|
8
9
|
* Class representing a MongoDB service for interacting with a collection.
|
|
9
10
|
* @extends ServiceBase
|
|
@@ -23,20 +24,33 @@ class MongoService extends core_1.ServiceBase {
|
|
|
23
24
|
this._outputCodecs = {};
|
|
24
25
|
this._dataType_ = dataType;
|
|
25
26
|
this.db = options?.db;
|
|
26
|
-
this
|
|
27
|
-
this
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
this.documentFilter = options?.documentFilter;
|
|
28
|
+
this.interceptor = options?.interceptor;
|
|
29
|
+
if (options?.collectionName)
|
|
30
|
+
this.collectionName = options?.collectionName;
|
|
31
|
+
else {
|
|
30
32
|
if (typeof dataType === 'string')
|
|
31
|
-
this
|
|
33
|
+
this.collectionName = dataType;
|
|
32
34
|
if (typeof dataType === 'function') {
|
|
33
35
|
const metadata = Reflect.getMetadata(common_1.DATATYPE_METADATA, dataType);
|
|
34
36
|
if (metadata)
|
|
35
|
-
this
|
|
37
|
+
this.collectionName = metadata.name;
|
|
36
38
|
}
|
|
37
39
|
}
|
|
38
|
-
this
|
|
39
|
-
this
|
|
40
|
+
this.resourceName = options?.resourceName;
|
|
41
|
+
this.idGenerator = options?.idGenerator;
|
|
42
|
+
this.onError = options?.onError;
|
|
43
|
+
}
|
|
44
|
+
for(context, overwriteProperties, overwriteContext) {
|
|
45
|
+
if (overwriteProperties?.documentFilter && this.documentFilter) {
|
|
46
|
+
overwriteProperties.documentFilter = [
|
|
47
|
+
...(Array.isArray(this.documentFilter) ? this.documentFilter : [this.documentFilter]),
|
|
48
|
+
...(Array.isArray(overwriteProperties?.documentFilter)
|
|
49
|
+
? overwriteProperties?.documentFilter
|
|
50
|
+
: [overwriteProperties?.documentFilter]),
|
|
51
|
+
];
|
|
52
|
+
}
|
|
53
|
+
return super.for(context, overwriteProperties, overwriteContext);
|
|
40
54
|
}
|
|
41
55
|
/**
|
|
42
56
|
* Retrieves the collection name.
|
|
@@ -46,7 +60,7 @@ class MongoService extends core_1.ServiceBase {
|
|
|
46
60
|
* @throws {Error} If the collection name is not defined.
|
|
47
61
|
*/
|
|
48
62
|
getCollectionName() {
|
|
49
|
-
const out = typeof this
|
|
63
|
+
const out = typeof this.collectionName === 'function' ? this.collectionName(this) : this.collectionName;
|
|
50
64
|
if (out)
|
|
51
65
|
return out;
|
|
52
66
|
throw new Error('collectionName is not defined');
|
|
@@ -56,12 +70,10 @@ class MongoService extends core_1.ServiceBase {
|
|
|
56
70
|
*
|
|
57
71
|
* @protected
|
|
58
72
|
* @returns {string} The resource name.
|
|
59
|
-
* @throws {Error} If the
|
|
73
|
+
* @throws {Error} If the resource name is not defined.
|
|
60
74
|
*/
|
|
61
75
|
getResourceName() {
|
|
62
|
-
const out = typeof this
|
|
63
|
-
? this.$resourceName(this)
|
|
64
|
-
: this.$resourceName || this.getCollectionName();
|
|
76
|
+
const out = typeof this.resourceName === 'function' ? this.resourceName(this) : this.resourceName || this.getCollectionName();
|
|
65
77
|
if (out)
|
|
66
78
|
return out;
|
|
67
79
|
throw new Error('resourceName is not defined');
|
|
@@ -76,36 +88,6 @@ class MongoService extends core_1.ServiceBase {
|
|
|
76
88
|
this._dataType = this.context.document.node.getComplexType(this._dataType_);
|
|
77
89
|
return this._dataType;
|
|
78
90
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Retrieves the codec for the specified operation.
|
|
81
|
-
*
|
|
82
|
-
* @param operation - The operation to retrieve the encoder for. Valid values are 'create' and 'update'.
|
|
83
|
-
*/
|
|
84
|
-
getInputCodec(operation) {
|
|
85
|
-
let validator = this._inputCodecs[operation];
|
|
86
|
-
if (validator)
|
|
87
|
-
return validator;
|
|
88
|
-
const options = { projection: '*' };
|
|
89
|
-
if (operation === 'update')
|
|
90
|
-
options.partial = 'deep';
|
|
91
|
-
const dataType = this.dataType;
|
|
92
|
-
validator = dataType.generateCodec('decode', options);
|
|
93
|
-
this._inputCodecs[operation] = validator;
|
|
94
|
-
return validator;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Retrieves the codec.
|
|
98
|
-
*/
|
|
99
|
-
getOutputCodec(operation) {
|
|
100
|
-
let validator = this._outputCodecs[operation];
|
|
101
|
-
if (validator)
|
|
102
|
-
return validator;
|
|
103
|
-
const options = { projection: '*', partial: 'deep' };
|
|
104
|
-
const dataType = this.dataType;
|
|
105
|
-
validator = dataType.generateCodec('decode', options);
|
|
106
|
-
this._outputCodecs[operation] = validator;
|
|
107
|
-
return validator;
|
|
108
|
-
}
|
|
109
91
|
/**
|
|
110
92
|
* Executes the provided function within a transaction.
|
|
111
93
|
*
|
|
@@ -147,191 +129,6 @@ class MongoService extends core_1.ServiceBase {
|
|
|
147
129
|
await session.endSession();
|
|
148
130
|
}
|
|
149
131
|
}
|
|
150
|
-
/**
|
|
151
|
-
* Gets the number of documents matching the filter.
|
|
152
|
-
*
|
|
153
|
-
* @param filter - The filter used to match documents.
|
|
154
|
-
* @param options - The options for counting documents.
|
|
155
|
-
* @protected
|
|
156
|
-
*/
|
|
157
|
-
async _dbCountDocuments(filter, options) {
|
|
158
|
-
const db = this.getDatabase();
|
|
159
|
-
const collection = await this.getCollection(db);
|
|
160
|
-
options = {
|
|
161
|
-
...options,
|
|
162
|
-
limit: undefined,
|
|
163
|
-
session: options?.session || this.getSession(),
|
|
164
|
-
};
|
|
165
|
-
return (await collection.countDocuments(filter || {}, options)) || 0;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Acquires a connection and performs Collection.deleteOne operation
|
|
169
|
-
*
|
|
170
|
-
* @param filter - The filter used to select the document to remove
|
|
171
|
-
* @param options - Optional settings for the command
|
|
172
|
-
* @protected
|
|
173
|
-
*/
|
|
174
|
-
async _dbDeleteOne(filter, options) {
|
|
175
|
-
const db = this.getDatabase();
|
|
176
|
-
const collection = await this.getCollection(db);
|
|
177
|
-
options = {
|
|
178
|
-
...options,
|
|
179
|
-
session: options?.session || this.getSession(),
|
|
180
|
-
};
|
|
181
|
-
return await collection.deleteOne(filter || {}, options);
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Acquires a connection and performs Collection.deleteMany operation
|
|
185
|
-
*
|
|
186
|
-
* @param filter - The filter used to select the documents to remove
|
|
187
|
-
* @param options - Optional settings for the command
|
|
188
|
-
* @protected
|
|
189
|
-
*/
|
|
190
|
-
async _dbDeleteMany(filter, options) {
|
|
191
|
-
const db = this.getDatabase();
|
|
192
|
-
const collection = await this.getCollection(db);
|
|
193
|
-
options = {
|
|
194
|
-
...options,
|
|
195
|
-
session: options?.session || this.getSession(),
|
|
196
|
-
};
|
|
197
|
-
return await collection.deleteMany(filter || {}, options);
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Acquires a connection and performs Collection.distinct operation
|
|
201
|
-
*
|
|
202
|
-
* @param field - Field of the document to find distinct values for
|
|
203
|
-
* @param filter - The filter for filtering the set of documents to which we apply the distinct filter.
|
|
204
|
-
* @param options - Optional settings for the command
|
|
205
|
-
* @protected
|
|
206
|
-
*/
|
|
207
|
-
async _dbDistinct(field, filter, options) {
|
|
208
|
-
const db = this.getDatabase();
|
|
209
|
-
const collection = await this.getCollection(db);
|
|
210
|
-
options = {
|
|
211
|
-
...options,
|
|
212
|
-
session: options?.session || this.getSession(),
|
|
213
|
-
};
|
|
214
|
-
return await collection.distinct(field, filter || {}, options);
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Acquires a connection and performs Collection.aggregate operation
|
|
218
|
-
*
|
|
219
|
-
* @param pipeline - An array of aggregation pipelines to execute
|
|
220
|
-
* @param options - Optional settings for the command
|
|
221
|
-
* @protected
|
|
222
|
-
*/
|
|
223
|
-
async _dbAggregate(pipeline, options) {
|
|
224
|
-
const db = this.getDatabase();
|
|
225
|
-
const collection = await this.getCollection(db);
|
|
226
|
-
options = {
|
|
227
|
-
...options,
|
|
228
|
-
session: options?.session || this.getSession(),
|
|
229
|
-
};
|
|
230
|
-
return await collection.aggregate(pipeline, options);
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Acquires a connection and performs Collection.findOne operation
|
|
234
|
-
*
|
|
235
|
-
* @param filter - Query for find Operation
|
|
236
|
-
* @param options - Optional settings for the command
|
|
237
|
-
* @protected
|
|
238
|
-
*/
|
|
239
|
-
async _dbFindOne(filter, options) {
|
|
240
|
-
const db = this.getDatabase();
|
|
241
|
-
const collection = await this.getCollection(db);
|
|
242
|
-
options = {
|
|
243
|
-
...options,
|
|
244
|
-
session: options?.session || this.getSession(),
|
|
245
|
-
};
|
|
246
|
-
return (await collection.findOne(filter || {}, options));
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
|
-
* Acquires a connection and performs Collection.find operation
|
|
250
|
-
*
|
|
251
|
-
* @param filter - The filter predicate. If unspecified,
|
|
252
|
-
* then all documents in the collection will match the predicate
|
|
253
|
-
* @param options - Optional settings for the command
|
|
254
|
-
* @protected
|
|
255
|
-
*/
|
|
256
|
-
async _dbFind(filter, options) {
|
|
257
|
-
const db = this.getDatabase();
|
|
258
|
-
const collection = await this.getCollection(db);
|
|
259
|
-
options = {
|
|
260
|
-
...options,
|
|
261
|
-
session: options?.session || this.getSession(),
|
|
262
|
-
};
|
|
263
|
-
return collection.find(filter || {}, options);
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Acquires a connection and performs Collection.insertOne operation
|
|
267
|
-
*
|
|
268
|
-
* @param doc - The document to insert
|
|
269
|
-
* @param options - Optional settings for the command
|
|
270
|
-
* @protected
|
|
271
|
-
*/
|
|
272
|
-
async _dbInsertOne(doc, options) {
|
|
273
|
-
const db = this.getDatabase();
|
|
274
|
-
const collection = await this.getCollection(db);
|
|
275
|
-
options = {
|
|
276
|
-
...options,
|
|
277
|
-
session: options?.session || this.getSession(),
|
|
278
|
-
};
|
|
279
|
-
return await collection.insertOne(doc, options);
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Acquires a connection and performs Collection.updateOne operation
|
|
283
|
-
*
|
|
284
|
-
* @param filter - The filter used to select the document to update
|
|
285
|
-
* @param update - The update operations to be applied to the document
|
|
286
|
-
* @param options - Optional settings for the command
|
|
287
|
-
* @protected
|
|
288
|
-
*/
|
|
289
|
-
async _dbUpdateOne(filter, update, options) {
|
|
290
|
-
const db = this.getDatabase();
|
|
291
|
-
const collection = await this.getCollection(db);
|
|
292
|
-
options = {
|
|
293
|
-
...options,
|
|
294
|
-
session: options?.session || this.getSession(),
|
|
295
|
-
};
|
|
296
|
-
return collection.updateOne(filter || {}, update, options);
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Acquires a connection and performs Collection.findOneAndUpdate operation
|
|
300
|
-
*
|
|
301
|
-
* @param filter - The filter used to select the document to update
|
|
302
|
-
* @param update - Update operations to be performed on the document
|
|
303
|
-
* @param options - Optional settings for the command
|
|
304
|
-
* @protected
|
|
305
|
-
*/
|
|
306
|
-
async _dbFindOneAndUpdate(filter, update, options) {
|
|
307
|
-
const db = this.getDatabase();
|
|
308
|
-
const collection = await this.getCollection(db);
|
|
309
|
-
const opts = {
|
|
310
|
-
returnDocument: 'after',
|
|
311
|
-
includeResultMetadata: false,
|
|
312
|
-
...options,
|
|
313
|
-
session: options?.session || this.getSession(),
|
|
314
|
-
};
|
|
315
|
-
return await collection.findOneAndUpdate(filter || {}, update, opts);
|
|
316
|
-
}
|
|
317
|
-
/**
|
|
318
|
-
* Acquires a connection and performs Collection.updateMany operation
|
|
319
|
-
*
|
|
320
|
-
* @param filter - The filter used to select the documents to update
|
|
321
|
-
* @param update - The update operations to be applied to the documents
|
|
322
|
-
* @param options - Optional settings for the command
|
|
323
|
-
* @protected
|
|
324
|
-
*/
|
|
325
|
-
async _dbUpdateMany(filter, update, options) {
|
|
326
|
-
const db = this.getDatabase();
|
|
327
|
-
const collection = await this.getCollection(db);
|
|
328
|
-
options = {
|
|
329
|
-
...options,
|
|
330
|
-
session: options?.session || this.getSession(),
|
|
331
|
-
upsert: false,
|
|
332
|
-
};
|
|
333
|
-
return await collection.updateMany(filter || {}, update, options);
|
|
334
|
-
}
|
|
335
132
|
/**
|
|
336
133
|
* Retrieves the database connection.
|
|
337
134
|
*
|
|
@@ -370,8 +167,8 @@ class MongoService extends core_1.ServiceBase {
|
|
|
370
167
|
* @protected
|
|
371
168
|
* @returns {MongoAdapter.AnyId} The generated ID.
|
|
372
169
|
*/
|
|
373
|
-
_generateId() {
|
|
374
|
-
return typeof this
|
|
170
|
+
_generateId(command) {
|
|
171
|
+
return typeof this.idGenerator === 'function' ? this.idGenerator(command, this) : new mongodb_1.ObjectId();
|
|
375
172
|
}
|
|
376
173
|
/**
|
|
377
174
|
* Retrieves the common filter used for querying documents.
|
|
@@ -381,20 +178,63 @@ class MongoService extends core_1.ServiceBase {
|
|
|
381
178
|
* @returns {FilterInput | Promise<FilterInput> | undefined} The common filter or a Promise
|
|
382
179
|
* that resolves to the common filter, or undefined if not available.
|
|
383
180
|
*/
|
|
384
|
-
_getDocumentFilter(
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
181
|
+
_getDocumentFilter(command) {
|
|
182
|
+
const commonFilter = Array.isArray(this.documentFilter) ? this.documentFilter : [this.documentFilter];
|
|
183
|
+
const mapped = commonFilter.map(f => (typeof f === 'function' ? f(command, this) : f));
|
|
184
|
+
return mapped.length > 1 ? mongo_adapter_js_1.MongoAdapter.prepareFilter(mapped) : mapped[0];
|
|
185
|
+
}
|
|
186
|
+
async _executeCommand(command, commandFn) {
|
|
187
|
+
let proto;
|
|
188
|
+
const next = async () => {
|
|
189
|
+
proto = proto ? Object.getPrototypeOf(proto) : this;
|
|
190
|
+
while (proto) {
|
|
191
|
+
if (proto.interceptor && Object.prototype.hasOwnProperty.call(proto, 'interceptor')) {
|
|
192
|
+
return await proto.interceptor.call(this, next, command, this);
|
|
193
|
+
}
|
|
194
|
+
proto = Object.getPrototypeOf(proto);
|
|
195
|
+
if (!(proto instanceof MongoService))
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
return commandFn();
|
|
199
|
+
};
|
|
388
200
|
try {
|
|
389
|
-
|
|
390
|
-
return this.$interceptor(callback, info, this);
|
|
391
|
-
return callback();
|
|
201
|
+
return await next();
|
|
392
202
|
}
|
|
393
203
|
catch (e) {
|
|
394
|
-
Error.captureStackTrace(e, this.
|
|
395
|
-
await this
|
|
204
|
+
Error.captureStackTrace(e, this._executeCommand);
|
|
205
|
+
await this.onError?.(e, this);
|
|
396
206
|
throw e;
|
|
397
207
|
}
|
|
398
208
|
}
|
|
209
|
+
/**
|
|
210
|
+
* Retrieves the codec for the specified operation.
|
|
211
|
+
*
|
|
212
|
+
* @param operation - The operation to retrieve the encoder for. Valid values are 'create' and 'update'.
|
|
213
|
+
*/
|
|
214
|
+
_getInputCodec(operation) {
|
|
215
|
+
let validator = this._inputCodecs[operation];
|
|
216
|
+
if (validator)
|
|
217
|
+
return validator;
|
|
218
|
+
const options = { projection: '*' };
|
|
219
|
+
if (operation === 'update')
|
|
220
|
+
options.partial = 'deep';
|
|
221
|
+
const dataType = this.dataType;
|
|
222
|
+
validator = dataType.generateCodec('decode', options);
|
|
223
|
+
this._inputCodecs[operation] = validator;
|
|
224
|
+
return validator;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Retrieves the codec.
|
|
228
|
+
*/
|
|
229
|
+
_getOutputCodec(operation) {
|
|
230
|
+
let validator = this._outputCodecs[operation];
|
|
231
|
+
if (validator)
|
|
232
|
+
return validator;
|
|
233
|
+
const options = { projection: '*', partial: 'deep' };
|
|
234
|
+
const dataType = this.dataType;
|
|
235
|
+
validator = dataType.generateCodec('decode', options);
|
|
236
|
+
this._outputCodecs[operation] = validator;
|
|
237
|
+
return validator;
|
|
238
|
+
}
|
|
399
239
|
}
|
|
400
240
|
exports.MongoService = MongoService;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.MongoSingletonService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
4
5
|
const common_1 = require("@opra/common");
|
|
6
|
+
const lodash_omit_1 = tslib_1.__importDefault(require("lodash.omit"));
|
|
5
7
|
const mongodb_1 = require("mongodb");
|
|
6
8
|
const mongo_adapter_js_1 = require("./mongo-adapter.js");
|
|
7
9
|
const mongo_entity_service_js_1 = require("./mongo-entity-service.js");
|
|
@@ -21,12 +23,12 @@ class MongoSingletonService extends mongo_entity_service_js_1.MongoEntityService
|
|
|
21
23
|
*/
|
|
22
24
|
constructor(dataType, options) {
|
|
23
25
|
super(dataType, options);
|
|
24
|
-
this._id =
|
|
26
|
+
this._id = options?._id || new mongodb_1.ObjectId('655608925cad472b75fc6485');
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* Asserts the existence of a resource based on the given options.
|
|
28
30
|
*
|
|
29
|
-
* @param {
|
|
31
|
+
* @param {MongoEntityService.ExistsOptions<T>} [options]
|
|
30
32
|
* @returns {Promise<void>} A Promise that resolves when the resource exists.
|
|
31
33
|
* @throws {ResourceNotAvailableError} If the resource does not exist.
|
|
32
34
|
*/
|
|
@@ -34,128 +36,164 @@ class MongoSingletonService extends mongo_entity_service_js_1.MongoEntityService
|
|
|
34
36
|
if (!(await this.exists(options)))
|
|
35
37
|
throw new common_1.ResourceNotAvailableError(this.getResourceName());
|
|
36
38
|
}
|
|
39
|
+
async create(input, options) {
|
|
40
|
+
const command = {
|
|
41
|
+
crud: 'create',
|
|
42
|
+
method: 'create',
|
|
43
|
+
byId: false,
|
|
44
|
+
input,
|
|
45
|
+
options,
|
|
46
|
+
};
|
|
47
|
+
input._id = this._id;
|
|
48
|
+
return this._executeCommand(command, async () => {
|
|
49
|
+
const r = await this._create(command);
|
|
50
|
+
if (!command.options?.projection)
|
|
51
|
+
return r;
|
|
52
|
+
const findCommand = {
|
|
53
|
+
...command,
|
|
54
|
+
crud: 'read',
|
|
55
|
+
byId: true,
|
|
56
|
+
documentId: r._id,
|
|
57
|
+
options: (0, lodash_omit_1.default)(options, 'filter'),
|
|
58
|
+
};
|
|
59
|
+
const out = await this._findById(findCommand);
|
|
60
|
+
if (out)
|
|
61
|
+
return out;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
37
64
|
/**
|
|
38
65
|
* Creates the document in the database.
|
|
39
66
|
*
|
|
40
|
-
* @param {
|
|
41
|
-
* @param {
|
|
42
|
-
* @
|
|
67
|
+
* @param {DTO<T>} input - The partial input to create the document with.
|
|
68
|
+
* @param {MongoEntityService.CreateOptions} [options] - The options for creating the document.
|
|
69
|
+
* @returns {Promise<T>} A promise that resolves create operation result
|
|
43
70
|
* @throws {Error} Throws an error if an unknown error occurs while creating the document.
|
|
44
71
|
*/
|
|
45
|
-
async
|
|
46
|
-
|
|
47
|
-
const info = {
|
|
72
|
+
async createOnly(input, options) {
|
|
73
|
+
const command = {
|
|
48
74
|
crud: 'create',
|
|
49
|
-
method: '
|
|
75
|
+
method: 'createOnly',
|
|
50
76
|
byId: false,
|
|
51
|
-
documentId: this._id,
|
|
52
77
|
input,
|
|
53
78
|
options,
|
|
54
79
|
};
|
|
55
|
-
|
|
80
|
+
input._id = this._id;
|
|
81
|
+
return this._executeCommand(command, () => this._create(command));
|
|
56
82
|
}
|
|
57
83
|
/**
|
|
58
84
|
* Deletes a record from the database
|
|
59
85
|
*
|
|
60
|
-
* @param {
|
|
86
|
+
* @param {MongoEntityService.DeleteOptions<T>} options - The options for deleting the record
|
|
61
87
|
* @returns {Promise<number>} The number of records deleted
|
|
62
88
|
*/
|
|
63
89
|
async delete(options) {
|
|
64
|
-
const
|
|
90
|
+
const command = {
|
|
65
91
|
crud: 'delete',
|
|
66
92
|
method: 'delete',
|
|
67
93
|
byId: true,
|
|
68
94
|
documentId: this._id,
|
|
69
95
|
options,
|
|
70
96
|
};
|
|
71
|
-
return this.
|
|
72
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
73
|
-
|
|
74
|
-
|
|
97
|
+
return this._executeCommand(command, async () => {
|
|
98
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command), command.options?.filter]);
|
|
99
|
+
command.options = { ...command.options, filter };
|
|
100
|
+
return this._delete(command);
|
|
101
|
+
});
|
|
75
102
|
}
|
|
76
103
|
/**
|
|
77
104
|
* Checks if the document exists in the database.
|
|
78
105
|
*
|
|
106
|
+
* @param {MongoEntityService.FindOneOptions<T>} [options] - The options for finding the document.
|
|
79
107
|
* @return {Promise<boolean>} - A promise that resolves to a boolean value indicating if the document exists.
|
|
80
108
|
*/
|
|
81
109
|
async exists(options) {
|
|
82
|
-
|
|
110
|
+
const command = {
|
|
111
|
+
crud: 'read',
|
|
112
|
+
method: 'exists',
|
|
113
|
+
byId: true,
|
|
114
|
+
documentId: this._id,
|
|
115
|
+
options,
|
|
116
|
+
};
|
|
117
|
+
return this._executeCommand(command, async () => {
|
|
118
|
+
const documentFilter = await this._getDocumentFilter(command);
|
|
119
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([documentFilter, command.options?.filter]);
|
|
120
|
+
const findCommand = command;
|
|
121
|
+
findCommand.options = { ...command.options, filter, projection: ['_id'] };
|
|
122
|
+
return !!(await this._findById(findCommand));
|
|
123
|
+
});
|
|
83
124
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Fetches the document if it exists. Returns undefined if not found.
|
|
86
|
-
*
|
|
87
|
-
* @param {MongoSingletonService.FindOneOptions<T>} [options] - The options for finding the document.
|
|
88
|
-
* @returns {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the found document or undefined if not found.
|
|
89
|
-
*/
|
|
90
125
|
async find(options) {
|
|
91
|
-
const
|
|
126
|
+
const command = {
|
|
92
127
|
crud: 'read',
|
|
93
|
-
method: '
|
|
128
|
+
method: 'findById',
|
|
94
129
|
byId: true,
|
|
95
130
|
documentId: this._id,
|
|
96
131
|
options,
|
|
97
132
|
};
|
|
98
|
-
return this.
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
133
|
+
return this._executeCommand(command, async () => {
|
|
134
|
+
const documentFilter = await this._getDocumentFilter(command);
|
|
135
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([documentFilter, command.options?.filter]);
|
|
136
|
+
command.options = { ...command.options, filter };
|
|
137
|
+
return this._findById(command);
|
|
138
|
+
});
|
|
102
139
|
}
|
|
103
|
-
/**
|
|
104
|
-
* Fetches the document from the Mongo collection service. Throws error if not found.
|
|
105
|
-
*
|
|
106
|
-
* @param {MongoSingletonService.FindOneOptions<T>} options - The options to customize the query.
|
|
107
|
-
* @return {Promise<PartialDTO<T>>} - A promise that resolves to the fetched document.
|
|
108
|
-
* @throws {ResourceNotAvailableError} - If the document is not found in the collection.
|
|
109
|
-
*/
|
|
110
140
|
async get(options) {
|
|
111
141
|
const out = await this.find(options);
|
|
112
142
|
if (!out)
|
|
113
143
|
throw new common_1.ResourceNotAvailableError(this.getResourceName());
|
|
114
144
|
return out;
|
|
115
145
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
* @param {PatchDTO<T>} input - The partial input to update the document.
|
|
120
|
-
* @param {MongoSingletonService.UpdateOptions<T>} [options] - The update options.
|
|
121
|
-
*
|
|
122
|
-
* @return {Promise<number>} - A promise that resolves to the updated document or undefined if not found.
|
|
123
|
-
*/
|
|
124
|
-
async updateOnly(input, options) {
|
|
125
|
-
const info = {
|
|
146
|
+
async update(input, options) {
|
|
147
|
+
const isUpdateFilter = Array.isArray(input) || !!Object.keys(input).find(x => x.startsWith('$'));
|
|
148
|
+
const command = {
|
|
126
149
|
crud: 'update',
|
|
127
150
|
method: 'update',
|
|
128
|
-
byId: true,
|
|
129
151
|
documentId: this._id,
|
|
130
|
-
|
|
152
|
+
byId: true,
|
|
153
|
+
input: isUpdateFilter ? undefined : input,
|
|
154
|
+
inputRaw: isUpdateFilter ? input : undefined,
|
|
131
155
|
options,
|
|
132
156
|
};
|
|
133
|
-
return this.
|
|
134
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
135
|
-
|
|
136
|
-
|
|
157
|
+
return this._executeCommand(command, async () => {
|
|
158
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command), command.options?.filter]);
|
|
159
|
+
command.options = { ...command.options, filter };
|
|
160
|
+
const matchCount = await this._updateOnly(command);
|
|
161
|
+
if (matchCount) {
|
|
162
|
+
const findCommand = {
|
|
163
|
+
...command,
|
|
164
|
+
crud: 'read',
|
|
165
|
+
byId: true,
|
|
166
|
+
documentId: this._id,
|
|
167
|
+
options: (0, lodash_omit_1.default)(options, ['filter', 'sort']),
|
|
168
|
+
};
|
|
169
|
+
const out = await this._findById(findCommand);
|
|
170
|
+
if (out)
|
|
171
|
+
return out;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
137
174
|
}
|
|
138
175
|
/**
|
|
139
176
|
* Updates a document in the MongoDB collection.
|
|
140
177
|
*
|
|
141
178
|
* @param {PatchDTO<T>} input - The partial input to update the document.
|
|
142
|
-
* @param {
|
|
179
|
+
* @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
|
|
143
180
|
*
|
|
144
|
-
* @return {Promise<
|
|
181
|
+
* @return {Promise<number>} - A promise that resolves to the updated document or undefined if not found.
|
|
145
182
|
*/
|
|
146
|
-
async
|
|
147
|
-
const
|
|
183
|
+
async updateOnly(input, options) {
|
|
184
|
+
const command = {
|
|
148
185
|
crud: 'update',
|
|
149
|
-
method: '
|
|
150
|
-
byId: true,
|
|
186
|
+
method: 'updateOnly',
|
|
151
187
|
documentId: this._id,
|
|
188
|
+
byId: true,
|
|
152
189
|
input,
|
|
153
190
|
options,
|
|
154
191
|
};
|
|
155
|
-
return this.
|
|
156
|
-
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(
|
|
157
|
-
|
|
158
|
-
|
|
192
|
+
return this._executeCommand(command, async () => {
|
|
193
|
+
const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command), command.options?.filter]);
|
|
194
|
+
command.options = { ...command.options, filter };
|
|
195
|
+
return this._updateOnly(command);
|
|
196
|
+
});
|
|
159
197
|
}
|
|
160
198
|
}
|
|
161
199
|
exports.MongoSingletonService = MongoSingletonService;
|
|
@@ -10,7 +10,7 @@ export default function prepareProjection(dataType, projection) {
|
|
|
10
10
|
}
|
|
11
11
|
export function prepare(dataType, target, projection) {
|
|
12
12
|
const defaultFields = !projection || !Object.values(projection).find(p => !p.sign);
|
|
13
|
-
const projectionKeys = projection && Object.keys(projection)
|
|
13
|
+
const projectionKeys = projection && Object.keys(projection);
|
|
14
14
|
const projectionKeysSet = new Set(projectionKeys);
|
|
15
15
|
let fieldName;
|
|
16
16
|
let field;
|
|
@@ -24,9 +24,9 @@ export function prepare(dataType, target, projection) {
|
|
|
24
24
|
if (
|
|
25
25
|
/** Ignore if field is omitted */
|
|
26
26
|
p?.sign === '-' ||
|
|
27
|
-
/** Ignore if
|
|
27
|
+
/** Ignore if defaultFields is false and field is not in projection */
|
|
28
28
|
(!defaultFields && !p) ||
|
|
29
|
-
/** Ignore if
|
|
29
|
+
/** Ignore if defaultFields is true and fields is exclusive */
|
|
30
30
|
(defaultFields && field.exclusive && !p)) {
|
|
31
31
|
continue;
|
|
32
32
|
}
|
|
@@ -40,7 +40,7 @@ export function prepare(dataType, target, projection) {
|
|
|
40
40
|
/** Add additional fields */
|
|
41
41
|
if (dataType.additionalFields) {
|
|
42
42
|
for (k of projectionKeysSet.values()) {
|
|
43
|
-
const n =
|
|
43
|
+
const n = projection?.[k];
|
|
44
44
|
if (n?.sign !== '-')
|
|
45
45
|
target[k] = 1;
|
|
46
46
|
}
|
package/esm/index.js
CHANGED