uql-orm 0.22.0 → 0.24.0
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/README.md +4 -4
- package/dist/browser/uql-browser.min.js.map +3 -3
- package/dist/dialect/abstractSqlDialect.d.ts +14 -1
- package/dist/dialect/abstractSqlDialect.js +21 -14
- package/dist/dialect/mysqlLikeSqlDialect.d.ts +11 -1
- package/dist/dialect/mysqlLikeSqlDialect.js +25 -0
- package/dist/dialect/pgLikeSqlDialect.d.ts +4 -7
- package/dist/dialect/pgLikeSqlDialect.js +7 -12
- package/dist/entity/decorator/bag.d.ts +35 -0
- package/dist/entity/decorator/bag.js +54 -0
- package/dist/entity/decorator/entity.d.ts +28 -2
- package/dist/entity/decorator/entity.js +40 -2
- package/dist/entity/decorator/members.d.ts +51 -0
- package/dist/entity/decorator/members.js +51 -0
- package/dist/entity/index.d.ts +3 -1
- package/dist/entity/index.js +3 -1
- package/dist/entity/metadata/definition.d.ts +23 -9
- package/dist/entity/metadata/definition.js +55 -100
- package/dist/http/contract.js +1 -2
- package/dist/http/handler.js +5 -26
- package/dist/http/query.js +1 -1
- package/dist/migrate/acquireQuerierForMigrations.d.ts +13 -1
- package/dist/migrate/acquireQuerierForMigrations.js +28 -0
- package/dist/migrate/cli-config.js +24 -8
- package/dist/migrate/cli.js +5 -1
- package/dist/migrate/codegen/entityCodeGenerator.js +3 -4
- package/dist/migrate/codegen/index.d.ts +0 -1
- package/dist/migrate/codegen/index.js +0 -2
- package/dist/migrate/drift/driftDetector.d.ts +10 -1
- package/dist/migrate/drift/driftDetector.js +22 -5
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +5 -1
- package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +17 -27
- package/dist/migrate/introspection/mongoIntrospector.js +7 -13
- package/dist/migrate/migrator.js +44 -81
- package/dist/migrate/storage/databaseStorage.d.ts +2 -0
- package/dist/migrate/storage/databaseStorage.js +8 -23
- package/dist/mongo/mongodbQuerier.js +171 -229
- package/dist/nestjs/uqlContextInterceptor.js +58 -22
- package/dist/nestjs/uqlModule.d.ts +2 -11
- package/dist/nestjs/uqlModule.js +93 -44
- package/dist/postgres/postgresDialect.js +2 -2
- package/dist/querier/abstractQuerier.d.ts +28 -0
- package/dist/querier/abstractQuerier.js +47 -22
- package/dist/querier/abstractQuerierPool.d.ts +21 -1
- package/dist/querier/abstractQuerierPool.js +113 -3
- package/dist/querier/abstractSqlQuerier.d.ts +1 -3
- package/dist/querier/abstractSqlQuerier.js +51 -96
- package/dist/querier/index.d.ts +3 -1
- package/dist/querier/index.js +3 -1
- package/dist/querier/querierContext.browser.d.ts +12 -0
- package/dist/querier/querierContext.browser.js +18 -0
- package/dist/querier/querierContext.d.ts +22 -0
- package/dist/querier/querierContext.js +42 -0
- package/dist/querier/queryError.d.ts +22 -0
- package/dist/querier/queryError.js +20 -0
- package/dist/querier/transactional.d.ts +26 -0
- package/dist/querier/transactional.js +43 -0
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/schemaASTBuilder.d.ts +1 -1
- package/dist/schema/schemaASTBuilder.js +2 -2
- package/dist/schema/types.d.ts +0 -21
- package/dist/sqlite/abstractSqliteQuerier.d.ts +9 -2
- package/dist/sqlite/hranaQuerier.js +20 -42
- package/dist/sqlite/index.d.ts +1 -0
- package/dist/sqlite/index.js +1 -0
- package/dist/sqlite/localSqliteQuerierPool.d.ts +31 -0
- package/dist/sqlite/localSqliteQuerierPool.js +34 -0
- package/dist/sqlite/nodeSqliteAdapter.d.ts +35 -0
- package/dist/sqlite/nodeSqliteAdapter.js +28 -0
- package/dist/sqlite/nodeSqliteQuerierPool.d.ts +28 -0
- package/dist/sqlite/nodeSqliteQuerierPool.js +29 -0
- package/dist/sqlite/sqliteDialect.d.ts +1 -2
- package/dist/sqlite/sqliteDialect.js +0 -13
- package/dist/sqlite/sqliteQuerierPool.d.ts +10 -23
- package/dist/sqlite/sqliteQuerierPool.js +9 -28
- package/dist/type/entity.d.ts +95 -28
- package/dist/type/querier.d.ts +8 -35
- package/dist/type/querierPool.d.ts +13 -12
- package/dist/type/universalQuerier.d.ts +23 -7
- package/dist/util/hook.util.js +1 -1
- package/package.json +7 -16
- package/dist/entity/decorator/field.d.ts +0 -2
- package/dist/entity/decorator/field.js +0 -7
- package/dist/entity/decorator/filter.d.ts +0 -7
- package/dist/entity/decorator/filter.js +0 -11
- package/dist/entity/decorator/hook.d.ts +0 -7
- package/dist/entity/decorator/hook.js +0 -14
- package/dist/entity/decorator/id.d.ts +0 -2
- package/dist/entity/decorator/id.js +0 -7
- package/dist/entity/decorator/index-decorator.d.ts +0 -22
- package/dist/entity/decorator/index-decorator.js +0 -26
- package/dist/entity/decorator/index.d.ts +0 -8
- package/dist/entity/decorator/index.js +0 -8
- package/dist/entity/decorator/relation.d.ts +0 -8
- package/dist/entity/decorator/relation.js +0 -19
- package/dist/migrate/codegen/smartRelationDetector.d.ts +0 -47
- package/dist/migrate/codegen/smartRelationDetector.js +0 -134
- package/dist/querier/decorator/index.d.ts +0 -4
- package/dist/querier/decorator/index.js +0 -4
- package/dist/querier/decorator/injectQuerier.d.ts +0 -3
- package/dist/querier/decorator/injectQuerier.js +0 -33
- package/dist/querier/decorator/log.d.ts +0 -32
- package/dist/querier/decorator/log.js +0 -52
- package/dist/querier/decorator/serialized.d.ts +0 -6
- package/dist/querier/decorator/serialized.js +0 -13
- package/dist/querier/decorator/transactional.d.ts +0 -6
- package/dist/querier/decorator/transactional.js +0 -48
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
-
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
-
};
|
|
10
|
-
var _a;
|
|
11
1
|
import { getMeta } from '../entity/index.js';
|
|
12
|
-
import { AbstractQuerier, enrichError
|
|
2
|
+
import { AbstractQuerier, enrichError } from '../querier/index.js';
|
|
13
3
|
import { clone, getKeys, getRelationRequestSummary, getSoftDeleteValue, hasKeys, throwNoPendingTransaction, throwPendingTransaction, withoutSoftDeleteFilter, } from '../util/index.js';
|
|
14
4
|
export class MongodbQuerier extends AbstractQuerier {
|
|
15
5
|
dialect;
|
|
@@ -23,34 +13,38 @@ export class MongodbQuerier extends AbstractQuerier {
|
|
|
23
13
|
this.extra = extra;
|
|
24
14
|
}
|
|
25
15
|
async execute(task) {
|
|
26
|
-
return
|
|
16
|
+
return this.serialize(async () => {
|
|
17
|
+
return task(this.session);
|
|
18
|
+
});
|
|
27
19
|
}
|
|
28
20
|
async internalFindMany(entity, q, opts) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// to-many relations need their own query, exactly as in the non-vector path
|
|
36
|
-
await this.fillToManyRelations(entity, documents, q.$populate);
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
const relationSummary = getRelationRequestSummary(meta, q.$populate);
|
|
40
|
-
// A relation condition needs `$lookup`, so it forces the aggregation path just like populating
|
|
41
|
-
// one does; a plain `find` cursor cannot express it.
|
|
42
|
-
if (relationSummary.requestedKeys.length || this.dialect.constrainsRelations(entity, q.$where)) {
|
|
43
|
-
const pipeline = this.dialect.aggregationPipeline(entity, q, relationSummary, opts);
|
|
21
|
+
return this.timed('internalFindMany', undefined, async () => {
|
|
22
|
+
const meta = getMeta(entity);
|
|
23
|
+
const vectorSort = this.dialect.extractVectorSort(q.$sort);
|
|
24
|
+
let documents;
|
|
25
|
+
if (vectorSort) {
|
|
26
|
+
const pipeline = this.buildVectorPipeline(entity, q, vectorSort, opts);
|
|
44
27
|
documents = await this.runPipeline(entity, meta, pipeline);
|
|
28
|
+
// to-many relations need their own query, exactly as in the non-vector path
|
|
45
29
|
await this.fillToManyRelations(entity, documents, q.$populate);
|
|
46
30
|
}
|
|
47
31
|
else {
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
32
|
+
const relationSummary = getRelationRequestSummary(meta, q.$populate);
|
|
33
|
+
// A relation condition needs `$lookup`, so it forces the aggregation path just like populating
|
|
34
|
+
// one does; a plain `find` cursor cannot express it.
|
|
35
|
+
if (relationSummary.requestedKeys.length || this.dialect.constrainsRelations(entity, q.$where)) {
|
|
36
|
+
const pipeline = this.dialect.aggregationPipeline(entity, q, relationSummary, opts);
|
|
37
|
+
documents = await this.runPipeline(entity, meta, pipeline);
|
|
38
|
+
await this.fillToManyRelations(entity, documents, q.$populate);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const cursor = this.buildFindCursor(entity, q, opts);
|
|
42
|
+
documents = await this.execute(() => cursor.toArray());
|
|
43
|
+
documents = this.dialect.normalizeIds(meta, documents) || [];
|
|
44
|
+
}
|
|
51
45
|
}
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
return documents;
|
|
47
|
+
});
|
|
54
48
|
}
|
|
55
49
|
async *internalFindManyStream(entity, q, opts) {
|
|
56
50
|
const meta = getMeta(entity);
|
|
@@ -71,7 +65,7 @@ export class MongodbQuerier extends AbstractQuerier {
|
|
|
71
65
|
}
|
|
72
66
|
}
|
|
73
67
|
catch (err) {
|
|
74
|
-
enrichError(err, this.logger, 'internalFindManyStream');
|
|
68
|
+
throw enrichError(err, this.logger, 'internalFindManyStream');
|
|
75
69
|
}
|
|
76
70
|
}
|
|
77
71
|
buildScalarProjection(entity, q) {
|
|
@@ -144,22 +138,26 @@ export class MongodbQuerier extends AbstractQuerier {
|
|
|
144
138
|
return pipeline;
|
|
145
139
|
}
|
|
146
140
|
async internalAggregate(entity, q, opts) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
141
|
+
return this.timed('internalAggregate', undefined, async () => {
|
|
142
|
+
const pipeline = this.dialect.buildAggregateStages(entity, q, opts);
|
|
143
|
+
// biome-ignore lint/suspicious/noExplicitAny: aggregate result type matches QueryAggregateResult at runtime but TS can't verify
|
|
144
|
+
return this.execute((session) => this.collection(entity).aggregate(pipeline, { session }).toArray());
|
|
145
|
+
});
|
|
150
146
|
}
|
|
151
147
|
async internalCount(entity, qm = {}, opts) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
session,
|
|
162
|
-
|
|
148
|
+
return this.timed('internalCount', undefined, async () => {
|
|
149
|
+
if (this.dialect.constrainsRelations(entity, qm.$where)) {
|
|
150
|
+
const { stages, filter } = this.dialect.whereWithRelations(entity, qm.$where, opts);
|
|
151
|
+
const [counted] = await this.execute((session) => this.collection(entity)
|
|
152
|
+
.aggregate([...stages, { $match: filter }, { $count: 'n' }], { session })
|
|
153
|
+
.toArray());
|
|
154
|
+
return counted?.n ?? 0;
|
|
155
|
+
}
|
|
156
|
+
const filter = this.dialect.where(entity, qm.$where, opts);
|
|
157
|
+
return this.execute((session) => this.collection(entity).countDocuments(filter, {
|
|
158
|
+
session,
|
|
159
|
+
}));
|
|
160
|
+
});
|
|
163
161
|
}
|
|
164
162
|
/**
|
|
165
163
|
* The `_id`s a search matches. Writes need this whenever the `$where` constrains a relation, since a
|
|
@@ -174,35 +172,39 @@ export class MongodbQuerier extends AbstractQuerier {
|
|
|
174
172
|
return (this.dialect.normalizeIds(meta, founds) || []).map((found) => found[meta.id]);
|
|
175
173
|
}
|
|
176
174
|
async internalInsertMany(entity, payloads) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
175
|
+
return this.timed('internalInsertMany', undefined, async () => {
|
|
176
|
+
if (!payloads?.length) {
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
payloads = clone(payloads);
|
|
180
|
+
const meta = getMeta(entity);
|
|
181
|
+
const persistables = this.dialect.getPersistables(meta, payloads, 'onInsert');
|
|
182
|
+
const { insertedIds } = await this.execute((session) => this.collection(entity).insertMany(persistables, { session }));
|
|
183
|
+
const ids = Object.values(insertedIds);
|
|
184
|
+
for (const [index, it] of payloads.entries()) {
|
|
185
|
+
it[meta.id] = ids[index];
|
|
186
|
+
}
|
|
187
|
+
await this.insertRelations(entity, payloads);
|
|
188
|
+
return ids;
|
|
189
|
+
});
|
|
190
190
|
}
|
|
191
191
|
async internalUpdateMany(entity, qm, payload, opts) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
session,
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
192
|
+
return this.timed('internalUpdateMany', undefined, async () => {
|
|
193
|
+
payload = clone(payload);
|
|
194
|
+
const meta = getMeta(entity);
|
|
195
|
+
const persistable = this.dialect.getPersistable(meta, payload, 'onUpdate');
|
|
196
|
+
// An `updateMany` filter cannot host a `$lookup`, so a relation condition is resolved to ids first.
|
|
197
|
+
const where = this.dialect.constrainsRelations(entity, qm.$where)
|
|
198
|
+
? { _id: { $in: await this.matchedIds(entity, qm.$where, opts) } }
|
|
199
|
+
: this.dialect.where(entity, qm.$where, opts);
|
|
200
|
+
// Maps JSON operators ($set/$unset/$push/$pull) onto their native MongoDB equivalents.
|
|
201
|
+
const update = this.dialect.getUpdateFilter(persistable);
|
|
202
|
+
const { matchedCount } = await this.execute((session) => this.collection(entity).updateMany(where, update, {
|
|
203
|
+
session,
|
|
204
|
+
}));
|
|
205
|
+
await this.updateRelations(entity, qm, payload, opts);
|
|
206
|
+
return matchedCount;
|
|
207
|
+
});
|
|
206
208
|
}
|
|
207
209
|
buildConflictFilter(entity, conflictPaths, item) {
|
|
208
210
|
const where = getKeys(conflictPaths).reduce((acc, key) => {
|
|
@@ -212,77 +214,83 @@ export class MongodbQuerier extends AbstractQuerier {
|
|
|
212
214
|
return this.dialect.where(entity, where);
|
|
213
215
|
}
|
|
214
216
|
async upsertOne(entity, conflictPaths, payload) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
217
|
+
return this.timed('upsertOne', undefined, async () => {
|
|
218
|
+
payload = clone(payload);
|
|
219
|
+
const meta = getMeta(entity);
|
|
220
|
+
const persistable = this.dialect.getPersistable(meta, payload, 'onInsert');
|
|
221
|
+
const filter = this.buildConflictFilter(entity, conflictPaths, payload);
|
|
222
|
+
const update = { $set: persistable };
|
|
223
|
+
const res = await this.execute((session) => this.collection(entity).findOneAndUpdate(filter, update, {
|
|
224
|
+
upsert: true,
|
|
225
|
+
returnDocument: 'after',
|
|
226
|
+
includeResultMetadata: true,
|
|
227
|
+
session,
|
|
228
|
+
}));
|
|
229
|
+
const firstId = res?.value?._id;
|
|
230
|
+
// `updatedExisting` is false when a new document was inserted (upserted).
|
|
231
|
+
const created = res?.lastErrorObject?.['updatedExisting'] === false;
|
|
232
|
+
return { firstId, changes: firstId ? 1 : 0, created };
|
|
233
|
+
});
|
|
230
234
|
}
|
|
231
235
|
async upsertMany(entity, conflictPaths, payload) {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
236
|
+
return this.timed('upsertMany', undefined, async () => {
|
|
237
|
+
if (!payload?.length) {
|
|
238
|
+
return { changes: 0 };
|
|
239
|
+
}
|
|
240
|
+
payload = clone(payload);
|
|
241
|
+
const meta = getMeta(entity);
|
|
242
|
+
const operations = payload.map((item) => {
|
|
243
|
+
const persistable = this.dialect.getPersistable(meta, item, 'onInsert');
|
|
244
|
+
const filter = this.buildConflictFilter(entity, conflictPaths, item);
|
|
245
|
+
const update = { $set: persistable };
|
|
246
|
+
return {
|
|
247
|
+
updateOne: {
|
|
248
|
+
filter,
|
|
249
|
+
update,
|
|
250
|
+
upsert: true,
|
|
251
|
+
},
|
|
252
|
+
};
|
|
253
|
+
});
|
|
254
|
+
const res = await this.execute((session) => this.collection(entity).bulkWrite(operations, { session }));
|
|
255
|
+
const changes = (res.upsertedCount ?? 0) + (res.modifiedCount ?? 0);
|
|
256
|
+
// `upsertedIds` only covers newly-inserted documents (keyed by operation index); a matched and
|
|
257
|
+
// updated document's `_id` isn't in the response, so it's simply not represented here - same
|
|
258
|
+
// "exact where knowable, absent otherwise" convention `RETURNING`-based SQL dialects use for
|
|
259
|
+
// rows that hit `DO NOTHING`.
|
|
260
|
+
const ids = Object.values(res.upsertedIds);
|
|
261
|
+
return { changes, ids, firstId: ids[0] };
|
|
248
262
|
});
|
|
249
|
-
const res = await this.execute((session) => this.collection(entity).bulkWrite(operations, { session }));
|
|
250
|
-
const changes = (res.upsertedCount ?? 0) + (res.modifiedCount ?? 0);
|
|
251
|
-
// `upsertedIds` only covers newly-inserted documents (keyed by operation index); a matched and
|
|
252
|
-
// updated document's `_id` isn't in the response, so it's simply not represented here - same
|
|
253
|
-
// "exact where knowable, absent otherwise" convention `RETURNING`-based SQL dialects use for
|
|
254
|
-
// rows that hit `DO NOTHING`.
|
|
255
|
-
const ids = Object.values(res.upsertedIds);
|
|
256
|
-
return { changes, ids, firstId: ids[0] };
|
|
257
263
|
}
|
|
258
264
|
async internalDeleteMany(entity, qm, opts = {}) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
session,
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
265
|
+
return this.timed('internalDeleteMany', undefined, async () => {
|
|
266
|
+
const meta = getMeta(entity);
|
|
267
|
+
// Soft-delete (stamp) unless `hardDelete` is requested or the entity has no soft-delete field.
|
|
268
|
+
const field = !opts.hardDelete && meta.softDelete ? meta.fields[meta.softDelete] : undefined;
|
|
269
|
+
// Hard delete targets matching rows regardless of soft-delete state (keeps other filters).
|
|
270
|
+
const findOpts = field ? opts : { ...opts, filters: withoutSoftDeleteFilter(opts.filters) };
|
|
271
|
+
// Delete has always resolved its ids first (it stamps or removes them by `_id`), so a relation
|
|
272
|
+
// condition needs nothing extra here.
|
|
273
|
+
const ids = await this.matchedIds(entity, qm.$where, findOpts);
|
|
274
|
+
if (!ids.length) {
|
|
275
|
+
return 0;
|
|
276
|
+
}
|
|
277
|
+
let changes;
|
|
278
|
+
if (field) {
|
|
279
|
+
// Stamp the mapped column: reads filter on it, so a `@Field({ name })` mismatch here would
|
|
280
|
+
// report a successful delete and leave the row visible.
|
|
281
|
+
const softDeleteColumn = this.dialect.resolveColumnName(meta.softDelete, field);
|
|
282
|
+
const updateResult = await this.execute((session) => this.collection(entity).updateMany({ _id: { $in: ids } }, { $set: { [softDeleteColumn]: getSoftDeleteValue(field) } }, {
|
|
283
|
+
session,
|
|
284
|
+
}));
|
|
285
|
+
changes = updateResult.matchedCount;
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
const deleteResult = await this.execute((session) => this.collection(entity).deleteMany({ _id: { $in: ids } }, { session }));
|
|
289
|
+
changes = deleteResult.deletedCount;
|
|
290
|
+
}
|
|
291
|
+
await this.deleteRelations(entity, ids, opts);
|
|
292
|
+
return changes;
|
|
293
|
+
});
|
|
286
294
|
}
|
|
287
295
|
get hasOpenTransaction() {
|
|
288
296
|
return !!this.session?.inTransaction();
|
|
@@ -295,27 +303,33 @@ export class MongodbQuerier extends AbstractQuerier {
|
|
|
295
303
|
return this.conn.db();
|
|
296
304
|
}
|
|
297
305
|
async beginTransaction(_opts) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
306
|
+
return this.serialize(async () => {
|
|
307
|
+
if (this.hasOpenTransaction) {
|
|
308
|
+
throwPendingTransaction();
|
|
309
|
+
}
|
|
310
|
+
this.logger.logInfo('beginTransaction');
|
|
311
|
+
await this.session?.endSession();
|
|
312
|
+
this.session = this.conn.startSession();
|
|
313
|
+
this.session.startTransaction();
|
|
314
|
+
});
|
|
305
315
|
}
|
|
306
316
|
async commitTransaction() {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
317
|
+
return this.serialize(async () => {
|
|
318
|
+
if (!this.hasOpenTransaction) {
|
|
319
|
+
throwNoPendingTransaction();
|
|
320
|
+
}
|
|
321
|
+
this.logger.logInfo('commitTransaction');
|
|
322
|
+
await this.session.commitTransaction();
|
|
323
|
+
});
|
|
312
324
|
}
|
|
313
325
|
async rollbackTransaction() {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
326
|
+
return this.serialize(async () => {
|
|
327
|
+
if (!this.hasOpenTransaction) {
|
|
328
|
+
throwNoPendingTransaction();
|
|
329
|
+
}
|
|
330
|
+
this.logger.logInfo('rollbackTransaction');
|
|
331
|
+
await this.session.abortTransaction();
|
|
332
|
+
});
|
|
319
333
|
}
|
|
320
334
|
async internalRelease() {
|
|
321
335
|
if (this.hasOpenTransaction) {
|
|
@@ -325,75 +339,3 @@ export class MongodbQuerier extends AbstractQuerier {
|
|
|
325
339
|
this.session = undefined;
|
|
326
340
|
}
|
|
327
341
|
}
|
|
328
|
-
__decorate([
|
|
329
|
-
Serialized(),
|
|
330
|
-
__metadata("design:type", Function),
|
|
331
|
-
__metadata("design:paramtypes", [Function]),
|
|
332
|
-
__metadata("design:returntype", Promise)
|
|
333
|
-
], MongodbQuerier.prototype, "execute", null);
|
|
334
|
-
__decorate([
|
|
335
|
-
Log(),
|
|
336
|
-
__metadata("design:type", Function),
|
|
337
|
-
__metadata("design:paramtypes", [Object, Object, Object]),
|
|
338
|
-
__metadata("design:returntype", Promise)
|
|
339
|
-
], MongodbQuerier.prototype, "internalFindMany", null);
|
|
340
|
-
__decorate([
|
|
341
|
-
Log(),
|
|
342
|
-
__metadata("design:type", Function),
|
|
343
|
-
__metadata("design:paramtypes", [Object, Object, Object]),
|
|
344
|
-
__metadata("design:returntype", Promise)
|
|
345
|
-
], MongodbQuerier.prototype, "internalAggregate", null);
|
|
346
|
-
__decorate([
|
|
347
|
-
Log(),
|
|
348
|
-
__metadata("design:type", Function),
|
|
349
|
-
__metadata("design:paramtypes", [Object, Object, Object]),
|
|
350
|
-
__metadata("design:returntype", Promise)
|
|
351
|
-
], MongodbQuerier.prototype, "internalCount", null);
|
|
352
|
-
__decorate([
|
|
353
|
-
Log(),
|
|
354
|
-
__metadata("design:type", Function),
|
|
355
|
-
__metadata("design:paramtypes", [Object, Array]),
|
|
356
|
-
__metadata("design:returntype", Promise)
|
|
357
|
-
], MongodbQuerier.prototype, "internalInsertMany", null);
|
|
358
|
-
__decorate([
|
|
359
|
-
Log(),
|
|
360
|
-
__metadata("design:type", Function),
|
|
361
|
-
__metadata("design:paramtypes", [Object, Object, Object, Object]),
|
|
362
|
-
__metadata("design:returntype", Promise)
|
|
363
|
-
], MongodbQuerier.prototype, "internalUpdateMany", null);
|
|
364
|
-
__decorate([
|
|
365
|
-
Log(),
|
|
366
|
-
__metadata("design:type", Function),
|
|
367
|
-
__metadata("design:paramtypes", [Object, Object, typeof (_a = typeof E !== "undefined" && E) === "function" ? _a : Object]),
|
|
368
|
-
__metadata("design:returntype", Promise)
|
|
369
|
-
], MongodbQuerier.prototype, "upsertOne", null);
|
|
370
|
-
__decorate([
|
|
371
|
-
Log(),
|
|
372
|
-
__metadata("design:type", Function),
|
|
373
|
-
__metadata("design:paramtypes", [Object, Object, Array]),
|
|
374
|
-
__metadata("design:returntype", Promise)
|
|
375
|
-
], MongodbQuerier.prototype, "upsertMany", null);
|
|
376
|
-
__decorate([
|
|
377
|
-
Log(),
|
|
378
|
-
__metadata("design:type", Function),
|
|
379
|
-
__metadata("design:paramtypes", [Object, Object, Object]),
|
|
380
|
-
__metadata("design:returntype", Promise)
|
|
381
|
-
], MongodbQuerier.prototype, "internalDeleteMany", null);
|
|
382
|
-
__decorate([
|
|
383
|
-
Serialized(),
|
|
384
|
-
__metadata("design:type", Function),
|
|
385
|
-
__metadata("design:paramtypes", [Object]),
|
|
386
|
-
__metadata("design:returntype", Promise)
|
|
387
|
-
], MongodbQuerier.prototype, "beginTransaction", null);
|
|
388
|
-
__decorate([
|
|
389
|
-
Serialized(),
|
|
390
|
-
__metadata("design:type", Function),
|
|
391
|
-
__metadata("design:paramtypes", []),
|
|
392
|
-
__metadata("design:returntype", Promise)
|
|
393
|
-
], MongodbQuerier.prototype, "commitTransaction", null);
|
|
394
|
-
__decorate([
|
|
395
|
-
Serialized(),
|
|
396
|
-
__metadata("design:type", Function),
|
|
397
|
-
__metadata("design:paramtypes", []),
|
|
398
|
-
__metadata("design:returntype", Promise)
|
|
399
|
-
], MongodbQuerier.prototype, "rollbackTransaction", null);
|
|
@@ -1,11 +1,36 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
6
|
+
var _, done = false;
|
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
8
|
+
var context = {};
|
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
13
|
+
if (kind === "accessor") {
|
|
14
|
+
if (result === void 0) continue;
|
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
19
|
+
}
|
|
20
|
+
else if (_ = accept(result)) {
|
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
|
22
|
+
else descriptor[key] = _;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
|
+
done = true;
|
|
6
27
|
};
|
|
7
|
-
var
|
|
8
|
-
|
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
+
var useValue = arguments.length > 2;
|
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
+
}
|
|
33
|
+
return useValue ? value : void 0;
|
|
9
34
|
};
|
|
10
35
|
import { Injectable } from '@nestjs/common';
|
|
11
36
|
import { Observable } from 'rxjs';
|
|
@@ -15,19 +40,30 @@ import { withContext } from '../context/context.js';
|
|
|
15
40
|
* are scoped automatically for every query in the request - including relations, cascades, and
|
|
16
41
|
* `@Transactional` services. Wired for you by {@link UqlModule.forRoot} when you pass `getContext`.
|
|
17
42
|
*/
|
|
18
|
-
let UqlContextInterceptor =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
43
|
+
let UqlContextInterceptor = (() => {
|
|
44
|
+
let _classDecorators = [Injectable()];
|
|
45
|
+
let _classDescriptor;
|
|
46
|
+
let _classExtraInitializers = [];
|
|
47
|
+
let _classThis;
|
|
48
|
+
var UqlContextInterceptor = class {
|
|
49
|
+
static { _classThis = this; }
|
|
50
|
+
static {
|
|
51
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
52
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
53
|
+
UqlContextInterceptor = _classThis = _classDescriptor.value;
|
|
54
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
55
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
56
|
+
}
|
|
57
|
+
getContext;
|
|
58
|
+
constructor(getContext) {
|
|
59
|
+
this.getContext = getContext;
|
|
60
|
+
}
|
|
61
|
+
intercept(execContext, next) {
|
|
62
|
+
const context = this.getContext(execContext.switchToHttp().getRequest()) ?? {};
|
|
63
|
+
// Subscribe inside the context so the handler's async chain (and its queries) inherit it.
|
|
64
|
+
return new Observable((subscriber) => withContext(context, () => next.handle().subscribe(subscriber)));
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
return UqlContextInterceptor = _classThis;
|
|
68
|
+
})();
|
|
33
69
|
export { UqlContextInterceptor };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DynamicModule, type FactoryProvider
|
|
1
|
+
import { type DynamicModule, type FactoryProvider } from '@nestjs/common';
|
|
2
2
|
import type { QuerierPool, UqlContext } from '../type/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Injection token for the configured {@link QuerierPool} - for injecting into your own
|
|
@@ -30,16 +30,7 @@ export type UqlModuleAsyncOptions<Req = unknown> = UqlModuleCommon<Req> & {
|
|
|
30
30
|
/** Providers to inject into `useFactory`. */
|
|
31
31
|
readonly inject?: FactoryProvider['inject'];
|
|
32
32
|
};
|
|
33
|
-
|
|
34
|
-
* NestJS integration: provides the pool via DI, sets it as UQL's default pool (so `getQuerier()`,
|
|
35
|
-
* `querierMiddleware` (express platform), `createFetchHandler`, and `@Transactional` work unchanged),
|
|
36
|
-
* optionally scopes every request to a {@link UqlContext} (multi-tenancy), and ends the pool on
|
|
37
|
-
* application shutdown.
|
|
38
|
-
*/
|
|
39
|
-
export declare class UqlModule implements OnApplicationShutdown {
|
|
40
|
-
private readonly pool;
|
|
41
|
-
constructor(pool: QuerierPool);
|
|
42
|
-
onApplicationShutdown(): Promise<void>;
|
|
33
|
+
export declare class UqlModule {
|
|
43
34
|
/** Configure with an already-built pool. */
|
|
44
35
|
static forRoot<Req = unknown>({ pool, global, getContext }: UqlModuleOptions<Req>): DynamicModule;
|
|
45
36
|
/** Configure with a pool built asynchronously from injected providers (e.g. `ConfigService`). */
|