@mikro-orm/mongodb 7.0.0-dev.8 → 7.0.0-dev.80
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/MongoConnection.d.ts +8 -4
- package/MongoConnection.js +51 -26
- package/MongoDriver.d.ts +7 -1
- package/MongoDriver.js +69 -16
- package/MongoEntityManager.d.ts +9 -1
- package/MongoEntityManager.js +18 -2
- package/MongoExceptionConverter.d.ts +1 -1
- package/MongoExceptionConverter.js +2 -3
- package/MongoMikroORM.d.ts +10 -7
- package/MongoMikroORM.js +12 -8
- package/MongoPlatform.d.ts +2 -4
- package/MongoPlatform.js +3 -9
- package/MongoSchemaGenerator.d.ts +6 -4
- package/MongoSchemaGenerator.js +46 -22
- package/README.md +3 -2
- package/index.d.ts +1 -1
- package/package.json +5 -5
package/MongoConnection.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { type ClientSession, type Collection, type Db, MongoClient, type MongoClientOptions, type TransactionOptions } from 'mongodb';
|
|
2
|
+
import { type AnyEntity, type Configuration, Connection, type ConnectionOptions, type ConnectionType, type EntityData, type EntityName, type FilterQuery, type IsolationLevel, type LoggingOptions, type QueryOrderMap, type QueryResult, type Transaction, type TransactionEventBroadcaster, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
|
|
3
3
|
export declare class MongoConnection extends Connection {
|
|
4
4
|
protected client: MongoClient;
|
|
5
5
|
protected db: Db;
|
|
6
6
|
constructor(config: Configuration, options?: ConnectionOptions, type?: ConnectionType);
|
|
7
|
-
connect(
|
|
7
|
+
connect(options?: {
|
|
8
|
+
skipOnConnect?: boolean;
|
|
9
|
+
}): Promise<void>;
|
|
8
10
|
close(force?: boolean): Promise<void>;
|
|
9
11
|
isConnected(): Promise<boolean>;
|
|
10
12
|
checkConnection(): Promise<{
|
|
@@ -20,16 +22,18 @@ export declare class MongoConnection extends Connection {
|
|
|
20
22
|
listCollections(): Promise<string[]>;
|
|
21
23
|
dropCollection(name: EntityName<AnyEntity>): Promise<boolean>;
|
|
22
24
|
mapOptions(overrides: MongoClientOptions): MongoClientOptions;
|
|
23
|
-
getClientUrl(): string;
|
|
24
25
|
getDb(): Db;
|
|
25
26
|
execute(query: string): Promise<any>;
|
|
26
27
|
find<T extends object>(collection: string, where: FilterQuery<T>, orderBy?: QueryOrderMap<T> | QueryOrderMap<T>[], limit?: number, offset?: number, fields?: string[], ctx?: Transaction<ClientSession>, loggerContext?: LoggingOptions): Promise<EntityData<T>[]>;
|
|
28
|
+
stream<T extends object>(collection: string, where: FilterQuery<T>, orderBy?: QueryOrderMap<T> | QueryOrderMap<T>[], limit?: number, offset?: number, fields?: string[], ctx?: Transaction<ClientSession>, loggerContext?: LoggingOptions): AsyncIterableIterator<T>;
|
|
29
|
+
private _find;
|
|
27
30
|
insertOne<T extends object>(collection: string, data: Partial<T>, ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
|
|
28
31
|
insertMany<T extends object>(collection: string, data: Partial<T>[], ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
|
|
29
32
|
updateMany<T extends object>(collection: string, where: FilterQuery<T>, data: Partial<T>, ctx?: Transaction<ClientSession>, upsert?: boolean, upsertOptions?: UpsertOptions<T>): Promise<QueryResult<T>>;
|
|
30
33
|
bulkUpdateMany<T extends object>(collection: string, where: FilterQuery<T>[], data: Partial<T>[], ctx?: Transaction<ClientSession>, upsert?: boolean, upsertOptions?: UpsertManyOptions<T>): Promise<QueryResult<T>>;
|
|
31
34
|
deleteMany<T extends object>(collection: string, where: FilterQuery<T>, ctx?: Transaction<ClientSession>): Promise<QueryResult<T>>;
|
|
32
35
|
aggregate<T extends object = any>(collection: string, pipeline: any[], ctx?: Transaction<ClientSession>, loggerContext?: LoggingOptions): Promise<T[]>;
|
|
36
|
+
streamAggregate<T extends object>(collection: string, pipeline: any[], ctx?: Transaction<ClientSession>, loggerContext?: LoggingOptions, stream?: boolean): AsyncIterableIterator<T>;
|
|
33
37
|
countDocuments<T extends object>(collection: string, where: FilterQuery<T>, ctx?: Transaction<ClientSession>): Promise<number>;
|
|
34
38
|
transactional<T>(cb: (trx: Transaction<ClientSession>) => Promise<T>, options?: {
|
|
35
39
|
isolationLevel?: IsolationLevel;
|
package/MongoConnection.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MongoClient, ObjectId, } from 'mongodb';
|
|
2
2
|
import { inspect } from 'node:util';
|
|
3
3
|
import { Connection, EventType, QueryOrder, Utils, ValidationError, } from '@mikro-orm/core';
|
|
4
4
|
export class MongoConnection extends Connection {
|
|
@@ -15,7 +15,7 @@ export class MongoConnection extends Connection {
|
|
|
15
15
|
return `ISODate('${this.toISOString()}')`;
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
-
async connect() {
|
|
18
|
+
async connect(options) {
|
|
19
19
|
let driverOptions = this.options.driverOptions ?? this.config.get('driverOptions');
|
|
20
20
|
if (typeof driverOptions === 'function') {
|
|
21
21
|
driverOptions = await driverOptions();
|
|
@@ -25,19 +25,22 @@ export class MongoConnection extends Connection {
|
|
|
25
25
|
this.client = driverOptions;
|
|
26
26
|
}
|
|
27
27
|
else {
|
|
28
|
-
this.client = new MongoClient(this.config.
|
|
28
|
+
this.client = new MongoClient(this.config.get('clientUrl'), this.mapOptions(driverOptions));
|
|
29
29
|
await this.client.connect();
|
|
30
30
|
const onCreateConnection = this.options.onCreateConnection ?? this.config.get('onCreateConnection');
|
|
31
|
-
/* v8 ignore next
|
|
31
|
+
/* v8 ignore next */
|
|
32
32
|
this.client.on('connectionCreated', () => {
|
|
33
33
|
void onCreateConnection?.(this.client);
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
this.db = this.client.db(this.config.get('dbName'));
|
|
37
37
|
this.connected = true;
|
|
38
|
+
if (options?.skipOnConnect !== true) {
|
|
39
|
+
await this.onConnect();
|
|
40
|
+
}
|
|
38
41
|
}
|
|
39
42
|
async close(force) {
|
|
40
|
-
await this.client?.close(
|
|
43
|
+
await this.client?.close(force);
|
|
41
44
|
this.connected = false;
|
|
42
45
|
}
|
|
43
46
|
async isConnected() {
|
|
@@ -96,12 +99,6 @@ export class MongoConnection extends Connection {
|
|
|
96
99
|
};
|
|
97
100
|
return Utils.mergeConfig(ret, overrides);
|
|
98
101
|
}
|
|
99
|
-
getClientUrl() {
|
|
100
|
-
const options = this.mapOptions(this.options.driverOptions ?? {});
|
|
101
|
-
const clientUrl = this.config.getClientUrl(true);
|
|
102
|
-
const match = clientUrl.match(/^(\w+):\/\/((.*@.+)|.+)$/);
|
|
103
|
-
return match ? `${match[1]}://${options.auth ? options.auth.username + ':*****@' : ''}${match[2]}` : clientUrl;
|
|
104
|
-
}
|
|
105
102
|
getDb() {
|
|
106
103
|
return this.db;
|
|
107
104
|
}
|
|
@@ -109,6 +106,18 @@ export class MongoConnection extends Connection {
|
|
|
109
106
|
throw new Error(`${this.constructor.name} does not support generic execute method`);
|
|
110
107
|
}
|
|
111
108
|
async find(collection, where, orderBy, limit, offset, fields, ctx, loggerContext) {
|
|
109
|
+
const { cursor, query } = await this._find(collection, where, orderBy, limit, offset, fields, ctx, loggerContext);
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
const res = await cursor.toArray();
|
|
112
|
+
this.logQuery(`${query}.toArray();`, { took: Date.now() - now, results: res.length, ...loggerContext });
|
|
113
|
+
return res;
|
|
114
|
+
}
|
|
115
|
+
async *stream(collection, where, orderBy, limit, offset, fields, ctx, loggerContext) {
|
|
116
|
+
const { cursor, query } = await this._find(collection, where, orderBy, limit, offset, fields, ctx, loggerContext);
|
|
117
|
+
this.logQuery(`${query}.toArray();`, loggerContext);
|
|
118
|
+
yield* cursor;
|
|
119
|
+
}
|
|
120
|
+
async _find(collection, where, orderBy, limit, offset, fields, ctx, loggerContext) {
|
|
112
121
|
await this.ensureConnection();
|
|
113
122
|
collection = this.getCollectionName(collection);
|
|
114
123
|
const options = ctx ? { session: ctx } : {};
|
|
@@ -123,12 +132,11 @@ export class MongoConnection extends Connection {
|
|
|
123
132
|
orderBy.forEach(o => {
|
|
124
133
|
Utils.keys(o).forEach(k => {
|
|
125
134
|
const direction = o[k];
|
|
126
|
-
orderByTuples.push([k.toString(),
|
|
135
|
+
orderByTuples.push([k.toString(), typeof direction === 'string' ? direction.toUpperCase() === QueryOrder.ASC ? 1 : -1 : direction]);
|
|
127
136
|
});
|
|
128
137
|
});
|
|
129
138
|
if (orderByTuples.length > 0) {
|
|
130
139
|
query += `.sort(${this.logObject(orderByTuples)})`;
|
|
131
|
-
// @ts-expect-error ??
|
|
132
140
|
resultSet.sort(orderByTuples);
|
|
133
141
|
}
|
|
134
142
|
}
|
|
@@ -140,10 +148,7 @@ export class MongoConnection extends Connection {
|
|
|
140
148
|
query += `.skip(${offset})`;
|
|
141
149
|
resultSet.skip(offset);
|
|
142
150
|
}
|
|
143
|
-
|
|
144
|
-
const res = await resultSet.toArray();
|
|
145
|
-
this.logQuery(`${query}.toArray();`, { took: Date.now() - now, results: res.length, ...loggerContext });
|
|
146
|
-
return res;
|
|
151
|
+
return { cursor: resultSet, query };
|
|
147
152
|
}
|
|
148
153
|
async insertOne(collection, data, ctx) {
|
|
149
154
|
return this.runQuery('insertOne', collection, data, undefined, ctx);
|
|
@@ -171,6 +176,16 @@ export class MongoConnection extends Connection {
|
|
|
171
176
|
this.logQuery(query, { took: Date.now() - now, results: res.length, ...loggerContext });
|
|
172
177
|
return res;
|
|
173
178
|
}
|
|
179
|
+
async *streamAggregate(collection, pipeline, ctx, loggerContext, stream = false) {
|
|
180
|
+
await this.ensureConnection();
|
|
181
|
+
collection = this.getCollectionName(collection);
|
|
182
|
+
/* v8 ignore next */
|
|
183
|
+
const options = ctx ? { session: ctx } : {};
|
|
184
|
+
const query = `db.getCollection('${collection}').aggregate(${this.logObject(pipeline)}, ${this.logObject(options)})};`;
|
|
185
|
+
const cursor = this.getCollection(collection).aggregate(pipeline, options);
|
|
186
|
+
this.logQuery(query, { ...loggerContext });
|
|
187
|
+
yield* cursor;
|
|
188
|
+
}
|
|
174
189
|
async countDocuments(collection, where, ctx) {
|
|
175
190
|
return this.runQuery('countDocuments', collection, undefined, where, ctx);
|
|
176
191
|
}
|
|
@@ -292,12 +307,19 @@ export class MongoConnection extends Connection {
|
|
|
292
307
|
createUpdatePayload(row, upsertOptions) {
|
|
293
308
|
const doc = { $set: row };
|
|
294
309
|
const $unset = {};
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
310
|
+
const $inc = {};
|
|
311
|
+
for (const k of Utils.keys(row)) {
|
|
312
|
+
const item = row[k];
|
|
313
|
+
if (typeof item === 'undefined') {
|
|
314
|
+
$unset[k] = '';
|
|
315
|
+
delete row[k];
|
|
316
|
+
continue;
|
|
317
|
+
}
|
|
318
|
+
if (Utils.isPlainObject(item) && '$inc' in item) {
|
|
319
|
+
$inc[k] = item.$inc;
|
|
320
|
+
delete row[k];
|
|
321
|
+
}
|
|
322
|
+
}
|
|
301
323
|
if (upsertOptions) {
|
|
302
324
|
if (upsertOptions.onConflictAction === 'ignore') {
|
|
303
325
|
doc.$setOnInsert = doc.$set;
|
|
@@ -323,9 +345,12 @@ export class MongoConnection extends Connection {
|
|
|
323
345
|
}
|
|
324
346
|
if (Utils.hasObjectKeys($unset)) {
|
|
325
347
|
doc.$unset = $unset;
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
348
|
+
}
|
|
349
|
+
if (Utils.hasObjectKeys($inc)) {
|
|
350
|
+
doc.$inc = $inc;
|
|
351
|
+
}
|
|
352
|
+
if (!Utils.hasObjectKeys(doc.$set)) {
|
|
353
|
+
delete doc.$set;
|
|
329
354
|
}
|
|
330
355
|
return doc;
|
|
331
356
|
}
|
package/MongoDriver.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ClientSession } from 'mongodb';
|
|
2
|
-
import { type Configuration, type CountOptions, DatabaseDriver, type EntityData, type EntityDictionary, type EntityField, EntityManagerType, type FilterQuery, type FindOneOptions, type FindOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type PopulateOptions, type PopulatePath, type QueryResult, type Transaction, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
|
|
2
|
+
import { type Configuration, type CountOptions, DatabaseDriver, type EntityData, type EntityDictionary, type EntityField, EntityManagerType, type EntityName, type FilterQuery, type FindOneOptions, type FindOptions, type NativeInsertUpdateManyOptions, type NativeInsertUpdateOptions, type PopulateOptions, type PopulatePath, type QueryResult, type StreamOptions, type Transaction, type UpsertManyOptions, type UpsertOptions } from '@mikro-orm/core';
|
|
3
3
|
import { MongoConnection } from './MongoConnection.js';
|
|
4
4
|
import { MongoPlatform } from './MongoPlatform.js';
|
|
5
5
|
import { MongoEntityManager } from './MongoEntityManager.js';
|
|
@@ -9,9 +9,13 @@ export declare class MongoDriver extends DatabaseDriver<MongoConnection> {
|
|
|
9
9
|
protected readonly platform: MongoPlatform;
|
|
10
10
|
constructor(config: Configuration);
|
|
11
11
|
createEntityManager(useContext?: boolean): this[typeof EntityManagerType];
|
|
12
|
+
stream<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: StreamOptions<T, any, any, any> & {
|
|
13
|
+
rawResults?: boolean;
|
|
14
|
+
}): AsyncIterableIterator<T>;
|
|
12
15
|
find<T extends object, P extends string = never, F extends string = '*', E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOptions<T, P, F, E>): Promise<EntityData<T>[]>;
|
|
13
16
|
findOne<T extends object, P extends string = never, F extends string = PopulatePath.ALL, E extends string = never>(entityName: string, where: FilterQuery<T>, options?: FindOneOptions<T, P, F, E>): Promise<EntityData<T> | null>;
|
|
14
17
|
findVirtual<T extends object>(entityName: string, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): Promise<EntityData<T>[]>;
|
|
18
|
+
streamVirtual<T extends object>(entityName: EntityName<T>, where: FilterQuery<T>, options: FindOptions<T, any, any, any>): AsyncIterableIterator<EntityData<T>>;
|
|
15
19
|
count<T extends object>(entityName: string, where: FilterQuery<T>, options?: CountOptions<T>, ctx?: Transaction<ClientSession>): Promise<number>;
|
|
16
20
|
nativeInsert<T extends object>(entityName: string, data: EntityDictionary<T>, options?: NativeInsertUpdateOptions<T>): Promise<QueryResult<T>>;
|
|
17
21
|
nativeInsertMany<T extends object>(entityName: string, data: EntityDictionary<T>[], options?: NativeInsertUpdateManyOptions<T>): Promise<QueryResult<T>>;
|
|
@@ -21,9 +25,11 @@ export declare class MongoDriver extends DatabaseDriver<MongoConnection> {
|
|
|
21
25
|
ctx?: Transaction<ClientSession>;
|
|
22
26
|
}): Promise<QueryResult<T>>;
|
|
23
27
|
aggregate(entityName: string, pipeline: any[], ctx?: Transaction<ClientSession>): Promise<any[]>;
|
|
28
|
+
streamAggregate<T extends object>(entityName: string, pipeline: any[], ctx?: Transaction<ClientSession>): AsyncIterableIterator<T>;
|
|
24
29
|
getPlatform(): MongoPlatform;
|
|
25
30
|
private renameFields;
|
|
26
31
|
private convertObjectIds;
|
|
27
32
|
private buildFilterById;
|
|
28
33
|
protected buildFields<T extends object, P extends string = never>(entityName: string, populate: PopulateOptions<T>[], fields?: readonly EntityField<T, P>[], exclude?: string[]): string[] | undefined;
|
|
34
|
+
private handleVersionProperty;
|
|
29
35
|
}
|
package/MongoDriver.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ObjectId } from 'mongodb';
|
|
2
|
-
import { DatabaseDriver, EntityManagerType, ReferenceKind, Utils, } from '@mikro-orm/core';
|
|
2
|
+
import { DatabaseDriver, EntityManagerType, GroupOperator, ReferenceKind, Utils, } from '@mikro-orm/core';
|
|
3
3
|
import { MongoConnection } from './MongoConnection.js';
|
|
4
4
|
import { MongoPlatform } from './MongoPlatform.js';
|
|
5
5
|
import { MongoEntityManager } from './MongoEntityManager.js';
|
|
@@ -14,6 +14,25 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
14
14
|
const EntityManagerClass = this.config.get('entityManager', MongoEntityManager);
|
|
15
15
|
return new EntityManagerClass(this.config, this, this.metadata, useContext);
|
|
16
16
|
}
|
|
17
|
+
async *stream(entityName, where, options) {
|
|
18
|
+
if (this.metadata.find(entityName)?.virtual) {
|
|
19
|
+
yield* this.streamVirtual(entityName, where, options);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
entityName = Utils.className(entityName);
|
|
23
|
+
const fields = this.buildFields(entityName, options.populate || [], options.fields, options.exclude);
|
|
24
|
+
where = this.renameFields(entityName, where, true);
|
|
25
|
+
const orderBy = Utils.asArray(options.orderBy).map(orderBy => this.renameFields(entityName, orderBy, true));
|
|
26
|
+
const res = this.getConnection('read').stream(entityName, where, orderBy, options.limit, options.offset, fields, options.ctx);
|
|
27
|
+
for await (const item of res) {
|
|
28
|
+
if (options.rawResults) {
|
|
29
|
+
yield item;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
yield this.mapResult(item, this.metadata.find(entityName));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
17
36
|
async find(entityName, where, options = {}) {
|
|
18
37
|
if (this.metadata.find(entityName)?.virtual) {
|
|
19
38
|
return this.findVirtual(entityName, where, options);
|
|
@@ -70,8 +89,19 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
70
89
|
/* v8 ignore next */
|
|
71
90
|
return super.findVirtual(entityName, where, options);
|
|
72
91
|
}
|
|
92
|
+
async *streamVirtual(entityName, where, options) {
|
|
93
|
+
const meta = this.metadata.find(entityName);
|
|
94
|
+
if (meta.expression instanceof Function) {
|
|
95
|
+
const em = this.createEntityManager();
|
|
96
|
+
const stream = await meta.expression(em, where, options, true);
|
|
97
|
+
yield* stream;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
/* v8 ignore next */
|
|
101
|
+
return super.findVirtual(entityName, where, options);
|
|
102
|
+
}
|
|
73
103
|
async count(entityName, where, options = {}, ctx) {
|
|
74
|
-
/* v8 ignore next
|
|
104
|
+
/* v8 ignore next */
|
|
75
105
|
if (this.metadata.find(entityName)?.virtual) {
|
|
76
106
|
return this.countVirtual(entityName, where, options);
|
|
77
107
|
}
|
|
@@ -79,11 +109,15 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
79
109
|
return this.rethrow(this.getConnection('read').countDocuments(entityName, where, ctx));
|
|
80
110
|
}
|
|
81
111
|
async nativeInsert(entityName, data, options = {}) {
|
|
112
|
+
this.handleVersionProperty(entityName, data);
|
|
82
113
|
data = this.renameFields(entityName, data);
|
|
83
114
|
return this.rethrow(this.getConnection('write').insertOne(entityName, data, options.ctx));
|
|
84
115
|
}
|
|
85
116
|
async nativeInsertMany(entityName, data, options = {}) {
|
|
86
|
-
data = data.map(
|
|
117
|
+
data = data.map(item => {
|
|
118
|
+
this.handleVersionProperty(entityName, item);
|
|
119
|
+
return this.renameFields(entityName, item);
|
|
120
|
+
});
|
|
87
121
|
const meta = this.metadata.find(entityName);
|
|
88
122
|
/* v8 ignore next */
|
|
89
123
|
const pk = meta?.getPrimaryProps()[0].fieldNames[0] ?? '_id';
|
|
@@ -95,8 +129,9 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
95
129
|
if (Utils.isPrimaryKey(where)) {
|
|
96
130
|
where = this.buildFilterById(entityName, where);
|
|
97
131
|
}
|
|
98
|
-
|
|
132
|
+
this.handleVersionProperty(entityName, data, true);
|
|
99
133
|
data = this.renameFields(entityName, data);
|
|
134
|
+
where = this.renameFields(entityName, where, true);
|
|
100
135
|
options = { ...options };
|
|
101
136
|
const meta = this.metadata.find(entityName);
|
|
102
137
|
/* v8 ignore next */
|
|
@@ -119,7 +154,10 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
119
154
|
}
|
|
120
155
|
return row;
|
|
121
156
|
});
|
|
122
|
-
data = data.map(row =>
|
|
157
|
+
data = data.map(row => {
|
|
158
|
+
this.handleVersionProperty(entityName, row, true);
|
|
159
|
+
return this.renameFields(entityName, row);
|
|
160
|
+
});
|
|
123
161
|
options = { ...options };
|
|
124
162
|
const meta = this.metadata.find(entityName);
|
|
125
163
|
/* v8 ignore next */
|
|
@@ -157,6 +195,9 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
157
195
|
async aggregate(entityName, pipeline, ctx) {
|
|
158
196
|
return this.rethrow(this.getConnection('read').aggregate(entityName, pipeline, ctx));
|
|
159
197
|
}
|
|
198
|
+
async *streamAggregate(entityName, pipeline, ctx) {
|
|
199
|
+
yield* this.getConnection('read').streamAggregate(entityName, pipeline, ctx);
|
|
200
|
+
}
|
|
160
201
|
getPlatform() {
|
|
161
202
|
return this.platform;
|
|
162
203
|
}
|
|
@@ -176,7 +217,7 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
176
217
|
for (let i = 0; i < copiedData.$and.length; i++) {
|
|
177
218
|
const and = copiedData.$and[i];
|
|
178
219
|
if ('$fulltext' in and) {
|
|
179
|
-
/* v8 ignore next
|
|
220
|
+
/* v8 ignore next */
|
|
180
221
|
if ('$fulltext' in copiedData) {
|
|
181
222
|
throw new Error('Cannot merge multiple $fulltext conditions to top level of the query object.');
|
|
182
223
|
}
|
|
@@ -196,8 +237,8 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
196
237
|
throw new Error('Full text search is only supported on the top level of the query object.');
|
|
197
238
|
}
|
|
198
239
|
Utils.keys(copiedData).forEach(k => {
|
|
199
|
-
if (
|
|
200
|
-
/* v8 ignore next
|
|
240
|
+
if (k in GroupOperator) {
|
|
241
|
+
/* v8 ignore next */
|
|
201
242
|
if (Array.isArray(copiedData[k])) {
|
|
202
243
|
copiedData[k] = copiedData[k].map(v => this.renameFields(entityName, v));
|
|
203
244
|
}
|
|
@@ -210,7 +251,7 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
210
251
|
const prop = meta.properties[k];
|
|
211
252
|
let isObjectId = false;
|
|
212
253
|
if (prop.kind === ReferenceKind.SCALAR) {
|
|
213
|
-
isObjectId = prop.type
|
|
254
|
+
isObjectId = prop.type === 'ObjectId';
|
|
214
255
|
}
|
|
215
256
|
else if (prop.kind === ReferenceKind.EMBEDDED) {
|
|
216
257
|
if (copiedData[prop.name] == null) {
|
|
@@ -226,7 +267,7 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
226
267
|
else {
|
|
227
268
|
const meta2 = this.metadata.find(prop.type);
|
|
228
269
|
const pk = meta2.properties[meta2.primaryKeys[0]];
|
|
229
|
-
isObjectId = pk.type
|
|
270
|
+
isObjectId = pk.type === 'ObjectId';
|
|
230
271
|
}
|
|
231
272
|
if (isObjectId) {
|
|
232
273
|
copiedData[k] = this.convertObjectIds(copiedData[k]);
|
|
@@ -245,7 +286,7 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
245
286
|
if (data instanceof ObjectId) {
|
|
246
287
|
return data;
|
|
247
288
|
}
|
|
248
|
-
if (
|
|
289
|
+
if (typeof data === 'string' && data.match(/^[0-9a-f]{24}$/i)) {
|
|
249
290
|
return new ObjectId(data);
|
|
250
291
|
}
|
|
251
292
|
if (Array.isArray(data)) {
|
|
@@ -260,7 +301,7 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
260
301
|
}
|
|
261
302
|
buildFilterById(entityName, id) {
|
|
262
303
|
const meta = this.metadata.find(entityName);
|
|
263
|
-
if (meta.properties[meta.primaryKeys[0]].type
|
|
304
|
+
if (meta.properties[meta.primaryKeys[0]].type === 'ObjectId') {
|
|
264
305
|
return { _id: new ObjectId(id) };
|
|
265
306
|
}
|
|
266
307
|
return { _id: id };
|
|
@@ -270,11 +311,11 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
270
311
|
if (!meta) {
|
|
271
312
|
return fields;
|
|
272
313
|
}
|
|
273
|
-
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p =>
|
|
314
|
+
const lazyProps = meta.props.filter(prop => prop.lazy && !populate.some(p => this.isPopulated(meta, prop, p)));
|
|
274
315
|
const ret = [];
|
|
275
316
|
if (fields) {
|
|
276
317
|
for (let field of fields) {
|
|
277
|
-
/* v8 ignore next
|
|
318
|
+
/* v8 ignore next */
|
|
278
319
|
if (Utils.isPlainObject(field)) {
|
|
279
320
|
continue;
|
|
280
321
|
}
|
|
@@ -282,7 +323,7 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
282
323
|
field = field.toString().substring(0, field.toString().indexOf('.'));
|
|
283
324
|
}
|
|
284
325
|
let prop = meta.properties[field];
|
|
285
|
-
/* v8 ignore
|
|
326
|
+
/* v8 ignore next */
|
|
286
327
|
if (prop) {
|
|
287
328
|
if (!prop.fieldNames) {
|
|
288
329
|
continue;
|
|
@@ -297,7 +338,6 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
297
338
|
else {
|
|
298
339
|
ret.push(field);
|
|
299
340
|
}
|
|
300
|
-
/* v8 ignore stop */
|
|
301
341
|
}
|
|
302
342
|
ret.unshift(...meta.primaryKeys.filter(pk => !fields.includes(pk)));
|
|
303
343
|
}
|
|
@@ -307,4 +347,17 @@ export class MongoDriver extends DatabaseDriver {
|
|
|
307
347
|
}
|
|
308
348
|
return ret.length > 0 ? ret : undefined;
|
|
309
349
|
}
|
|
350
|
+
handleVersionProperty(entityName, data, update = false) {
|
|
351
|
+
const meta = this.metadata.find(entityName);
|
|
352
|
+
if (!meta?.versionProperty) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
const versionProperty = meta.properties[meta.versionProperty];
|
|
356
|
+
if (versionProperty.runtimeType === 'Date') {
|
|
357
|
+
data[versionProperty.name] ??= new Date();
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
data[versionProperty.name] ??= update ? { $inc: 1 } : 1;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
310
363
|
}
|
package/MongoEntityManager.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityManager, type EntityName, type EntityRepository, type GetRepository, type TransactionOptions } from '@mikro-orm/core';
|
|
1
|
+
import { EntityManager, type EntityName, type EntityRepository, type GetRepository, type TransactionOptions, type StreamOptions, type NoInfer, type Loaded } from '@mikro-orm/core';
|
|
2
2
|
import type { Collection, Document, TransactionOptions as MongoTransactionOptions } from 'mongodb';
|
|
3
3
|
import type { MongoDriver } from './MongoDriver.js';
|
|
4
4
|
import type { MongoEntityRepository } from './MongoEntityRepository.js';
|
|
@@ -10,6 +10,14 @@ export declare class MongoEntityManager<Driver extends MongoDriver = MongoDriver
|
|
|
10
10
|
* Shortcut to driver's aggregate method. Available in MongoDriver only.
|
|
11
11
|
*/
|
|
12
12
|
aggregate(entityName: EntityName<any>, pipeline: any[]): Promise<any[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Shortcut to driver's aggregate method. Returns a stream. Available in MongoDriver only.
|
|
15
|
+
*/
|
|
16
|
+
streamAggregate<T extends object>(entityName: EntityName<any>, pipeline: any[]): AsyncIterableIterator<T>;
|
|
17
|
+
/**
|
|
18
|
+
* @inheritDoc
|
|
19
|
+
*/
|
|
20
|
+
stream<Entity extends object, Hint extends string = never, Fields extends string = '*', Excludes extends string = never>(entityName: EntityName<Entity>, options?: StreamOptions<NoInfer<Entity>, Hint, Fields, Excludes>): AsyncIterableIterator<Loaded<Entity, Hint, Fields, Excludes>>;
|
|
13
21
|
getCollection<T extends Document>(entityName: EntityName<T>): Collection<T>;
|
|
14
22
|
/**
|
|
15
23
|
* @inheritDoc
|
package/MongoEntityManager.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EntityManager, Utils } from '@mikro-orm/core';
|
|
1
|
+
import { EntityManager, Utils, } from '@mikro-orm/core';
|
|
2
2
|
/**
|
|
3
3
|
* @inheritDoc
|
|
4
4
|
*/
|
|
@@ -8,7 +8,23 @@ export class MongoEntityManager extends EntityManager {
|
|
|
8
8
|
*/
|
|
9
9
|
async aggregate(entityName, pipeline) {
|
|
10
10
|
entityName = Utils.className(entityName);
|
|
11
|
-
return this.getDriver().aggregate(entityName, pipeline);
|
|
11
|
+
return this.getDriver().aggregate(entityName, pipeline, this.getTransactionContext());
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Shortcut to driver's aggregate method. Returns a stream. Available in MongoDriver only.
|
|
15
|
+
*/
|
|
16
|
+
async *streamAggregate(entityName, pipeline) {
|
|
17
|
+
entityName = Utils.className(entityName);
|
|
18
|
+
yield* this.getDriver().streamAggregate(entityName, pipeline, this.getTransactionContext());
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @inheritDoc
|
|
22
|
+
*/
|
|
23
|
+
async *stream(entityName, options = {}) {
|
|
24
|
+
if (!Utils.isEmpty(options.populate)) {
|
|
25
|
+
throw new Error('Populate option is not supported when streaming results in MongoDB');
|
|
26
|
+
}
|
|
27
|
+
yield* super.stream(entityName, options);
|
|
12
28
|
}
|
|
13
29
|
getCollection(entityName) {
|
|
14
30
|
return this.getConnection().getCollection(entityName);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExceptionConverter, type Dictionary, type DriverException } from '@mikro-orm/core';
|
|
2
2
|
export declare class MongoExceptionConverter extends ExceptionConverter {
|
|
3
3
|
/**
|
|
4
|
-
* @
|
|
4
|
+
* @see https://gist.github.com/rluvaton/a97a8da46ab6541a3e5702e83b9d357b
|
|
5
5
|
*/
|
|
6
6
|
convertException(exception: Error & Dictionary): DriverException;
|
|
7
7
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { UniqueConstraintViolationException, ExceptionConverter, TableExistsException } from '@mikro-orm/core';
|
|
2
|
-
/* v8 ignore
|
|
2
|
+
/* v8 ignore next */
|
|
3
3
|
export class MongoExceptionConverter extends ExceptionConverter {
|
|
4
4
|
/**
|
|
5
|
-
* @
|
|
5
|
+
* @see https://gist.github.com/rluvaton/a97a8da46ab6541a3e5702e83b9d357b
|
|
6
6
|
*/
|
|
7
7
|
convertException(exception) {
|
|
8
8
|
switch (exception.code) {
|
|
@@ -14,4 +14,3 @@ export class MongoExceptionConverter extends ExceptionConverter {
|
|
|
14
14
|
return super.convertException(exception);
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
/* v8 ignore stop */
|
package/MongoMikroORM.d.ts
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { MikroORM, type Options, type IDatabaseDriver, type EntityManager, type EntityManagerType } from '@mikro-orm/core';
|
|
1
|
+
import { type AnyEntity, type EntityClass, type EntitySchema, MikroORM, type Options, type IDatabaseDriver, type EntityManager, type EntityManagerType, type IMigrator } from '@mikro-orm/core';
|
|
2
2
|
import { MongoDriver } from './MongoDriver.js';
|
|
3
3
|
import type { MongoEntityManager } from './MongoEntityManager.js';
|
|
4
|
+
export type MongoOptions<EM extends MongoEntityManager = MongoEntityManager, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> = Options<MongoDriver, EM, Entities>;
|
|
5
|
+
export declare function defineMongoConfig<EM extends MongoEntityManager = MongoEntityManager, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]>(options: MongoOptions<EM, Entities>): Options<MongoDriver, EM, Entities>;
|
|
4
6
|
/**
|
|
5
7
|
* @inheritDoc
|
|
6
8
|
*/
|
|
7
|
-
export declare class MongoMikroORM<EM extends
|
|
8
|
-
private static DRIVER;
|
|
9
|
+
export declare class MongoMikroORM<EM extends MongoEntityManager = MongoEntityManager, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]> extends MikroORM<MongoDriver, EM, Entities> {
|
|
9
10
|
/**
|
|
10
11
|
* @inheritDoc
|
|
11
12
|
*/
|
|
12
|
-
static init<D extends IDatabaseDriver = MongoDriver, EM extends EntityManager = D[typeof EntityManagerType] & EntityManager>(options
|
|
13
|
+
static init<D extends IDatabaseDriver = MongoDriver, EM extends EntityManager<D> = D[typeof EntityManagerType] & EntityManager<D>, Entities extends (string | EntityClass<AnyEntity> | EntitySchema)[] = (string | EntityClass<AnyEntity> | EntitySchema)[]>(options: Options<D, EM, Entities>): Promise<MikroORM<D, EM, Entities>>;
|
|
13
14
|
/**
|
|
14
15
|
* @inheritDoc
|
|
15
16
|
*/
|
|
16
|
-
|
|
17
|
+
constructor(options: Options<MongoDriver, EM, Entities>);
|
|
18
|
+
/**
|
|
19
|
+
* Gets the Migrator.
|
|
20
|
+
*/
|
|
21
|
+
get migrator(): IMigrator;
|
|
17
22
|
}
|
|
18
|
-
export type MongoOptions = Options<MongoDriver>;
|
|
19
|
-
export declare function defineMongoConfig(options: MongoOptions): Options<MongoDriver, MongoEntityManager<MongoDriver> & EntityManager<IDatabaseDriver<import("@mikro-orm/core").Connection>>>;
|
package/MongoMikroORM.js
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { defineConfig, MikroORM, } from '@mikro-orm/core';
|
|
2
2
|
import { MongoDriver } from './MongoDriver.js';
|
|
3
|
+
export function defineMongoConfig(options) {
|
|
4
|
+
return defineConfig({ driver: MongoDriver, ...options });
|
|
5
|
+
}
|
|
3
6
|
/**
|
|
4
7
|
* @inheritDoc
|
|
5
8
|
*/
|
|
6
9
|
export class MongoMikroORM extends MikroORM {
|
|
7
|
-
static DRIVER = MongoDriver;
|
|
8
10
|
/**
|
|
9
11
|
* @inheritDoc
|
|
10
12
|
*/
|
|
11
13
|
static async init(options) {
|
|
12
|
-
return super.init(options);
|
|
14
|
+
return super.init(defineMongoConfig(options));
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* @inheritDoc
|
|
16
18
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
constructor(options) {
|
|
20
|
+
super(defineMongoConfig(options));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Gets the Migrator.
|
|
24
|
+
*/
|
|
25
|
+
get migrator() {
|
|
26
|
+
return this.driver.getPlatform().getExtension('Migrator', '@mikro-orm/migrator', '@mikro-orm/migrations-mongodb', this.em);
|
|
19
27
|
}
|
|
20
|
-
}
|
|
21
|
-
/* v8 ignore next 3 */
|
|
22
|
-
export function defineMongoConfig(options) {
|
|
23
|
-
return defineConfig({ driver: MongoDriver, ...options });
|
|
24
28
|
}
|
package/MongoPlatform.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ObjectId } from 'mongodb';
|
|
2
|
-
import { Platform, type IPrimaryKey, type Primary, type NamingStrategy, type Constructor, type EntityRepository, type EntityProperty, type PopulateOptions, type EntityMetadata, type IDatabaseDriver, type EntityManager, type Configuration, type MikroORM } from '@mikro-orm/core';
|
|
2
|
+
import { Platform, type IPrimaryKey, type Primary, type NamingStrategy, type Constructor, type EntityRepository, type EntityProperty, type PopulateOptions, type EntityMetadata, type IDatabaseDriver, type EntityManager, type Configuration, type MikroORM, type TransformContext } from '@mikro-orm/core';
|
|
3
3
|
import { MongoExceptionConverter } from './MongoExceptionConverter.js';
|
|
4
4
|
import { MongoSchemaGenerator } from './MongoSchemaGenerator.js';
|
|
5
5
|
export declare class MongoPlatform extends Platform {
|
|
@@ -16,12 +16,10 @@ export declare class MongoPlatform extends Platform {
|
|
|
16
16
|
getSchemaGenerator(driver: IDatabaseDriver, em?: EntityManager): MongoSchemaGenerator;
|
|
17
17
|
normalizePrimaryKey<T extends number | string = number | string>(data: Primary<T> | IPrimaryKey | ObjectId): T;
|
|
18
18
|
denormalizePrimaryKey(data: number | string): IPrimaryKey;
|
|
19
|
-
getSerializedPrimaryKeyField(field: string): string;
|
|
20
|
-
usesDifferentSerializedPrimaryKey(): boolean;
|
|
21
19
|
usesImplicitTransactions(): boolean;
|
|
22
20
|
convertsJsonAutomatically(): boolean;
|
|
23
21
|
convertJsonToDatabaseValue(value: unknown): unknown;
|
|
24
|
-
convertJsonToJSValue(value: unknown,
|
|
22
|
+
convertJsonToJSValue(value: unknown, context?: TransformContext): unknown;
|
|
25
23
|
marshallArray(values: string[]): string;
|
|
26
24
|
cloneEmbeddable<T>(data: T): T;
|
|
27
25
|
shouldHaveColumn<T>(prop: EntityProperty<T>, populate: PopulateOptions<T>[], exclude?: string[]): boolean;
|
package/MongoPlatform.js
CHANGED
|
@@ -32,12 +32,12 @@ export class MongoPlatform extends Platform {
|
|
|
32
32
|
/* v8 ignore next */
|
|
33
33
|
return super.getExtension(extensionName, extensionKey, moduleName, em);
|
|
34
34
|
}
|
|
35
|
-
/* v8 ignore next
|
|
35
|
+
/* v8 ignore next: kept for type inference only */
|
|
36
36
|
getSchemaGenerator(driver, em) {
|
|
37
37
|
return new MongoSchemaGenerator(em ?? driver);
|
|
38
38
|
}
|
|
39
39
|
normalizePrimaryKey(data) {
|
|
40
|
-
if (Utils.
|
|
40
|
+
if (Utils.isObject(data) && data.constructor?.name === 'ObjectId') {
|
|
41
41
|
return data.toHexString();
|
|
42
42
|
}
|
|
43
43
|
return data;
|
|
@@ -45,12 +45,6 @@ export class MongoPlatform extends Platform {
|
|
|
45
45
|
denormalizePrimaryKey(data) {
|
|
46
46
|
return new ObjectId(data);
|
|
47
47
|
}
|
|
48
|
-
getSerializedPrimaryKeyField(field) {
|
|
49
|
-
return 'id';
|
|
50
|
-
}
|
|
51
|
-
usesDifferentSerializedPrimaryKey() {
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
48
|
usesImplicitTransactions() {
|
|
55
49
|
return false;
|
|
56
50
|
}
|
|
@@ -60,7 +54,7 @@ export class MongoPlatform extends Platform {
|
|
|
60
54
|
convertJsonToDatabaseValue(value) {
|
|
61
55
|
return Utils.copy(value);
|
|
62
56
|
}
|
|
63
|
-
convertJsonToJSValue(value,
|
|
57
|
+
convertJsonToJSValue(value, context) {
|
|
64
58
|
return value;
|
|
65
59
|
}
|
|
66
60
|
marshallArray(values) {
|
|
@@ -2,13 +2,13 @@ import { AbstractSchemaGenerator, type CreateSchemaOptions, type MikroORM } from
|
|
|
2
2
|
import type { MongoDriver } from './MongoDriver.js';
|
|
3
3
|
export declare class MongoSchemaGenerator extends AbstractSchemaGenerator<MongoDriver> {
|
|
4
4
|
static register(orm: MikroORM): void;
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
create(options?: MongoCreateSchemaOptions): Promise<void>;
|
|
6
|
+
drop(options?: {
|
|
7
7
|
dropMigrationsTable?: boolean;
|
|
8
8
|
}): Promise<void>;
|
|
9
|
-
|
|
9
|
+
update(options?: MongoCreateSchemaOptions): Promise<void>;
|
|
10
10
|
ensureDatabase(): Promise<boolean>;
|
|
11
|
-
|
|
11
|
+
refresh(options?: MongoCreateSchemaOptions): Promise<void>;
|
|
12
12
|
dropIndexes(options?: {
|
|
13
13
|
skipIndexes?: {
|
|
14
14
|
collection: string;
|
|
@@ -17,7 +17,9 @@ export declare class MongoSchemaGenerator extends AbstractSchemaGenerator<MongoD
|
|
|
17
17
|
collectionsWithFailedIndexes?: string[];
|
|
18
18
|
}): Promise<void>;
|
|
19
19
|
ensureIndexes(options?: EnsureIndexesOptions): Promise<void>;
|
|
20
|
+
private mapIndexProperties;
|
|
20
21
|
private createIndexes;
|
|
22
|
+
private executeQuery;
|
|
21
23
|
private createUniqueIndexes;
|
|
22
24
|
private createPropertyIndexes;
|
|
23
25
|
}
|
package/MongoSchemaGenerator.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import { inspect } from 'node:util';
|
|
1
2
|
import { AbstractSchemaGenerator, Utils, } from '@mikro-orm/core';
|
|
2
3
|
export class MongoSchemaGenerator extends AbstractSchemaGenerator {
|
|
3
4
|
static register(orm) {
|
|
4
5
|
orm.config.registerExtension('@mikro-orm/schema-generator', () => new MongoSchemaGenerator(orm.em));
|
|
5
6
|
}
|
|
6
|
-
async
|
|
7
|
+
async create(options = {}) {
|
|
8
|
+
await this.connection.ensureConnection();
|
|
7
9
|
options.ensureIndexes ??= true;
|
|
8
10
|
const existing = await this.connection.listCollections();
|
|
9
11
|
const metadata = this.getOrderedMetadata();
|
|
10
|
-
|
|
11
|
-
/* v8 ignore start */
|
|
12
|
+
/* v8 ignore next */
|
|
12
13
|
const promises = metadata
|
|
13
14
|
.filter(meta => !existing.includes(meta.collection))
|
|
14
15
|
.map(meta => this.connection.createCollection(meta.collection).catch(err => {
|
|
@@ -18,16 +19,14 @@ export class MongoSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
18
19
|
throw err;
|
|
19
20
|
}
|
|
20
21
|
}));
|
|
21
|
-
/* v8 ignore stop */
|
|
22
22
|
if (options.ensureIndexes) {
|
|
23
23
|
await this.ensureIndexes({ ensureCollections: false });
|
|
24
24
|
}
|
|
25
25
|
await Promise.all(promises);
|
|
26
26
|
}
|
|
27
|
-
async
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
const existing = collections.map(c => c.name);
|
|
27
|
+
async drop(options = {}) {
|
|
28
|
+
await this.connection.ensureConnection();
|
|
29
|
+
const existing = await this.connection.listCollections();
|
|
31
30
|
const metadata = this.getOrderedMetadata();
|
|
32
31
|
if (options.dropMigrationsTable) {
|
|
33
32
|
metadata.push({ collection: this.config.get('migrations').tableName });
|
|
@@ -37,18 +36,19 @@ export class MongoSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
37
36
|
.map(meta => this.connection.dropCollection(meta.collection));
|
|
38
37
|
await Promise.all(promises);
|
|
39
38
|
}
|
|
40
|
-
async
|
|
41
|
-
await this.
|
|
39
|
+
async update(options = {}) {
|
|
40
|
+
await this.create(options);
|
|
42
41
|
}
|
|
43
42
|
async ensureDatabase() {
|
|
44
43
|
return false;
|
|
45
44
|
}
|
|
46
|
-
async
|
|
45
|
+
async refresh(options = {}) {
|
|
47
46
|
await this.ensureDatabase();
|
|
48
|
-
await this.
|
|
49
|
-
await this.
|
|
47
|
+
await this.drop();
|
|
48
|
+
await this.create(options);
|
|
50
49
|
}
|
|
51
50
|
async dropIndexes(options) {
|
|
51
|
+
await this.connection.ensureConnection();
|
|
52
52
|
const db = this.connection.getDb();
|
|
53
53
|
const collections = await db.listCollections().toArray();
|
|
54
54
|
const promises = [];
|
|
@@ -59,19 +59,20 @@ export class MongoSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
59
59
|
const indexes = await db.collection(collection.name).listIndexes().toArray();
|
|
60
60
|
for (const index of indexes) {
|
|
61
61
|
const isIdIndex = index.key._id === 1 && Utils.getObjectKeysSize(index.key) === 1;
|
|
62
|
-
/* v8 ignore next
|
|
62
|
+
/* v8 ignore next */
|
|
63
63
|
if (!isIdIndex && !options?.skipIndexes?.find(idx => idx.collection === collection.name && idx.indexName === index.name)) {
|
|
64
|
-
promises.push(db.collection(collection.name)
|
|
64
|
+
promises.push(this.executeQuery(db.collection(collection.name), 'dropIndex', index.name));
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
await Promise.all(promises);
|
|
69
69
|
}
|
|
70
70
|
async ensureIndexes(options = {}) {
|
|
71
|
+
await this.connection.ensureConnection();
|
|
71
72
|
options.ensureCollections ??= true;
|
|
72
73
|
options.retryLimit ??= 3;
|
|
73
74
|
if (options.ensureCollections) {
|
|
74
|
-
await this.
|
|
75
|
+
await this.create({ ensureIndexes: false });
|
|
75
76
|
}
|
|
76
77
|
const promises = [];
|
|
77
78
|
for (const meta of this.getOrderedMetadata()) {
|
|
@@ -112,11 +113,21 @@ export class MongoSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
112
113
|
});
|
|
113
114
|
}
|
|
114
115
|
}
|
|
116
|
+
mapIndexProperties(index, meta) {
|
|
117
|
+
return Utils.flatten(Utils.asArray(index.properties).map(propName => {
|
|
118
|
+
const rootPropName = propName.split('.')[0];
|
|
119
|
+
const prop = meta.properties[rootPropName];
|
|
120
|
+
if (propName.includes('.')) {
|
|
121
|
+
return [prop.fieldNames[0] + propName.substring(propName.indexOf('.'))];
|
|
122
|
+
}
|
|
123
|
+
return prop?.fieldNames ?? propName;
|
|
124
|
+
}));
|
|
125
|
+
}
|
|
115
126
|
createIndexes(meta) {
|
|
116
127
|
const res = [];
|
|
117
128
|
meta.indexes.forEach(index => {
|
|
118
129
|
let fieldOrSpec;
|
|
119
|
-
const properties =
|
|
130
|
+
const properties = this.mapIndexProperties(index, meta);
|
|
120
131
|
const collection = this.connection.getCollection(meta.className);
|
|
121
132
|
if (Array.isArray(index.options) && index.options.length === 2 && properties.length === 0) {
|
|
122
133
|
res.push([collection.collectionName, collection.createIndex(index.options[0], index.options[1])]);
|
|
@@ -137,7 +148,7 @@ export class MongoSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
137
148
|
else {
|
|
138
149
|
fieldOrSpec = properties.reduce((o, i) => { o[i] = 1; return o; }, {});
|
|
139
150
|
}
|
|
140
|
-
res.push([collection.collectionName, collection
|
|
151
|
+
res.push([collection.collectionName, this.executeQuery(collection, 'createIndex', fieldOrSpec, {
|
|
141
152
|
name: index.name,
|
|
142
153
|
unique: false,
|
|
143
154
|
...index.options,
|
|
@@ -145,13 +156,26 @@ export class MongoSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
145
156
|
});
|
|
146
157
|
return res;
|
|
147
158
|
}
|
|
159
|
+
async executeQuery(collection, method, ...args) {
|
|
160
|
+
const now = Date.now();
|
|
161
|
+
return collection[method](...args).then((res) => {
|
|
162
|
+
Utils.dropUndefinedProperties(args);
|
|
163
|
+
const query = `db.getCollection('${collection.collectionName}').${method}(${args.map(arg => inspect(arg)).join(', ')});`;
|
|
164
|
+
this.config.getLogger().logQuery({
|
|
165
|
+
level: 'info',
|
|
166
|
+
query,
|
|
167
|
+
took: Date.now() - now,
|
|
168
|
+
});
|
|
169
|
+
return res;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
148
172
|
createUniqueIndexes(meta) {
|
|
149
173
|
const res = [];
|
|
150
174
|
meta.uniques.forEach(index => {
|
|
151
|
-
const properties =
|
|
175
|
+
const properties = this.mapIndexProperties(index, meta);
|
|
152
176
|
const fieldOrSpec = properties.reduce((o, i) => { o[i] = 1; return o; }, {});
|
|
153
177
|
const collection = this.connection.getCollection(meta.className);
|
|
154
|
-
res.push([collection.collectionName, collection
|
|
178
|
+
res.push([collection.collectionName, this.executeQuery(collection, 'createIndex', fieldOrSpec, {
|
|
155
179
|
name: index.name,
|
|
156
180
|
unique: true,
|
|
157
181
|
...index.options,
|
|
@@ -167,8 +191,8 @@ export class MongoSchemaGenerator extends AbstractSchemaGenerator {
|
|
|
167
191
|
const fieldOrSpec = prop.embeddedPath
|
|
168
192
|
? prop.embeddedPath.join('.')
|
|
169
193
|
: prop.fieldNames.reduce((o, i) => { o[i] = 1; return o; }, {});
|
|
170
|
-
return [[collection.collectionName, collection
|
|
171
|
-
name:
|
|
194
|
+
return [[collection.collectionName, this.executeQuery(collection, 'createIndex', fieldOrSpec, {
|
|
195
|
+
name: typeof prop[type] === 'string' ? prop[type] : undefined,
|
|
172
196
|
unique: type === 'unique',
|
|
173
197
|
sparse: prop.nullable === true,
|
|
174
198
|
})]];
|
package/README.md
CHANGED
|
@@ -11,7 +11,6 @@ TypeScript ORM for Node.js based on Data Mapper, [Unit of Work](https://mikro-or
|
|
|
11
11
|
[](https://discord.gg/w8bjxFHS7X)
|
|
12
12
|
[](https://www.npmjs.com/package/@mikro-orm/core)
|
|
13
13
|
[](https://coveralls.io/r/mikro-orm/mikro-orm?branch=master)
|
|
14
|
-
[](https://codeclimate.com/github/mikro-orm/mikro-orm/maintainability)
|
|
15
14
|
[](https://github.com/mikro-orm/mikro-orm/actions?workflow=tests)
|
|
16
15
|
|
|
17
16
|
## 🤔 Unit of What?
|
|
@@ -141,7 +140,7 @@ There is also auto-generated [CHANGELOG.md](CHANGELOG.md) file based on commit m
|
|
|
141
140
|
- [Composite and Foreign Keys as Primary Key](https://mikro-orm.io/docs/composite-keys)
|
|
142
141
|
- [Filters](https://mikro-orm.io/docs/filters)
|
|
143
142
|
- [Using `QueryBuilder`](https://mikro-orm.io/docs/query-builder)
|
|
144
|
-
- [
|
|
143
|
+
- [Populating relations](https://mikro-orm.io/docs/populating-relations)
|
|
145
144
|
- [Property Validation](https://mikro-orm.io/docs/property-validation)
|
|
146
145
|
- [Lifecycle Hooks](https://mikro-orm.io/docs/events#hooks)
|
|
147
146
|
- [Vanilla JS Support](https://mikro-orm.io/docs/usage-with-js)
|
|
@@ -382,6 +381,8 @@ See also the list of contributors who [participated](https://github.com/mikro-or
|
|
|
382
381
|
|
|
383
382
|
Please ⭐️ this repository if this project helped you!
|
|
384
383
|
|
|
384
|
+
> If you'd like to support my open-source work, consider sponsoring me directly at [github.com/sponsors/b4nan](https://github.com/sponsors/b4nan).
|
|
385
|
+
|
|
385
386
|
## 📝 License
|
|
386
387
|
|
|
387
388
|
Copyright © 2018 [Martin Adámek](https://github.com/b4nan).
|
package/index.d.ts
CHANGED
|
@@ -8,4 +8,4 @@ export * from './MongoEntityRepository.js';
|
|
|
8
8
|
export * from './MongoSchemaGenerator.js';
|
|
9
9
|
export { MongoEntityManager as EntityManager } from './MongoEntityManager.js';
|
|
10
10
|
export { MongoEntityRepository as EntityRepository } from './MongoEntityRepository.js';
|
|
11
|
-
export { MongoMikroORM as MikroORM, MongoOptions as Options, defineMongoConfig as defineConfig, } from './MongoMikroORM.js';
|
|
11
|
+
export { MongoMikroORM as MikroORM, type MongoOptions as Options, defineMongoConfig as defineConfig, } from './MongoMikroORM.js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mikro-orm/mongodb",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "7.0.0-dev.
|
|
4
|
+
"version": "7.0.0-dev.80",
|
|
5
5
|
"description": "TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.",
|
|
6
6
|
"exports": {
|
|
7
7
|
"./package.json": "./package.json",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
},
|
|
39
39
|
"homepage": "https://mikro-orm.io",
|
|
40
40
|
"engines": {
|
|
41
|
-
"node": ">= 22.
|
|
41
|
+
"node": ">= 22.17.0"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"build": "yarn clean && yarn compile && yarn copy",
|
|
@@ -50,12 +50,12 @@
|
|
|
50
50
|
"access": "public"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"mongodb": "6.
|
|
53
|
+
"mongodb": "6.20.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@mikro-orm/core": "^6.
|
|
56
|
+
"@mikro-orm/core": "^6.6.1"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@mikro-orm/core": "7.0.0-dev.
|
|
59
|
+
"@mikro-orm/core": "7.0.0-dev.80"
|
|
60
60
|
}
|
|
61
61
|
}
|