@zakodium/adonis-mongodb 0.18.1 → 0.20.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 +2 -2
- package/lib/adonis-typings/container.d.ts +3 -3
- package/lib/adonis-typings/database.d.ts +5 -5
- package/lib/adonis-typings/index.d.ts +0 -6
- package/lib/adonis-typings/migration.d.ts +8 -1
- package/lib/adonis-typings/odm.d.ts +4 -8
- package/lib/adonis-typings/transaction.d.ts +39 -0
- package/lib/adonis-typings/transaction.js +2 -0
- package/lib/commands/MongodbListMigrations.js +6 -6
- package/lib/commands/MongodbMakeMigration.js +8 -6
- package/lib/commands/MongodbMigrate.js +23 -13
- package/lib/commands/util/MigrationCommand.js +24 -13
- package/lib/commands/util/transformMigrations.d.ts +1 -1
- package/lib/commands/util/transformMigrations.js +2 -2
- package/lib/providers/MongodbProvider.d.ts +2 -2
- package/lib/providers/MongodbProvider.js +11 -1
- package/lib/src/Auth/MongodbModelAuthProvider.d.ts +2 -4
- package/lib/src/Auth/MongodbModelAuthProvider.js +12 -6
- package/lib/src/Database/Connection.d.ts +5 -5
- package/lib/src/Database/Connection.js +34 -9
- package/lib/src/Database/ConnectionManager.d.ts +1 -2
- package/lib/src/Database/ConnectionManager.js +5 -2
- package/lib/src/Database/Database.d.ts +2 -3
- package/lib/src/Database/Database.js +5 -1
- package/lib/src/Database/TransactionEventEmitter.d.ts +8 -0
- package/lib/src/Database/TransactionEventEmitter.js +8 -0
- package/lib/src/Migration.js +24 -3
- package/lib/src/Model/Model.d.ts +3 -3
- package/lib/src/Model/Model.js +35 -16
- package/lib/src/Model/proxyHandler.js +1 -1
- package/lib/src/Odm/decorators.d.ts +1 -1
- package/package.json +11 -11
- package/src/Auth/MongodbModelAuthProvider.ts +2 -2
- package/src/Database/Connection.ts +49 -13
- package/src/Database/ConnectionManager.ts +3 -1
- package/src/Database/Database.ts +2 -2
- package/src/Database/TransactionEventEmitter.ts +10 -0
- package/src/Migration.ts +33 -4
- package/src/Model/Model.ts +15 -17
- package/src/Model/proxyHandler.ts +1 -1
- package/src/Odm/decorators.ts +1 -1
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { EventEmitter } from 'node:events';
|
|
2
2
|
|
|
3
3
|
import { Exception } from '@poppinss/utils';
|
|
4
|
-
import {
|
|
5
|
-
MongoClient,
|
|
4
|
+
import type {
|
|
6
5
|
Db,
|
|
7
6
|
Collection,
|
|
8
7
|
ClientSession,
|
|
9
8
|
Document,
|
|
10
9
|
TransactionOptions,
|
|
11
10
|
} from 'mongodb';
|
|
11
|
+
import { MongoClient } from 'mongodb';
|
|
12
12
|
|
|
13
|
-
import { LoggerContract } from '@ioc:Adonis/Core/Logger';
|
|
13
|
+
import type { LoggerContract } from '@ioc:Adonis/Core/Logger';
|
|
14
14
|
import type {
|
|
15
15
|
MongodbConnectionConfig,
|
|
16
16
|
ConnectionContract,
|
|
17
17
|
} from '@ioc:Zakodium/Mongodb/Database';
|
|
18
18
|
|
|
19
|
+
import { TransactionEventEmitter } from './TransactionEventEmitter';
|
|
20
|
+
|
|
19
21
|
enum ConnectionStatus {
|
|
20
22
|
CONNECTED = 'CONNECTED',
|
|
21
23
|
DISCONNECTED = 'DISCONNECTED',
|
|
@@ -45,7 +47,7 @@ export declare interface Connection {
|
|
|
45
47
|
): this;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
// eslint-disable-next-line
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
49
51
|
export class Connection extends EventEmitter implements ConnectionContract {
|
|
50
52
|
public readonly client: MongoClient;
|
|
51
53
|
public readonly name: string;
|
|
@@ -131,17 +133,51 @@ export class Connection extends EventEmitter implements ConnectionContract {
|
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
public async transaction<TResult>(
|
|
134
|
-
handler: (
|
|
136
|
+
handler: (
|
|
137
|
+
session: ClientSession,
|
|
138
|
+
db: Db,
|
|
139
|
+
transactionEventEmitter: TransactionEventEmitter,
|
|
140
|
+
) => Promise<TResult>,
|
|
135
141
|
options?: TransactionOptions,
|
|
136
142
|
): Promise<TResult> {
|
|
137
143
|
const db = await this._ensureDb();
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
|
|
145
|
+
let session: ClientSession;
|
|
146
|
+
const emitter = new TransactionEventEmitter();
|
|
147
|
+
|
|
148
|
+
return this.client
|
|
149
|
+
.withSession((_session) =>
|
|
150
|
+
_session.withTransaction(async (_session) => {
|
|
151
|
+
session = _session;
|
|
152
|
+
return handler(session, db, emitter);
|
|
153
|
+
}, options),
|
|
154
|
+
)
|
|
155
|
+
.then(
|
|
156
|
+
(result) => {
|
|
157
|
+
// https://github.com/mongodb/node-mongodb-native/blob/v6.7.0/src/transactions.ts#L147
|
|
158
|
+
// https://github.com/mongodb/node-mongodb-native/blob/v6.7.0/src/transactions.ts#L54
|
|
159
|
+
// session.transaction.isCommitted is not a sufficient indicator,
|
|
160
|
+
// because it's true if transaction commits or aborts.
|
|
161
|
+
const isCommitted = session.transaction.isCommitted;
|
|
162
|
+
const isAborted =
|
|
163
|
+
// https://github.com/mongodb/node-mongodb-native/blob/v6.7.0/src/transactions.ts#L11
|
|
164
|
+
Reflect.get(session.transaction, 'state') === 'TRANSACTION_ABORTED';
|
|
165
|
+
|
|
166
|
+
emitter.emit(
|
|
167
|
+
isCommitted && isAborted ? 'abort' : 'commit',
|
|
168
|
+
session,
|
|
169
|
+
db,
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
return result;
|
|
173
|
+
// If an error occurs in this scope,
|
|
174
|
+
// it will not be caught by this then's error handler, but by the caller's catch.
|
|
175
|
+
// This is what we want, as an error in this scope should not trigger the abort event.
|
|
176
|
+
},
|
|
177
|
+
(error) => {
|
|
178
|
+
emitter.emit('abort', session, db, error);
|
|
179
|
+
throw error;
|
|
180
|
+
},
|
|
181
|
+
);
|
|
146
182
|
}
|
|
147
183
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Exception } from '@poppinss/utils';
|
|
2
2
|
|
|
3
|
-
import { LoggerContract } from '@ioc:Adonis/Core/Logger';
|
|
3
|
+
import type { LoggerContract } from '@ioc:Adonis/Core/Logger';
|
|
4
4
|
import type {
|
|
5
5
|
ConnectionContract,
|
|
6
6
|
ConnectionManagerContract,
|
|
@@ -78,6 +78,8 @@ export class ConnectionManager implements ConnectionManagerContract {
|
|
|
78
78
|
|
|
79
79
|
public connect(connectionName: string): void {
|
|
80
80
|
const connection = this.validateConnection(connectionName);
|
|
81
|
+
// Connection error is handled by the `error` event listener.
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
81
83
|
connection.connection.connect();
|
|
82
84
|
}
|
|
83
85
|
|
package/src/Database/Database.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ClientSession, Db, TransactionOptions } from 'mongodb';
|
|
1
|
+
import type { ClientSession, Db, TransactionOptions } from 'mongodb';
|
|
2
2
|
|
|
3
|
-
import { LoggerContract } from '@ioc:Adonis/Core/Logger';
|
|
3
|
+
import type { LoggerContract } from '@ioc:Adonis/Core/Logger';
|
|
4
4
|
import type {
|
|
5
5
|
ConnectionContract,
|
|
6
6
|
ConnectionManagerContract,
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
|
|
3
|
+
import type { ClientSession, Db } from 'mongodb';
|
|
4
|
+
|
|
5
|
+
export interface TransactionEvents {
|
|
6
|
+
commit: [session: ClientSession, db: Db];
|
|
7
|
+
abort: [session: ClientSession, db: Db, error?: Error];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class TransactionEventEmitter extends EventEmitter<TransactionEvents> {}
|
package/src/Migration.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Logger } from '@poppinss/cliui/build/src/Logger';
|
|
2
|
-
import {
|
|
3
|
-
CreateIndexesOptions,
|
|
1
|
+
import type { Logger } from '@poppinss/cliui/build/src/Logger';
|
|
2
|
+
import type {
|
|
4
3
|
ClientSession,
|
|
4
|
+
CreateIndexesOptions,
|
|
5
5
|
Db,
|
|
6
|
-
IndexSpecification,
|
|
7
6
|
DropIndexesOptions,
|
|
7
|
+
IndexSpecification,
|
|
8
8
|
} from 'mongodb';
|
|
9
9
|
|
|
10
10
|
import type {
|
|
@@ -13,12 +13,18 @@ import type {
|
|
|
13
13
|
} from '@ioc:Zakodium/Mongodb/Database';
|
|
14
14
|
|
|
15
15
|
enum MigrationType {
|
|
16
|
+
DropCollection = 'DropCollection',
|
|
16
17
|
CreateCollection = 'CreateCollection',
|
|
17
18
|
DropIndex = 'DropIndex',
|
|
18
19
|
CreateIndex = 'CreateIndex',
|
|
19
20
|
Custom = 'Custom',
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
interface DropCollectionOperation {
|
|
24
|
+
type: MigrationType.DropCollection;
|
|
25
|
+
collectionName: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
22
28
|
interface CreateCollectionOperation {
|
|
23
29
|
type: MigrationType.CreateCollection;
|
|
24
30
|
collectionName: string;
|
|
@@ -44,6 +50,7 @@ interface CustomOperation {
|
|
|
44
50
|
}
|
|
45
51
|
|
|
46
52
|
type MigrationOperation =
|
|
53
|
+
| DropCollectionOperation
|
|
47
54
|
| CreateCollectionOperation
|
|
48
55
|
| DropIndexOperation
|
|
49
56
|
| CreateIndexOperation
|
|
@@ -68,6 +75,13 @@ export default function createMigration(Database: DatabaseContract): any {
|
|
|
68
75
|
}
|
|
69
76
|
}
|
|
70
77
|
|
|
78
|
+
public dropCollection(collectionName: string): void {
|
|
79
|
+
this.$operations.push({
|
|
80
|
+
type: MigrationType.DropCollection,
|
|
81
|
+
collectionName,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
71
85
|
public createCollection(collectionName: string): void {
|
|
72
86
|
this.$operations.push({
|
|
73
87
|
type: MigrationType.CreateCollection,
|
|
@@ -114,6 +128,7 @@ export default function createMigration(Database: DatabaseContract): any {
|
|
|
114
128
|
await this._dropIndexes(session);
|
|
115
129
|
await this._createIndexes(session);
|
|
116
130
|
await this._executeDeferred(session);
|
|
131
|
+
await this._dropCollections();
|
|
117
132
|
}
|
|
118
133
|
|
|
119
134
|
private async _listCollections() {
|
|
@@ -128,6 +143,14 @@ export default function createMigration(Database: DatabaseContract): any {
|
|
|
128
143
|
return this.$collectionList;
|
|
129
144
|
}
|
|
130
145
|
|
|
146
|
+
private async _dropCollections(): Promise<void> {
|
|
147
|
+
const db = await this.$connection.database();
|
|
148
|
+
for (const op of this.$operations.filter(isDropCollection)) {
|
|
149
|
+
this.$logger.info(`Dropping collection ${op.collectionName}`);
|
|
150
|
+
await db.dropCollection(op.collectionName);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
131
154
|
private async _createCollections(session: ClientSession): Promise<void> {
|
|
132
155
|
const db = await this.$connection.database();
|
|
133
156
|
for (const op of this.$operations.filter(isCreateCollection)) {
|
|
@@ -179,6 +202,12 @@ export default function createMigration(Database: DatabaseContract): any {
|
|
|
179
202
|
return Migration;
|
|
180
203
|
}
|
|
181
204
|
|
|
205
|
+
function isDropCollection(
|
|
206
|
+
op: MigrationOperation,
|
|
207
|
+
): op is DropCollectionOperation {
|
|
208
|
+
return op.type === MigrationType.DropCollection;
|
|
209
|
+
}
|
|
210
|
+
|
|
182
211
|
function isCreateCollection(
|
|
183
212
|
op: MigrationOperation,
|
|
184
213
|
): op is CreateCollectionOperation {
|
package/src/Model/Model.ts
CHANGED
|
@@ -2,7 +2,7 @@ import assert from 'node:assert';
|
|
|
2
2
|
|
|
3
3
|
import { defineStaticProperty, Exception } from '@poppinss/utils';
|
|
4
4
|
import { cloneDeep, isEqual, pickBy, snakeCase } from 'lodash';
|
|
5
|
-
import {
|
|
5
|
+
import type {
|
|
6
6
|
BulkWriteOptions,
|
|
7
7
|
ClientSession,
|
|
8
8
|
Collection,
|
|
@@ -19,18 +19,18 @@ import {
|
|
|
19
19
|
} from 'mongodb';
|
|
20
20
|
import pluralize from 'pluralize';
|
|
21
21
|
|
|
22
|
-
import { DatabaseContract } from '@ioc:Zakodium/Mongodb/Database';
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
ModelAttributes,
|
|
22
|
+
import type { DatabaseContract } from '@ioc:Zakodium/Mongodb/Database';
|
|
23
|
+
import type {
|
|
24
|
+
ComputedOptions,
|
|
25
|
+
FieldOptions,
|
|
26
|
+
ForbiddenQueryOptions,
|
|
28
27
|
ModelAdapterOptions,
|
|
28
|
+
ModelAttributes,
|
|
29
29
|
ModelDocumentOptions,
|
|
30
|
-
|
|
30
|
+
MongodbDocument,
|
|
31
|
+
NoExtraProperties,
|
|
32
|
+
QueryContract,
|
|
31
33
|
QuerySortObject,
|
|
32
|
-
ForbiddenQueryOptions,
|
|
33
|
-
ComputedOptions,
|
|
34
34
|
} from '@ioc:Zakodium/Mongodb/Odm';
|
|
35
35
|
|
|
36
36
|
import { proxyHandler } from './proxyHandler';
|
|
@@ -200,7 +200,9 @@ class Query<ModelType extends typeof BaseModel>
|
|
|
200
200
|
public async explain(verbosity?: ExplainVerbosityLike): Promise<Document> {
|
|
201
201
|
const collection = await this.ModelConstructor.getCollection();
|
|
202
202
|
const driverOptions = this.getDriverOptions();
|
|
203
|
-
return collection
|
|
203
|
+
return collection
|
|
204
|
+
.find(this.filter, driverOptions)
|
|
205
|
+
.explain(verbosity as ExplainVerbosityLike);
|
|
204
206
|
}
|
|
205
207
|
|
|
206
208
|
public async *[Symbol.asyncIterator](): AsyncIterableIterator<
|
|
@@ -239,10 +241,6 @@ function ensureSort(options?: FindOptions): void {
|
|
|
239
241
|
};
|
|
240
242
|
}
|
|
241
243
|
|
|
242
|
-
function hasOwn(object: unknown, key: string): boolean {
|
|
243
|
-
return Object.prototype.hasOwnProperty.call(object, key);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
244
|
interface DataToSet {
|
|
247
245
|
[key: string]: unknown;
|
|
248
246
|
createdAt: Date;
|
|
@@ -358,7 +356,7 @@ export class BaseModel {
|
|
|
358
356
|
* Define the property when not defined on self. This makes sure that all
|
|
359
357
|
* subclasses boot on their own.
|
|
360
358
|
*/
|
|
361
|
-
if (!hasOwn(this, 'booted')) {
|
|
359
|
+
if (!Object.hasOwn(this, 'booted')) {
|
|
362
360
|
this.booted = false;
|
|
363
361
|
}
|
|
364
362
|
|
|
@@ -775,7 +773,7 @@ export class BaseModel {
|
|
|
775
773
|
}
|
|
776
774
|
|
|
777
775
|
export class BaseAutoIncrementModel extends BaseModel {
|
|
778
|
-
public readonly _id: number;
|
|
776
|
+
declare public readonly _id: number;
|
|
779
777
|
|
|
780
778
|
public async save(
|
|
781
779
|
options?: ModelDocumentOptions<InsertOneOptions>,
|
package/src/Odm/decorators.ts
CHANGED