@opra/mongodb 1.0.0-alpha.17 → 1.0.0-alpha.19

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.
@@ -23,20 +23,20 @@ class MongoService extends core_1.ServiceBase {
23
23
  this._outputCodecs = {};
24
24
  this._dataType_ = dataType;
25
25
  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) {
26
+ this.documentFilter = options?.documentFilter;
27
+ this.interceptor = options?.interceptor;
28
+ this.collectionName = options?.collectionName;
29
+ if (!this.collectionName) {
30
30
  if (typeof dataType === 'string')
31
- this.$collectionName = dataType;
31
+ this.collectionName = dataType;
32
32
  if (typeof dataType === 'function') {
33
33
  const metadata = Reflect.getMetadata(common_1.DATATYPE_METADATA, dataType);
34
34
  if (metadata)
35
- this.$collectionName = metadata.name;
35
+ this.collectionName = metadata.name;
36
36
  }
37
37
  }
38
- this.$resourceName = options?.resourceName;
39
- this.$idGenerator = options?.idGenerator;
38
+ this.resourceName = options?.resourceName;
39
+ this.idGenerator = options?.idGenerator;
40
40
  }
41
41
  /**
42
42
  * Retrieves the collection name.
@@ -46,7 +46,7 @@ class MongoService extends core_1.ServiceBase {
46
46
  * @throws {Error} If the collection name is not defined.
47
47
  */
48
48
  getCollectionName() {
49
- const out = typeof this.$collectionName === 'function' ? this.$collectionName(this) : this.$collectionName;
49
+ const out = typeof this.collectionName === 'function' ? this.collectionName(this) : this.collectionName;
50
50
  if (out)
51
51
  return out;
52
52
  throw new Error('collectionName is not defined');
@@ -59,9 +59,7 @@ class MongoService extends core_1.ServiceBase {
59
59
  * @throws {Error} If the resource name is not defined.
60
60
  */
61
61
  getResourceName() {
62
- const out = typeof this.$resourceName === 'function'
63
- ? this.$resourceName(this)
64
- : this.$resourceName || this.getCollectionName();
62
+ const out = typeof this.resourceName === 'function' ? this.resourceName(this) : this.resourceName || this.getCollectionName();
65
63
  if (out)
66
64
  return out;
67
65
  throw new Error('resourceName is not defined');
@@ -370,8 +368,8 @@ class MongoService extends core_1.ServiceBase {
370
368
  * @protected
371
369
  * @returns {MongoAdapter.AnyId} The generated ID.
372
370
  */
373
- _generateId() {
374
- return typeof this.$idGenerator === 'function' ? this.$idGenerator(this) : new mongodb_1.ObjectId();
371
+ _generateId(command) {
372
+ return typeof this.idGenerator === 'function' ? this.idGenerator(command, this) : new mongodb_1.ObjectId();
375
373
  }
376
374
  /**
377
375
  * Retrieves the common filter used for querying documents.
@@ -381,18 +379,29 @@ class MongoService extends core_1.ServiceBase {
381
379
  * @returns {FilterInput | Promise<FilterInput> | undefined} The common filter or a Promise
382
380
  * that resolves to the common filter, or undefined if not available.
383
381
  */
384
- _getDocumentFilter(info) {
385
- return typeof this.$documentFilter === 'function' ? this.$documentFilter(info, this) : this.$documentFilter;
382
+ _getDocumentFilter(command) {
383
+ return typeof this.documentFilter === 'function' ? this.documentFilter(command, this) : this.documentFilter;
386
384
  }
387
- async _intercept(callback, info) {
385
+ async _executeCommand(command, commandFn) {
386
+ let proto;
387
+ const next = async () => {
388
+ proto = proto ? Object.getPrototypeOf(proto) : this;
389
+ while (proto) {
390
+ if (proto.interceptor) {
391
+ return await proto.interceptor.call(this, next, command, this);
392
+ }
393
+ proto = Object.getPrototypeOf(proto);
394
+ if (!(proto instanceof MongoService))
395
+ break;
396
+ }
397
+ return commandFn();
398
+ };
388
399
  try {
389
- if (this.$interceptor)
390
- return this.$interceptor(callback, info, this);
391
- return callback();
400
+ return await next();
392
401
  }
393
402
  catch (e) {
394
- Error.captureStackTrace(e, this._intercept);
395
- await this.$onError?.(e, this);
403
+ Error.captureStackTrace(e, this._executeCommand);
404
+ await this.onError?.(e, this);
396
405
  throw e;
397
406
  }
398
407
  }
@@ -26,7 +26,7 @@ class MongoSingletonService extends mongo_entity_service_js_1.MongoEntityService
26
26
  /**
27
27
  * Asserts the existence of a resource based on the given options.
28
28
  *
29
- * @param {MongoSingletonService.ExistsOptions<T>} [options]
29
+ * @param {MongoEntityService.ExistsOptions<T>} [options]
30
30
  * @returns {Promise<void>} A Promise that resolves when the resource exists.
31
31
  * @throws {ResourceNotAvailableError} If the resource does not exist.
32
32
  */
@@ -38,72 +38,88 @@ class MongoSingletonService extends mongo_entity_service_js_1.MongoEntityService
38
38
  * Creates the document in the database.
39
39
  *
40
40
  * @param {PartialDTO<T>} input - The partial input to create the document with.
41
- * @param {MongoSingletonService.CreateOptions} [options] - The options for creating the document.
41
+ * @param {MongoEntityService.CreateOptions} [options] - The options for creating the document.
42
42
  * @return {Promise<PartialDTO<T>>} A promise that resolves to the partial output of the created document.
43
43
  * @throws {Error} Throws an error if an unknown error occurs while creating the document.
44
44
  */
45
45
  async create(input, options) {
46
- input._id = this._id;
47
- const info = {
46
+ const command = {
48
47
  crud: 'create',
49
48
  method: 'create',
50
49
  byId: false,
51
- documentId: this._id,
52
50
  input,
53
51
  options,
54
52
  };
55
- return this._intercept(() => this._create(input, options), info);
53
+ input._id = this._id;
54
+ return this._executeCommand(command, () => this._create(command));
56
55
  }
57
56
  /**
58
57
  * Deletes a record from the database
59
58
  *
60
- * @param {MongoSingletonService.DeleteOptions<T>} options - The options for deleting the record
59
+ * @param {MongoEntityService.DeleteOptions<T>} options - The options for deleting the record
61
60
  * @returns {Promise<number>} The number of records deleted
62
61
  */
63
62
  async delete(options) {
64
- const info = {
63
+ const command = {
65
64
  crud: 'delete',
66
65
  method: 'delete',
67
66
  byId: true,
68
67
  documentId: this._id,
69
68
  options,
70
69
  };
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);
70
+ return this._executeCommand(command, async () => {
71
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command), command.options?.filter]);
72
+ command.options = { ...command.options, filter };
73
+ return this._delete(command);
74
+ });
75
75
  }
76
76
  /**
77
77
  * Checks if the document exists in the database.
78
78
  *
79
+ * @param {MongoEntityService.FindOneOptions<T>} [options] - The options for finding the document.
79
80
  * @return {Promise<boolean>} - A promise that resolves to a boolean value indicating if the document exists.
80
81
  */
81
82
  async exists(options) {
82
- return !!(await this.find({ ...options, projection: ['_id'], skip: undefined }));
83
+ const command = {
84
+ crud: 'read',
85
+ method: 'exists',
86
+ byId: true,
87
+ documentId: this._id,
88
+ options,
89
+ };
90
+ return this._executeCommand(command, async () => {
91
+ const documentFilter = await this._getDocumentFilter(command);
92
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([documentFilter, command.options?.filter]);
93
+ const findCommand = command;
94
+ findCommand.options = { ...command.options, filter, projection: ['_id'] };
95
+ return !!(await this._findById(findCommand));
96
+ });
83
97
  }
84
98
  /**
85
99
  * Fetches the document if it exists. Returns undefined if not found.
86
100
  *
87
- * @param {MongoSingletonService.FindOneOptions<T>} [options] - The options for finding the document.
101
+ * @param {MongoEntityService.FindOneOptions<T>} [options] - The options for finding the document.
88
102
  * @returns {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the found document or undefined if not found.
89
103
  */
90
104
  async find(options) {
91
- const info = {
105
+ const command = {
92
106
  crud: 'read',
93
- method: 'findOne',
107
+ method: 'findById',
94
108
  byId: true,
95
109
  documentId: this._id,
96
110
  options,
97
111
  };
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);
112
+ return this._executeCommand(command, async () => {
113
+ const documentFilter = await this._getDocumentFilter(command);
114
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([documentFilter, command.options?.filter]);
115
+ command.options = { ...command.options, filter };
116
+ return this._findById(command);
117
+ });
102
118
  }
103
119
  /**
104
120
  * Fetches the document from the Mongo collection service. Throws error if not found.
105
121
  *
106
- * @param {MongoSingletonService.FindOneOptions<T>} options - The options to customize the query.
122
+ * @param {MongoEntityService.FindOneOptions<T>} options - The options to customize the query.
107
123
  * @return {Promise<PartialDTO<T>>} - A promise that resolves to the fetched document.
108
124
  * @throws {ResourceNotAvailableError} - If the document is not found in the collection.
109
125
  */
@@ -117,45 +133,49 @@ class MongoSingletonService extends mongo_entity_service_js_1.MongoEntityService
117
133
  * Updates a document in the MongoDB collection.
118
134
  *
119
135
  * @param {PatchDTO<T>} input - The partial input to update the document.
120
- * @param {MongoSingletonService.UpdateOptions<T>} [options] - The update options.
136
+ * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
121
137
  *
122
- * @return {Promise<number>} - A promise that resolves to the updated document or undefined if not found.
138
+ * @return {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the updated document or undefined if not found.
123
139
  */
124
- async updateOnly(input, options) {
125
- const info = {
140
+ async update(input, options) {
141
+ const isUpdateFilter = Array.isArray(input) || !!Object.keys(input).find(x => x.startsWith('$'));
142
+ const command = {
126
143
  crud: 'update',
127
144
  method: 'update',
128
- byId: true,
129
145
  documentId: this._id,
130
- input,
146
+ byId: true,
147
+ input: isUpdateFilter ? undefined : input,
148
+ inputRaw: isUpdateFilter ? input : undefined,
131
149
  options,
132
150
  };
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);
151
+ return this._executeCommand(command, async () => {
152
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command), command.options?.filter]);
153
+ command.options = { ...command.options, filter };
154
+ return this._update(command);
155
+ });
137
156
  }
138
157
  /**
139
158
  * Updates a document in the MongoDB collection.
140
159
  *
141
160
  * @param {PatchDTO<T>} input - The partial input to update the document.
142
- * @param {MongoSingletonService.UpdateOptions<T>} [options] - The update options.
161
+ * @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
143
162
  *
144
- * @return {Promise<PartialDTO<T> | undefined>} - A promise that resolves to the updated document or undefined if not found.
163
+ * @return {Promise<number>} - A promise that resolves to the updated document or undefined if not found.
145
164
  */
146
- async update(input, options) {
147
- const info = {
165
+ async updateOnly(input, options) {
166
+ const command = {
148
167
  crud: 'update',
149
- method: 'update',
150
- byId: true,
168
+ method: 'updateOnly',
151
169
  documentId: this._id,
170
+ byId: true,
152
171
  input,
153
172
  options,
154
173
  };
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);
174
+ return this._executeCommand(command, async () => {
175
+ const filter = mongo_adapter_js_1.MongoAdapter.prepareFilter([await this._getDocumentFilter(command), command.options?.filter]);
176
+ command.options = { ...command.options, filter };
177
+ return this._updateOnly(command);
178
+ });
159
179
  }
160
180
  }
161
181
  exports.MongoSingletonService = MongoSingletonService;