@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.
@@ -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.$documentFilter = this.$documentFilter || options?.documentFilter;
27
- this.$interceptor = this.$interceptor || options?.interceptor;
28
- this.$collectionName = options?.collectionName;
29
- if (!this.$collectionName) {
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.$collectionName = dataType;
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.$collectionName = metadata.name;
37
+ this.collectionName = metadata.name;
36
38
  }
37
39
  }
38
- this.$resourceName = options?.resourceName;
39
- this.$idGenerator = options?.idGenerator;
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.$collectionName === 'function' ? this.$collectionName(this) : this.$collectionName;
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 collection name is not defined.
73
+ * @throws {Error} If the resource name is not defined.
60
74
  */
61
75
  getResourceName() {
62
- const out = typeof this.$resourceName === 'function'
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.$idGenerator === 'function' ? this.$idGenerator(this) : new mongodb_1.ObjectId();
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(info) {
385
- return typeof this.$documentFilter === 'function' ? this.$documentFilter(info, this) : this.$documentFilter;
386
- }
387
- async _intercept(callback, info) {
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
- if (this.$interceptor)
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._intercept);
395
- await this.$onError?.(e, 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 = this._id || options?._id || new mongodb_1.ObjectId('655608925cad472b75fc6485');
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 {MongoSingletonService.ExistsOptions<T>} [options]
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 {PartialDTO<T>} input - The partial input to create the document with.
41
- * @param {MongoSingletonService.CreateOptions} [options] - The options for creating the document.
42
- * @return {Promise<PartialDTO<T>>} A promise that resolves to the partial output of the created document.
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 create(input, options) {
46
- input._id = this._id;
47
- const info = {
72
+ async createOnly(input, options) {
73
+ const command = {
48
74
  crud: 'create',
49
- method: 'create',
75
+ method: 'createOnly',
50
76
  byId: false,
51
- documentId: this._id,
52
77
  input,
53
78
  options,
54
79
  };
55
- return this._intercept(() => this._create(input, options), info);
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 {MongoSingletonService.DeleteOptions<T>} options - The options for deleting the record
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 info = {
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._intercept(async () => {
72
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info), options?.filter]);
73
- return this._delete(this._id, { ...options, filter });
74
- }, info);
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
- return !!(await this.find({ ...options, projection: ['_id'], skip: undefined }));
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 info = {
126
+ const command = {
92
127
  crud: 'read',
93
- method: 'findOne',
128
+ method: 'findById',
94
129
  byId: true,
95
130
  documentId: this._id,
96
131
  options,
97
132
  };
98
- return this._intercept(async () => {
99
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info), options?.filter]);
100
- return this._findById(this._id, { ...options, filter });
101
- }, info);
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
- * Updates a document in the MongoDB collection.
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
- input,
152
+ byId: true,
153
+ input: isUpdateFilter ? undefined : input,
154
+ inputRaw: isUpdateFilter ? input : undefined,
131
155
  options,
132
156
  };
133
- return this._intercept(async () => {
134
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info), options?.filter]);
135
- return this._updateOnly(this._id, input, { ...options, filter });
136
- }, info);
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 {MongoSingletonService.UpdateOptions<T>} [options] - The update options.
179
+ * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
143
180
  *
144
- * @return {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the updated document or undefined if not found.
181
+ * @return {Promise<number>} - A promise that resolves to the updated document or undefined if not found.
145
182
  */
146
- async update(input, options) {
147
- const info = {
183
+ async updateOnly(input, options) {
184
+ const command = {
148
185
  crud: 'update',
149
- method: 'update',
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._intercept(async () => {
156
- const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(info), options?.filter]);
157
- return this._update(this._id, input, { ...options, filter });
158
- }, info);
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).map(x => x.toLowerCase());
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 default fields and field is not in projection */
27
+ /** Ignore if defaultFields is false and field is not in projection */
28
28
  (!defaultFields && !p) ||
29
- /** Ignore if default fields enabled and fields is exclusive */
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 = projectionKeysSet[k];
43
+ const n = projection?.[k];
44
44
  if (n?.sign !== '-')
45
45
  target[k] = 1;
46
46
  }
package/esm/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './mongo-adapter.js';
2
2
  export * from './mongo-collection-service.js';
3
+ export * from './mongo-entity-service.js';
3
4
  export * from './mongo-nested-service.js';
4
5
  export * from './mongo-service.js';
5
6
  export * from './mongo-singleton-service.js';