@opra/mongodb 1.0.0-beta.3 → 1.0.0-beta.4
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/mongo-entity-service.js +13 -12
- package/cjs/mongo-nested-service.js +7 -7
- package/cjs/mongo-service.js +39 -23
- package/cjs/mongo-singleton-service.js +1 -1
- package/esm/mongo-entity-service.js +13 -12
- package/esm/mongo-nested-service.js +7 -7
- package/esm/mongo-service.js +39 -23
- package/esm/mongo-singleton-service.js +1 -1
- package/package.json +4 -4
- package/types/mongo-adapter.d.ts +1 -2
- package/types/mongo-service.d.ts +3 -3
- package/types/mongo-singleton-service.d.ts +3 -3
|
@@ -39,7 +39,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
39
39
|
const collection = await this.getCollection(db);
|
|
40
40
|
const r = await collection.insertOne(document, {
|
|
41
41
|
...options,
|
|
42
|
-
session: options?.session
|
|
42
|
+
session: options?.session ?? this.getSession(),
|
|
43
43
|
});
|
|
44
44
|
/* istanbul ignore next */
|
|
45
45
|
if (!r.insertedId) {
|
|
@@ -61,7 +61,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
61
61
|
return ((await collection.countDocuments(filter || {}, {
|
|
62
62
|
...options,
|
|
63
63
|
limit: undefined,
|
|
64
|
-
session: options?.session
|
|
64
|
+
session: options?.session ?? this.getSession(),
|
|
65
65
|
})) || 0);
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
@@ -79,9 +79,10 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
79
79
|
]);
|
|
80
80
|
const db = this.getDatabase();
|
|
81
81
|
const collection = await this.getCollection(db);
|
|
82
|
+
const session = options?.session ?? this.getSession();
|
|
82
83
|
return (await collection.deleteOne(filter || {}, {
|
|
83
84
|
...options,
|
|
84
|
-
session
|
|
85
|
+
session,
|
|
85
86
|
})).deletedCount;
|
|
86
87
|
}
|
|
87
88
|
/**
|
|
@@ -97,7 +98,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
97
98
|
const collection = await this.getCollection(db);
|
|
98
99
|
return (await collection.deleteMany(filter || {}, {
|
|
99
100
|
...options,
|
|
100
|
-
session: options?.session
|
|
101
|
+
session: options?.session ?? this.getSession(),
|
|
101
102
|
})).deletedCount;
|
|
102
103
|
}
|
|
103
104
|
/**
|
|
@@ -113,7 +114,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
113
114
|
const collection = await this.getCollection(db);
|
|
114
115
|
return await collection.distinct(field, filter || {}, {
|
|
115
116
|
...options,
|
|
116
|
-
session: options?.session
|
|
117
|
+
session: options?.session ?? this.getSession(),
|
|
117
118
|
});
|
|
118
119
|
}
|
|
119
120
|
/**
|
|
@@ -132,7 +133,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
132
133
|
const collection = await this.getCollection(db);
|
|
133
134
|
const out = await collection.findOne(filter || {}, {
|
|
134
135
|
...(0, lodash_omit_1.default)(options, 'filter'),
|
|
135
|
-
session: options?.session
|
|
136
|
+
session: options?.session ?? this.getSession(),
|
|
136
137
|
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
137
138
|
limit: undefined,
|
|
138
139
|
skip: undefined,
|
|
@@ -155,7 +156,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
155
156
|
const collection = await this.getCollection(db);
|
|
156
157
|
const out = await collection.findOne(filter || {}, {
|
|
157
158
|
...(0, lodash_omit_1.default)(options, 'filter'),
|
|
158
|
-
session: options?.session
|
|
159
|
+
session: options?.session ?? this.getSession(),
|
|
159
160
|
sort: options?.sort ? mongo_adapter_js_1.MongoAdapter.prepareSort(options.sort) : undefined,
|
|
160
161
|
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
161
162
|
limit: undefined,
|
|
@@ -195,7 +196,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
195
196
|
const collection = await this.getCollection(db);
|
|
196
197
|
const cursor = collection.aggregate(stages, {
|
|
197
198
|
...(0, lodash_omit_1.default)(options, ['projection', 'sort', 'skip', 'limit', 'filter']),
|
|
198
|
-
session: options?.session
|
|
199
|
+
session: options?.session ?? this.getSession(),
|
|
199
200
|
});
|
|
200
201
|
/** Execute db command */
|
|
201
202
|
try {
|
|
@@ -253,7 +254,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
253
254
|
const collection = await this.getCollection(db);
|
|
254
255
|
const cursor = collection.aggregate(stages, {
|
|
255
256
|
...(0, lodash_omit_1.default)(options, ['projection', 'sort', 'skip', 'limit', 'filter']),
|
|
256
|
-
session: options?.session
|
|
257
|
+
session: options?.session ?? this.getSession(),
|
|
257
258
|
});
|
|
258
259
|
/** Fetch the cursor and decode the result objects */
|
|
259
260
|
try {
|
|
@@ -301,7 +302,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
301
302
|
...options,
|
|
302
303
|
returnDocument: 'after',
|
|
303
304
|
includeResultMetadata: false,
|
|
304
|
-
session: options?.session
|
|
305
|
+
session: options?.session ?? this.getSession(),
|
|
305
306
|
projection: mongo_adapter_js_1.MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
306
307
|
});
|
|
307
308
|
const outputCodec = this._getOutputCodec('update');
|
|
@@ -339,7 +340,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
339
340
|
const collection = await this.getCollection(db);
|
|
340
341
|
return (await collection.updateOne(filter || {}, update, {
|
|
341
342
|
...options,
|
|
342
|
-
session: options?.session
|
|
343
|
+
session: options?.session ?? this.getSession(),
|
|
343
344
|
upsert: undefined,
|
|
344
345
|
})).matchedCount;
|
|
345
346
|
}
|
|
@@ -371,7 +372,7 @@ class MongoEntityService extends mongo_service_js_1.MongoService {
|
|
|
371
372
|
const collection = await this.getCollection(db);
|
|
372
373
|
return (await collection.updateMany(filter || {}, update, {
|
|
373
374
|
...(0, lodash_omit_1.default)(options, 'filter'),
|
|
374
|
-
session: options?.session
|
|
375
|
+
session: options?.session ?? this.getSession(),
|
|
375
376
|
upsert: false,
|
|
376
377
|
})).matchedCount;
|
|
377
378
|
}
|
|
@@ -123,7 +123,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
|
|
|
123
123
|
};
|
|
124
124
|
const r = await collection.updateOne(docFilter, update, {
|
|
125
125
|
...options,
|
|
126
|
-
session: options?.session
|
|
126
|
+
session: options?.session ?? this.getSession(),
|
|
127
127
|
upsert: undefined,
|
|
128
128
|
});
|
|
129
129
|
if (!r.matchedCount) {
|
|
@@ -173,7 +173,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
|
|
|
173
173
|
const collection = await this.getCollection(db);
|
|
174
174
|
const cursor = collection.aggregate(stages, {
|
|
175
175
|
...(0, lodash_omit_1.default)(options, ['documentFilter', 'nestedFilter', 'projection', 'sort', 'skip', 'limit', 'filter', 'count']),
|
|
176
|
-
session: options?.session
|
|
176
|
+
session: options?.session ?? this.getSession(),
|
|
177
177
|
});
|
|
178
178
|
try {
|
|
179
179
|
const n = await cursor.next();
|
|
@@ -223,7 +223,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
|
|
|
223
223
|
const collection = await this.getCollection(db);
|
|
224
224
|
const r = await collection.updateOne(matchFilter, update, {
|
|
225
225
|
...options,
|
|
226
|
-
session: options?.session
|
|
226
|
+
session: options?.session ?? this.getSession(),
|
|
227
227
|
upsert: undefined,
|
|
228
228
|
});
|
|
229
229
|
return r.modifiedCount ? 1 : 0;
|
|
@@ -273,7 +273,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
|
|
|
273
273
|
const collection = await this.getCollection(db);
|
|
274
274
|
await collection.updateOne(matchFilter, update, {
|
|
275
275
|
...options,
|
|
276
|
-
session: options?.session
|
|
276
|
+
session: options?.session ?? this.getSession(),
|
|
277
277
|
upsert: undefined,
|
|
278
278
|
});
|
|
279
279
|
return matchCount;
|
|
@@ -447,7 +447,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
|
|
|
447
447
|
const collection = await this.getCollection(db);
|
|
448
448
|
const cursor = collection.aggregate(stages, {
|
|
449
449
|
...(0, lodash_omit_1.default)(options, ['documentFilter', 'nestedFilter', 'projection', 'sort', 'skip', 'limit', 'filter', 'count']),
|
|
450
|
-
session: options?.session
|
|
450
|
+
session: options?.session ?? this.getSession(),
|
|
451
451
|
});
|
|
452
452
|
try {
|
|
453
453
|
const outputCodec = this._getOutputCodec('find');
|
|
@@ -518,7 +518,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
|
|
|
518
518
|
const collection = await this.getCollection(db);
|
|
519
519
|
const cursor = collection.aggregate(stages, {
|
|
520
520
|
...(0, lodash_omit_1.default)(options, ['documentFilter', 'nestedFilter', 'projection', 'sort', 'skip', 'limit', 'filter', 'count']),
|
|
521
|
-
session: options?.session
|
|
521
|
+
session: options?.session ?? this.getSession(),
|
|
522
522
|
});
|
|
523
523
|
try {
|
|
524
524
|
const facetResult = await cursor.toArray();
|
|
@@ -677,7 +677,7 @@ class MongoNestedService extends mongo_service_js_1.MongoService {
|
|
|
677
677
|
const collection = await this.getCollection(db);
|
|
678
678
|
await collection.updateOne(matchFilter, update, {
|
|
679
679
|
...options,
|
|
680
|
-
session: options?.session
|
|
680
|
+
session: options?.session ?? this.getSession(),
|
|
681
681
|
upsert: undefined,
|
|
682
682
|
});
|
|
683
683
|
return count;
|
package/cjs/mongo-service.js
CHANGED
|
@@ -5,6 +5,7 @@ const common_1 = require("@opra/common");
|
|
|
5
5
|
const core_1 = require("@opra/core");
|
|
6
6
|
const mongodb_1 = require("mongodb");
|
|
7
7
|
const mongo_adapter_js_1 = require("./mongo-adapter.js");
|
|
8
|
+
const transactionKey = Symbol.for('transaction');
|
|
8
9
|
/**
|
|
9
10
|
* Class representing a MongoDB service for interacting with a collection.
|
|
10
11
|
* @extends ServiceBase
|
|
@@ -95,38 +96,43 @@ class MongoService extends core_1.ServiceBase {
|
|
|
95
96
|
* @param [options] - Optional options for the transaction.
|
|
96
97
|
*/
|
|
97
98
|
async withTransaction(callback, options) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
99
|
+
const ctx = this.context;
|
|
100
|
+
let closeSessionOnFinish = false;
|
|
101
|
+
let transaction = ctx[transactionKey];
|
|
102
|
+
let session;
|
|
103
|
+
if (transaction) {
|
|
104
|
+
session = transaction.session;
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
const db = this.getDatabase();
|
|
108
|
+
const client = db.client;
|
|
109
|
+
session = client.startSession();
|
|
110
|
+
closeSessionOnFinish = true;
|
|
111
|
+
transaction = {
|
|
112
|
+
db,
|
|
113
|
+
session,
|
|
114
|
+
};
|
|
115
|
+
ctx[transactionKey] = transaction;
|
|
116
|
+
}
|
|
108
117
|
const oldInTransaction = session.inTransaction();
|
|
109
118
|
try {
|
|
110
119
|
if (!oldInTransaction)
|
|
111
120
|
session.startTransaction(options);
|
|
112
|
-
const out = await callback(session);
|
|
113
|
-
if (!oldInTransaction)
|
|
121
|
+
const out = await callback(session, this);
|
|
122
|
+
if (!oldInTransaction && session.inTransaction())
|
|
114
123
|
await session.commitTransaction();
|
|
115
124
|
return out;
|
|
116
125
|
}
|
|
117
126
|
catch (e) {
|
|
118
|
-
if (!oldInTransaction)
|
|
127
|
+
if (!oldInTransaction && session.inTransaction())
|
|
119
128
|
await session.abortTransaction();
|
|
120
129
|
throw e;
|
|
121
130
|
}
|
|
122
131
|
finally {
|
|
123
|
-
|
|
124
|
-
if (
|
|
125
|
-
this.session = oldSessionGetter;
|
|
126
|
-
else
|
|
127
|
-
delete this.session;
|
|
128
|
-
if (!oldInTransaction)
|
|
132
|
+
delete ctx[transactionKey];
|
|
133
|
+
if (closeSessionOnFinish) {
|
|
129
134
|
await session.endSession();
|
|
135
|
+
}
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
138
|
/**
|
|
@@ -137,10 +143,14 @@ class MongoService extends core_1.ServiceBase {
|
|
|
137
143
|
* @throws {Error} If the context or database is not set.
|
|
138
144
|
*/
|
|
139
145
|
getDatabase() {
|
|
146
|
+
const ctx = this.context;
|
|
147
|
+
const transaction = ctx[transactionKey];
|
|
148
|
+
if (transaction)
|
|
149
|
+
return transaction.db;
|
|
140
150
|
const db = typeof this.db === 'function' ? this.db(this) : this.db;
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
|
|
151
|
+
if (db)
|
|
152
|
+
return db;
|
|
153
|
+
throw new Error(`Database not set!`);
|
|
144
154
|
}
|
|
145
155
|
/**
|
|
146
156
|
* Retrieves the database session.
|
|
@@ -150,7 +160,13 @@ class MongoService extends core_1.ServiceBase {
|
|
|
150
160
|
* @throws {Error} If the context or database is not set.
|
|
151
161
|
*/
|
|
152
162
|
getSession() {
|
|
153
|
-
|
|
163
|
+
const ctx = this.context;
|
|
164
|
+
const transaction = ctx[transactionKey];
|
|
165
|
+
if (transaction)
|
|
166
|
+
return transaction.session;
|
|
167
|
+
const session = typeof this.session === 'function' ? this.session(this) : this.session;
|
|
168
|
+
if (session)
|
|
169
|
+
return session;
|
|
154
170
|
}
|
|
155
171
|
/**
|
|
156
172
|
* Retrieves a MongoDB collection from the given database.
|
|
@@ -173,7 +173,7 @@ class MongoSingletonService extends mongo_entity_service_js_1.MongoEntityService
|
|
|
173
173
|
});
|
|
174
174
|
}
|
|
175
175
|
/**
|
|
176
|
-
* Updates a document in the MongoDB collection
|
|
176
|
+
* Updates a document in the MongoDB collection
|
|
177
177
|
*
|
|
178
178
|
* @param {PatchDTO<T>} input - The partial input to update the document.
|
|
179
179
|
* @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
|
|
@@ -35,7 +35,7 @@ export class MongoEntityService extends MongoService {
|
|
|
35
35
|
const collection = await this.getCollection(db);
|
|
36
36
|
const r = await collection.insertOne(document, {
|
|
37
37
|
...options,
|
|
38
|
-
session: options?.session
|
|
38
|
+
session: options?.session ?? this.getSession(),
|
|
39
39
|
});
|
|
40
40
|
/* istanbul ignore next */
|
|
41
41
|
if (!r.insertedId) {
|
|
@@ -57,7 +57,7 @@ export class MongoEntityService extends MongoService {
|
|
|
57
57
|
return ((await collection.countDocuments(filter || {}, {
|
|
58
58
|
...options,
|
|
59
59
|
limit: undefined,
|
|
60
|
-
session: options?.session
|
|
60
|
+
session: options?.session ?? this.getSession(),
|
|
61
61
|
})) || 0);
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
@@ -75,9 +75,10 @@ export class MongoEntityService extends MongoService {
|
|
|
75
75
|
]);
|
|
76
76
|
const db = this.getDatabase();
|
|
77
77
|
const collection = await this.getCollection(db);
|
|
78
|
+
const session = options?.session ?? this.getSession();
|
|
78
79
|
return (await collection.deleteOne(filter || {}, {
|
|
79
80
|
...options,
|
|
80
|
-
session
|
|
81
|
+
session,
|
|
81
82
|
})).deletedCount;
|
|
82
83
|
}
|
|
83
84
|
/**
|
|
@@ -93,7 +94,7 @@ export class MongoEntityService extends MongoService {
|
|
|
93
94
|
const collection = await this.getCollection(db);
|
|
94
95
|
return (await collection.deleteMany(filter || {}, {
|
|
95
96
|
...options,
|
|
96
|
-
session: options?.session
|
|
97
|
+
session: options?.session ?? this.getSession(),
|
|
97
98
|
})).deletedCount;
|
|
98
99
|
}
|
|
99
100
|
/**
|
|
@@ -109,7 +110,7 @@ export class MongoEntityService extends MongoService {
|
|
|
109
110
|
const collection = await this.getCollection(db);
|
|
110
111
|
return await collection.distinct(field, filter || {}, {
|
|
111
112
|
...options,
|
|
112
|
-
session: options?.session
|
|
113
|
+
session: options?.session ?? this.getSession(),
|
|
113
114
|
});
|
|
114
115
|
}
|
|
115
116
|
/**
|
|
@@ -128,7 +129,7 @@ export class MongoEntityService extends MongoService {
|
|
|
128
129
|
const collection = await this.getCollection(db);
|
|
129
130
|
const out = await collection.findOne(filter || {}, {
|
|
130
131
|
...omit(options, 'filter'),
|
|
131
|
-
session: options?.session
|
|
132
|
+
session: options?.session ?? this.getSession(),
|
|
132
133
|
projection: MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
133
134
|
limit: undefined,
|
|
134
135
|
skip: undefined,
|
|
@@ -151,7 +152,7 @@ export class MongoEntityService extends MongoService {
|
|
|
151
152
|
const collection = await this.getCollection(db);
|
|
152
153
|
const out = await collection.findOne(filter || {}, {
|
|
153
154
|
...omit(options, 'filter'),
|
|
154
|
-
session: options?.session
|
|
155
|
+
session: options?.session ?? this.getSession(),
|
|
155
156
|
sort: options?.sort ? MongoAdapter.prepareSort(options.sort) : undefined,
|
|
156
157
|
projection: MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
157
158
|
limit: undefined,
|
|
@@ -191,7 +192,7 @@ export class MongoEntityService extends MongoService {
|
|
|
191
192
|
const collection = await this.getCollection(db);
|
|
192
193
|
const cursor = collection.aggregate(stages, {
|
|
193
194
|
...omit(options, ['projection', 'sort', 'skip', 'limit', 'filter']),
|
|
194
|
-
session: options?.session
|
|
195
|
+
session: options?.session ?? this.getSession(),
|
|
195
196
|
});
|
|
196
197
|
/** Execute db command */
|
|
197
198
|
try {
|
|
@@ -249,7 +250,7 @@ export class MongoEntityService extends MongoService {
|
|
|
249
250
|
const collection = await this.getCollection(db);
|
|
250
251
|
const cursor = collection.aggregate(stages, {
|
|
251
252
|
...omit(options, ['projection', 'sort', 'skip', 'limit', 'filter']),
|
|
252
|
-
session: options?.session
|
|
253
|
+
session: options?.session ?? this.getSession(),
|
|
253
254
|
});
|
|
254
255
|
/** Fetch the cursor and decode the result objects */
|
|
255
256
|
try {
|
|
@@ -297,7 +298,7 @@ export class MongoEntityService extends MongoService {
|
|
|
297
298
|
...options,
|
|
298
299
|
returnDocument: 'after',
|
|
299
300
|
includeResultMetadata: false,
|
|
300
|
-
session: options?.session
|
|
301
|
+
session: options?.session ?? this.getSession(),
|
|
301
302
|
projection: MongoAdapter.prepareProjection(this.dataType, options?.projection),
|
|
302
303
|
});
|
|
303
304
|
const outputCodec = this._getOutputCodec('update');
|
|
@@ -335,7 +336,7 @@ export class MongoEntityService extends MongoService {
|
|
|
335
336
|
const collection = await this.getCollection(db);
|
|
336
337
|
return (await collection.updateOne(filter || {}, update, {
|
|
337
338
|
...options,
|
|
338
|
-
session: options?.session
|
|
339
|
+
session: options?.session ?? this.getSession(),
|
|
339
340
|
upsert: undefined,
|
|
340
341
|
})).matchedCount;
|
|
341
342
|
}
|
|
@@ -367,7 +368,7 @@ export class MongoEntityService extends MongoService {
|
|
|
367
368
|
const collection = await this.getCollection(db);
|
|
368
369
|
return (await collection.updateMany(filter || {}, update, {
|
|
369
370
|
...omit(options, 'filter'),
|
|
370
|
-
session: options?.session
|
|
371
|
+
session: options?.session ?? this.getSession(),
|
|
371
372
|
upsert: false,
|
|
372
373
|
})).matchedCount;
|
|
373
374
|
}
|
|
@@ -119,7 +119,7 @@ export class MongoNestedService extends MongoService {
|
|
|
119
119
|
};
|
|
120
120
|
const r = await collection.updateOne(docFilter, update, {
|
|
121
121
|
...options,
|
|
122
|
-
session: options?.session
|
|
122
|
+
session: options?.session ?? this.getSession(),
|
|
123
123
|
upsert: undefined,
|
|
124
124
|
});
|
|
125
125
|
if (!r.matchedCount) {
|
|
@@ -169,7 +169,7 @@ export class MongoNestedService extends MongoService {
|
|
|
169
169
|
const collection = await this.getCollection(db);
|
|
170
170
|
const cursor = collection.aggregate(stages, {
|
|
171
171
|
...omit(options, ['documentFilter', 'nestedFilter', 'projection', 'sort', 'skip', 'limit', 'filter', 'count']),
|
|
172
|
-
session: options?.session
|
|
172
|
+
session: options?.session ?? this.getSession(),
|
|
173
173
|
});
|
|
174
174
|
try {
|
|
175
175
|
const n = await cursor.next();
|
|
@@ -219,7 +219,7 @@ export class MongoNestedService extends MongoService {
|
|
|
219
219
|
const collection = await this.getCollection(db);
|
|
220
220
|
const r = await collection.updateOne(matchFilter, update, {
|
|
221
221
|
...options,
|
|
222
|
-
session: options?.session
|
|
222
|
+
session: options?.session ?? this.getSession(),
|
|
223
223
|
upsert: undefined,
|
|
224
224
|
});
|
|
225
225
|
return r.modifiedCount ? 1 : 0;
|
|
@@ -269,7 +269,7 @@ export class MongoNestedService extends MongoService {
|
|
|
269
269
|
const collection = await this.getCollection(db);
|
|
270
270
|
await collection.updateOne(matchFilter, update, {
|
|
271
271
|
...options,
|
|
272
|
-
session: options?.session
|
|
272
|
+
session: options?.session ?? this.getSession(),
|
|
273
273
|
upsert: undefined,
|
|
274
274
|
});
|
|
275
275
|
return matchCount;
|
|
@@ -443,7 +443,7 @@ export class MongoNestedService extends MongoService {
|
|
|
443
443
|
const collection = await this.getCollection(db);
|
|
444
444
|
const cursor = collection.aggregate(stages, {
|
|
445
445
|
...omit(options, ['documentFilter', 'nestedFilter', 'projection', 'sort', 'skip', 'limit', 'filter', 'count']),
|
|
446
|
-
session: options?.session
|
|
446
|
+
session: options?.session ?? this.getSession(),
|
|
447
447
|
});
|
|
448
448
|
try {
|
|
449
449
|
const outputCodec = this._getOutputCodec('find');
|
|
@@ -514,7 +514,7 @@ export class MongoNestedService extends MongoService {
|
|
|
514
514
|
const collection = await this.getCollection(db);
|
|
515
515
|
const cursor = collection.aggregate(stages, {
|
|
516
516
|
...omit(options, ['documentFilter', 'nestedFilter', 'projection', 'sort', 'skip', 'limit', 'filter', 'count']),
|
|
517
|
-
session: options?.session
|
|
517
|
+
session: options?.session ?? this.getSession(),
|
|
518
518
|
});
|
|
519
519
|
try {
|
|
520
520
|
const facetResult = await cursor.toArray();
|
|
@@ -673,7 +673,7 @@ export class MongoNestedService extends MongoService {
|
|
|
673
673
|
const collection = await this.getCollection(db);
|
|
674
674
|
await collection.updateOne(matchFilter, update, {
|
|
675
675
|
...options,
|
|
676
|
-
session: options?.session
|
|
676
|
+
session: options?.session ?? this.getSession(),
|
|
677
677
|
upsert: undefined,
|
|
678
678
|
});
|
|
679
679
|
return count;
|
package/esm/mongo-service.js
CHANGED
|
@@ -2,6 +2,7 @@ import { DATATYPE_METADATA } from '@opra/common';
|
|
|
2
2
|
import { ServiceBase } from '@opra/core';
|
|
3
3
|
import { ObjectId } from 'mongodb';
|
|
4
4
|
import { MongoAdapter } from './mongo-adapter.js';
|
|
5
|
+
const transactionKey = Symbol.for('transaction');
|
|
5
6
|
/**
|
|
6
7
|
* Class representing a MongoDB service for interacting with a collection.
|
|
7
8
|
* @extends ServiceBase
|
|
@@ -92,38 +93,43 @@ export class MongoService extends ServiceBase {
|
|
|
92
93
|
* @param [options] - Optional options for the transaction.
|
|
93
94
|
*/
|
|
94
95
|
async withTransaction(callback, options) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
96
|
+
const ctx = this.context;
|
|
97
|
+
let closeSessionOnFinish = false;
|
|
98
|
+
let transaction = ctx[transactionKey];
|
|
99
|
+
let session;
|
|
100
|
+
if (transaction) {
|
|
101
|
+
session = transaction.session;
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
const db = this.getDatabase();
|
|
105
|
+
const client = db.client;
|
|
106
|
+
session = client.startSession();
|
|
107
|
+
closeSessionOnFinish = true;
|
|
108
|
+
transaction = {
|
|
109
|
+
db,
|
|
110
|
+
session,
|
|
111
|
+
};
|
|
112
|
+
ctx[transactionKey] = transaction;
|
|
113
|
+
}
|
|
105
114
|
const oldInTransaction = session.inTransaction();
|
|
106
115
|
try {
|
|
107
116
|
if (!oldInTransaction)
|
|
108
117
|
session.startTransaction(options);
|
|
109
|
-
const out = await callback(session);
|
|
110
|
-
if (!oldInTransaction)
|
|
118
|
+
const out = await callback(session, this);
|
|
119
|
+
if (!oldInTransaction && session.inTransaction())
|
|
111
120
|
await session.commitTransaction();
|
|
112
121
|
return out;
|
|
113
122
|
}
|
|
114
123
|
catch (e) {
|
|
115
|
-
if (!oldInTransaction)
|
|
124
|
+
if (!oldInTransaction && session.inTransaction())
|
|
116
125
|
await session.abortTransaction();
|
|
117
126
|
throw e;
|
|
118
127
|
}
|
|
119
128
|
finally {
|
|
120
|
-
|
|
121
|
-
if (
|
|
122
|
-
this.session = oldSessionGetter;
|
|
123
|
-
else
|
|
124
|
-
delete this.session;
|
|
125
|
-
if (!oldInTransaction)
|
|
129
|
+
delete ctx[transactionKey];
|
|
130
|
+
if (closeSessionOnFinish) {
|
|
126
131
|
await session.endSession();
|
|
132
|
+
}
|
|
127
133
|
}
|
|
128
134
|
}
|
|
129
135
|
/**
|
|
@@ -134,10 +140,14 @@ export class MongoService extends ServiceBase {
|
|
|
134
140
|
* @throws {Error} If the context or database is not set.
|
|
135
141
|
*/
|
|
136
142
|
getDatabase() {
|
|
143
|
+
const ctx = this.context;
|
|
144
|
+
const transaction = ctx[transactionKey];
|
|
145
|
+
if (transaction)
|
|
146
|
+
return transaction.db;
|
|
137
147
|
const db = typeof this.db === 'function' ? this.db(this) : this.db;
|
|
138
|
-
if (
|
|
139
|
-
|
|
140
|
-
|
|
148
|
+
if (db)
|
|
149
|
+
return db;
|
|
150
|
+
throw new Error(`Database not set!`);
|
|
141
151
|
}
|
|
142
152
|
/**
|
|
143
153
|
* Retrieves the database session.
|
|
@@ -147,7 +157,13 @@ export class MongoService extends ServiceBase {
|
|
|
147
157
|
* @throws {Error} If the context or database is not set.
|
|
148
158
|
*/
|
|
149
159
|
getSession() {
|
|
150
|
-
|
|
160
|
+
const ctx = this.context;
|
|
161
|
+
const transaction = ctx[transactionKey];
|
|
162
|
+
if (transaction)
|
|
163
|
+
return transaction.session;
|
|
164
|
+
const session = typeof this.session === 'function' ? this.session(this) : this.session;
|
|
165
|
+
if (session)
|
|
166
|
+
return session;
|
|
151
167
|
}
|
|
152
168
|
/**
|
|
153
169
|
* Retrieves a MongoDB collection from the given database.
|
|
@@ -169,7 +169,7 @@ export class MongoSingletonService extends MongoEntityService {
|
|
|
169
169
|
});
|
|
170
170
|
}
|
|
171
171
|
/**
|
|
172
|
-
* Updates a document in the MongoDB collection
|
|
172
|
+
* Updates a document in the MongoDB collection
|
|
173
173
|
*
|
|
174
174
|
* @param {PatchDTO<T>} input - The partial input to update the document.
|
|
175
175
|
* @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/mongodb",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"description": "Opra MongoDB adapter package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
"valgen": "^5.10.0"
|
|
12
12
|
},
|
|
13
13
|
"peerDependencies": {
|
|
14
|
-
"@opra/common": "^1.0.0-beta.
|
|
15
|
-
"@opra/core": "^1.0.0-beta.
|
|
16
|
-
"@opra/http": "^1.0.0-beta.
|
|
14
|
+
"@opra/common": "^1.0.0-beta.4",
|
|
15
|
+
"@opra/core": "^1.0.0-beta.4",
|
|
16
|
+
"@opra/http": "^1.0.0-beta.4",
|
|
17
17
|
"mongodb": ">= 6.0.0"
|
|
18
18
|
},
|
|
19
19
|
"type": "module",
|
package/types/mongo-adapter.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { OpraFilter } from '@opra/common';
|
|
2
2
|
import type { ExecutionContext } from '@opra/core';
|
|
3
|
-
import mongodb, {
|
|
3
|
+
import mongodb, { ObjectId } from 'mongodb';
|
|
4
4
|
import _prepareFilter from './adapter-utils/prepare-filter.js';
|
|
5
5
|
import _prepareKeyValues from './adapter-utils/prepare-key-values.js';
|
|
6
6
|
import _preparePatch from './adapter-utils/prepare-patch.js';
|
|
@@ -9,7 +9,6 @@ import _prepareSort from './adapter-utils/prepare-sort.js';
|
|
|
9
9
|
export declare namespace MongoAdapter {
|
|
10
10
|
type AnyId = string | number | ObjectId;
|
|
11
11
|
type FilterInput<T = any> = OpraFilter.Expression | mongodb.Filter<T> | string | undefined;
|
|
12
|
-
type WithTransactionCallback = (session: ClientSession) => any;
|
|
13
12
|
const prepareFilter: typeof _prepareFilter;
|
|
14
13
|
const prepareKeyValues: typeof _prepareKeyValues;
|
|
15
14
|
const preparePatch: typeof _preparePatch;
|
package/types/mongo-service.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComplexType } from '@opra/common';
|
|
2
2
|
import { ExecutionContext, ServiceBase } from '@opra/core';
|
|
3
|
-
import mongodb, { type Document, type TransactionOptions } from 'mongodb';
|
|
3
|
+
import mongodb, { ClientSession, type Document, type TransactionOptions } from 'mongodb';
|
|
4
4
|
import type { Nullish, StrictOmit, Type } from 'ts-gems';
|
|
5
5
|
import type { IsObject } from 'valgen';
|
|
6
6
|
import { MongoAdapter } from './mongo-adapter.js';
|
|
@@ -188,7 +188,7 @@ export declare class MongoService<T extends mongodb.Document = mongodb.Document>
|
|
|
188
188
|
* @constructor
|
|
189
189
|
*/
|
|
190
190
|
constructor(dataType: Type | string, options?: MongoService.Options);
|
|
191
|
-
for<C extends ExecutionContext, P extends Partial<this>>(context: C, overwriteProperties?: Nullish<P>, overwriteContext?: Partial<C>): this & Required<P>;
|
|
191
|
+
for<C extends ExecutionContext, P extends Partial<this>>(context: C | ServiceBase, overwriteProperties?: Nullish<P>, overwriteContext?: Partial<C>): this & Required<P>;
|
|
192
192
|
/**
|
|
193
193
|
* Retrieves the collection name.
|
|
194
194
|
*
|
|
@@ -217,7 +217,7 @@ export declare class MongoService<T extends mongodb.Document = mongodb.Document>
|
|
|
217
217
|
* @param callback - The function to be executed within the transaction.
|
|
218
218
|
* @param [options] - Optional options for the transaction.
|
|
219
219
|
*/
|
|
220
|
-
withTransaction(callback:
|
|
220
|
+
withTransaction(callback: (session: ClientSession, _this: this) => any, options?: TransactionOptions): Promise<any>;
|
|
221
221
|
/**
|
|
222
222
|
* Retrieves the database connection.
|
|
223
223
|
*
|
|
@@ -91,12 +91,12 @@ export declare class MongoSingletonService<T extends mongodb.Document> extends M
|
|
|
91
91
|
*
|
|
92
92
|
* @param {MongoEntityService.FindOneOptions<T>} options - The options to customize the query.
|
|
93
93
|
* @return {Promise<PartialDTO<T>>} - A promise that resolves to the fetched document.
|
|
94
|
-
* @throws {ResourceNotAvailableError} - If the document is not found in the collection
|
|
94
|
+
* @throws {ResourceNotAvailableError} - If the document is not found in the collection
|
|
95
95
|
*/
|
|
96
96
|
get(options: RequiredSome<MongoEntityService.FindOneOptions<T>, 'projection'>): Promise<PartialDTO<T>>;
|
|
97
97
|
get(options?: MongoEntityService.FindOneOptions<T>): Promise<T>;
|
|
98
98
|
/**
|
|
99
|
-
* Updates a document in the MongoDB collection
|
|
99
|
+
* Updates a document in the MongoDB collection
|
|
100
100
|
*
|
|
101
101
|
* @param {PatchDTO<T>} input - The partial input to update the document.
|
|
102
102
|
* @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
|
|
@@ -106,7 +106,7 @@ export declare class MongoSingletonService<T extends mongodb.Document> extends M
|
|
|
106
106
|
update(input: PatchDTO<T> | UpdateFilter<T>, options: RequiredSome<MongoEntityService.UpdateOneOptions<T>, 'projection'>): Promise<PartialDTO<T> | undefined>;
|
|
107
107
|
update(input: PatchDTO<T> | UpdateFilter<T>, options?: MongoEntityService.UpdateOneOptions<T>): Promise<T | undefined>;
|
|
108
108
|
/**
|
|
109
|
-
* Updates a document in the MongoDB collection
|
|
109
|
+
* Updates a document in the MongoDB collection
|
|
110
110
|
*
|
|
111
111
|
* @param {PatchDTO<T>} input - The partial input to update the document.
|
|
112
112
|
* @param {MongoEntityService.UpdateOneOptions<T>} [options] - The update options.
|