@sprucelabs/data-stores 28.1.334 → 28.1.336
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/build/databases/MongoDatabase.d.ts +13 -8
- package/build/databases/MongoDatabase.js +56 -64
- package/build/databases/NeDbDatabase.d.ts +8 -7
- package/build/databases/NeDbDatabase.js +26 -33
- package/build/databases/database.utilities.d.ts +6 -0
- package/build/databases/database.utilities.js +40 -0
- package/build/esm/databases/MongoDatabase.d.ts +13 -8
- package/build/esm/databases/MongoDatabase.js +56 -62
- package/build/esm/databases/NeDbDatabase.d.ts +8 -7
- package/build/esm/databases/NeDbDatabase.js +23 -30
- package/build/esm/databases/database.utilities.d.ts +6 -0
- package/build/esm/databases/database.utilities.js +30 -0
- package/build/esm/index.d.ts +1 -1
- package/build/esm/index.js +1 -1
- package/build/esm/tests/databaseAssertUtil.d.ts +4 -3
- package/build/esm/tests/databaseAssertUtil.js +102 -49
- package/build/esm/types/database.types.d.ts +8 -9
- package/build/index.d.ts +1 -1
- package/build/index.js +2 -3
- package/build/tests/databaseAssertUtil.d.ts +4 -3
- package/build/tests/databaseAssertUtil.js +100 -49
- package/build/types/database.types.d.ts +8 -9
- package/package.json +1 -1
- package/build/databases/normalizeIndex.d.ts +0 -5
- package/build/databases/normalizeIndex.js +0 -8
- package/build/esm/databases/normalizeIndex.d.ts +0 -5
- package/build/esm/databases/normalizeIndex.js +0 -5
@@ -1,5 +1,5 @@
|
|
1
1
|
import { MongoClientOptions, MongoClient } from 'mongodb';
|
2
|
-
import { Database, DatabaseOptions,
|
2
|
+
import { Database, DatabaseOptions, Index, IndexWithFilter } from '../types/database.types';
|
3
3
|
import { QueryOptions } from '../types/query.types';
|
4
4
|
export declare const MONGO_TEST_URI = "mongodb://localhost:27017";
|
5
5
|
export default class MongoDatabase implements Database {
|
@@ -26,16 +26,21 @@ export default class MongoDatabase implements Database {
|
|
26
26
|
dropCollection(name: string): Promise<void>;
|
27
27
|
dropDatabase(): Promise<void>;
|
28
28
|
private listIndexes;
|
29
|
-
dropIndex(collection: string, index:
|
30
|
-
getUniqueIndexes(collection: string): Promise<
|
31
|
-
getIndexes(collection: string, shouldIncludeUnique?: boolean): Promise<
|
32
|
-
|
29
|
+
dropIndex(collection: string, index: Index): Promise<void>;
|
30
|
+
getUniqueIndexes(collection: string): Promise<IndexWithFilter[]>;
|
31
|
+
getIndexes(collection: string, shouldIncludeUnique?: boolean): Promise<IndexWithFilter[] | {
|
32
|
+
fields: string[];
|
33
|
+
filter: any;
|
34
|
+
}[]>;
|
35
|
+
createIndex(collection: string, index: Index): Promise<void>;
|
33
36
|
private assertIndexDoesNotExist;
|
34
|
-
private
|
35
|
-
syncIndexes(collectionName: string, indexes:
|
37
|
+
private doesInclude;
|
38
|
+
syncIndexes(collectionName: string, indexes: Index[]): Promise<void>;
|
39
|
+
private _syncIndexes;
|
36
40
|
createUniqueIndex(collection: string, index: string[] | IndexWithFilter): Promise<void>;
|
41
|
+
private generateIndexName;
|
37
42
|
private normalizeIndex;
|
38
|
-
syncUniqueIndexes(collectionName: string, indexes:
|
43
|
+
syncUniqueIndexes(collectionName: string, indexes: Index[]): Promise<void>;
|
39
44
|
update(collection: string, query: Record<string, any>, updates: Record<string, any>): Promise<number>;
|
40
45
|
updateOne(collection: string, query: Record<string, any>, updates: Record<string, any>): Promise<Record<string, any>>;
|
41
46
|
upsertOne(collection: string, query: Record<string, any>, updates: Record<string, any>): Promise<Record<string, any>>;
|
@@ -16,13 +16,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
17
|
exports.MONGO_TEST_URI = void 0;
|
18
18
|
const spruce_skill_utils_1 = require("@sprucelabs/spruce-skill-utils");
|
19
|
-
const differenceWith_1 = __importDefault(require("lodash/differenceWith"));
|
20
|
-
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
21
19
|
const mongodb_1 = require("mongodb");
|
22
20
|
const SpruceError_1 = __importDefault(require("../errors/SpruceError"));
|
23
21
|
const generateId_1 = __importDefault(require("../utilities/generateId"));
|
24
22
|
const mongo_utility_1 = __importDefault(require("../utilities/mongo.utility"));
|
25
|
-
const
|
23
|
+
const database_utilities_1 = require("./database.utilities");
|
26
24
|
exports.MONGO_TEST_URI = 'mongodb://localhost:27017';
|
27
25
|
class MongoDatabase {
|
28
26
|
constructor(url, options) {
|
@@ -226,10 +224,11 @@ class MongoDatabase {
|
|
226
224
|
}
|
227
225
|
async listIndexes(collection) {
|
228
226
|
try {
|
229
|
-
|
227
|
+
const indexes = await this.assertDbWhileAttempingTo('get indexes.', collection)
|
230
228
|
.collection(collection)
|
231
229
|
.listIndexes()
|
232
230
|
.toArray();
|
231
|
+
return indexes.filter((index) => index.name !== '_id_');
|
233
232
|
}
|
234
233
|
catch (err) {
|
235
234
|
return [];
|
@@ -237,9 +236,10 @@ class MongoDatabase {
|
|
237
236
|
}
|
238
237
|
async dropIndex(collection, index) {
|
239
238
|
const indexes = await this.listIndexes(collection);
|
239
|
+
const name = this.generateIndexName(this.normalizeIndex(index));
|
240
240
|
let found = false;
|
241
241
|
for (const thisIndex of indexes) {
|
242
|
-
if (
|
242
|
+
if (thisIndex.name === name) {
|
243
243
|
await this.assertDbWhileAttempingTo('drop a index.', collection)
|
244
244
|
.collection(collection)
|
245
245
|
.dropIndex(thisIndex.name);
|
@@ -249,7 +249,7 @@ class MongoDatabase {
|
|
249
249
|
if (!found) {
|
250
250
|
throw new SpruceError_1.default({
|
251
251
|
code: 'INDEX_NOT_FOUND',
|
252
|
-
missingIndex: (0,
|
252
|
+
missingIndex: (0, database_utilities_1.normalizeIndex)(index).fields,
|
253
253
|
collectionName: collection,
|
254
254
|
});
|
255
255
|
}
|
@@ -260,7 +260,10 @@ class MongoDatabase {
|
|
260
260
|
const uniqueIndexes = [];
|
261
261
|
for (const index of indexes) {
|
262
262
|
if (index.unique) {
|
263
|
-
uniqueIndexes.push(
|
263
|
+
uniqueIndexes.push({
|
264
|
+
fields: Object.keys(index.key),
|
265
|
+
filter: index.partialFilterExpression,
|
266
|
+
});
|
264
267
|
}
|
265
268
|
}
|
266
269
|
return uniqueIndexes;
|
@@ -273,12 +276,18 @@ class MongoDatabase {
|
|
273
276
|
try {
|
274
277
|
const indexes = await this.listIndexes(collection);
|
275
278
|
if (shouldIncludeUnique) {
|
276
|
-
return indexes
|
279
|
+
return indexes.map((index) => ({
|
280
|
+
fields: Object.keys(index.key),
|
281
|
+
filter: index.partialFilterExpression,
|
282
|
+
}));
|
277
283
|
}
|
278
284
|
const nonUniqueIndexes = [];
|
279
285
|
for (const index of indexes) {
|
280
286
|
if (!index.unique) {
|
281
|
-
nonUniqueIndexes.push(
|
287
|
+
nonUniqueIndexes.push({
|
288
|
+
fields: Object.keys(index.key),
|
289
|
+
filter: undefined,
|
290
|
+
});
|
282
291
|
}
|
283
292
|
}
|
284
293
|
return nonUniqueIndexes;
|
@@ -287,23 +296,25 @@ class MongoDatabase {
|
|
287
296
|
return [];
|
288
297
|
}
|
289
298
|
}
|
290
|
-
async createIndex(collection,
|
299
|
+
async createIndex(collection, index) {
|
291
300
|
const currentIndexes = await this.getIndexes(collection);
|
292
|
-
|
293
|
-
const
|
294
|
-
fields.forEach((name) => {
|
295
|
-
|
301
|
+
this.assertIndexDoesNotExist(currentIndexes, index, collection);
|
302
|
+
const indexSpec = {};
|
303
|
+
this.normalizeIndex(index).fields.forEach((name) => {
|
304
|
+
indexSpec[name] = 1;
|
296
305
|
});
|
297
306
|
try {
|
298
307
|
await this.assertDbWhileAttempingTo('create an index.', collection)
|
299
308
|
.collection(collection)
|
300
|
-
.createIndex(
|
309
|
+
.createIndex(indexSpec, {
|
310
|
+
name: this.generateIndexName(index),
|
311
|
+
});
|
301
312
|
}
|
302
313
|
catch (err) {
|
303
314
|
if ((err === null || err === void 0 ? void 0 : err.code) === 11000) {
|
304
315
|
throw new SpruceError_1.default({
|
305
316
|
code: 'DUPLICATE_KEY',
|
306
|
-
friendlyMessage: `Could not create index! Index on '${collection}' has duplicate key for "${fields.join(',')}"`,
|
317
|
+
friendlyMessage: `Could not create index! Index on '${collection}' has duplicate key for "${this.normalizeIndex(index).fields.join(',')}"`,
|
307
318
|
});
|
308
319
|
}
|
309
320
|
else {
|
@@ -311,32 +322,29 @@ class MongoDatabase {
|
|
311
322
|
}
|
312
323
|
}
|
313
324
|
}
|
314
|
-
assertIndexDoesNotExist(currentIndexes,
|
315
|
-
if (this.
|
325
|
+
assertIndexDoesNotExist(currentIndexes, index, collectionName) {
|
326
|
+
if (this.doesInclude(currentIndexes, index)) {
|
316
327
|
throw new SpruceError_1.default({
|
317
328
|
code: 'INDEX_EXISTS',
|
318
|
-
index: fields,
|
329
|
+
index: this.normalizeIndex(index).fields,
|
319
330
|
collectionName,
|
320
331
|
});
|
321
332
|
}
|
322
333
|
}
|
323
|
-
|
324
|
-
|
325
|
-
const { fields: normalizedFields } = this.normalizeIndex(index);
|
326
|
-
if ((0, isEqual_1.default)(normalizedFields, fields)) {
|
327
|
-
return true;
|
328
|
-
}
|
329
|
-
}
|
330
|
-
return false;
|
334
|
+
doesInclude(haystack, needle) {
|
335
|
+
return (0, database_utilities_1.doesIndexesInclude)(haystack, needle);
|
331
336
|
}
|
332
337
|
async syncIndexes(collectionName, indexes) {
|
338
|
+
await this._syncIndexes(collectionName, indexes, 'createIndex');
|
339
|
+
}
|
340
|
+
async _syncIndexes(collectionName, indexes, func, shouldIncludeUnique = false) {
|
333
341
|
var _a;
|
334
|
-
const currentIndexes = await this.getIndexes(collectionName);
|
335
|
-
const
|
342
|
+
const currentIndexes = await this.getIndexes(collectionName, shouldIncludeUnique);
|
343
|
+
const indexesToDelete = (0, database_utilities_1.pluckMissingIndexes)(currentIndexes, indexes);
|
336
344
|
for (const index of indexes) {
|
337
|
-
if (!this.
|
345
|
+
if (!this.doesInclude(currentIndexes, this.normalizeIndex(index))) {
|
338
346
|
try {
|
339
|
-
await this
|
347
|
+
await this[func](collectionName, index);
|
340
348
|
}
|
341
349
|
catch (err) {
|
342
350
|
if (((_a = err.options) === null || _a === void 0 ? void 0 : _a.code) !== 'INDEX_EXISTS') {
|
@@ -345,22 +353,25 @@ class MongoDatabase {
|
|
345
353
|
}
|
346
354
|
}
|
347
355
|
}
|
348
|
-
for (const extra of
|
356
|
+
for (const extra of indexesToDelete) {
|
349
357
|
await this.dropIndex(collectionName, extra);
|
350
358
|
}
|
351
359
|
}
|
352
360
|
async createUniqueIndex(collection, index) {
|
353
361
|
const currentIndexes = await this.getUniqueIndexes(collection);
|
354
|
-
const
|
355
|
-
this.assertIndexDoesNotExist(currentIndexes,
|
362
|
+
const indexWithFilter = this.normalizeIndex(index);
|
363
|
+
this.assertIndexDoesNotExist(currentIndexes, indexWithFilter, collection);
|
356
364
|
const created = {};
|
357
|
-
fields.forEach((name) => {
|
365
|
+
indexWithFilter.fields.forEach((name) => {
|
358
366
|
created[name] = 1;
|
359
367
|
});
|
360
368
|
try {
|
361
|
-
const options = {
|
362
|
-
|
363
|
-
|
369
|
+
const options = {
|
370
|
+
unique: true,
|
371
|
+
name: this.generateIndexName(indexWithFilter),
|
372
|
+
};
|
373
|
+
if (indexWithFilter.filter) {
|
374
|
+
options.partialFilterExpression = indexWithFilter.filter;
|
364
375
|
}
|
365
376
|
await this.assertDbWhileAttempingTo('create a unique index.', collection)
|
366
377
|
.collection(collection)
|
@@ -370,7 +381,8 @@ class MongoDatabase {
|
|
370
381
|
if ((err === null || err === void 0 ? void 0 : err.code) === 11000) {
|
371
382
|
throw new SpruceError_1.default({
|
372
383
|
code: 'DUPLICATE_KEY',
|
373
|
-
|
384
|
+
originalError: err,
|
385
|
+
friendlyMessage: `Could not create index! Unique index on '${collection}' has duplicate key for "${indexWithFilter.fields.join(',')}"\n\nOriginal error:\n\n${err.message}`,
|
374
386
|
});
|
375
387
|
}
|
376
388
|
else {
|
@@ -378,35 +390,15 @@ class MongoDatabase {
|
|
378
390
|
}
|
379
391
|
}
|
380
392
|
}
|
393
|
+
generateIndexName(indexWithFilter) {
|
394
|
+
return (0, database_utilities_1.generateIndexName)(this.normalizeIndex(indexWithFilter));
|
395
|
+
}
|
381
396
|
normalizeIndex(index) {
|
382
|
-
const { fields, filter } = (0,
|
397
|
+
const { fields, filter } = (0, database_utilities_1.normalizeIndex)(index);
|
383
398
|
return { fields, filter };
|
384
399
|
}
|
385
400
|
async syncUniqueIndexes(collectionName, indexes) {
|
386
|
-
|
387
|
-
const currentIndexes = await this.getUniqueIndexes(collectionName);
|
388
|
-
const toDelete = [];
|
389
|
-
for (const index of currentIndexes) {
|
390
|
-
if (!this.doesIndexExist(indexes, index)) {
|
391
|
-
toDelete.push(index);
|
392
|
-
}
|
393
|
-
}
|
394
|
-
for (const index of indexes) {
|
395
|
-
const { fields } = this.normalizeIndex(index);
|
396
|
-
if (!this.doesIndexExist(currentIndexes, fields)) {
|
397
|
-
try {
|
398
|
-
await this.createUniqueIndex(collectionName, index);
|
399
|
-
}
|
400
|
-
catch (err) {
|
401
|
-
if (((_a = err.options) === null || _a === void 0 ? void 0 : _a.code) !== 'INDEX_EXISTS') {
|
402
|
-
throw err;
|
403
|
-
}
|
404
|
-
}
|
405
|
-
}
|
406
|
-
}
|
407
|
-
for (const extra of toDelete) {
|
408
|
-
await this.dropIndex(collectionName, extra);
|
409
|
-
}
|
401
|
+
await this._syncIndexes(collectionName, indexes, 'createUniqueIndex', true);
|
410
402
|
}
|
411
403
|
async update(collection, query, updates) {
|
412
404
|
const q = this.toMongoIdAndNull(collection, query);
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import AbstractMutexer from '../mutexers/AbstractMutexer';
|
2
|
-
import { CreateOptions, Database, DatabaseInternalOptions,
|
2
|
+
import { CreateOptions, Database, DatabaseInternalOptions, Index, IndexWithFilter } from '../types/database.types';
|
3
3
|
import { QueryOptions } from '../types/query.types';
|
4
4
|
export default class NeDbDatabase extends AbstractMutexer implements Database {
|
5
5
|
private collections;
|
@@ -31,14 +31,15 @@ export default class NeDbDatabase extends AbstractMutexer implements Database {
|
|
31
31
|
delete(collection: string, query: Record<string, any>): Promise<number>;
|
32
32
|
deleteOne(collection: string, query: Record<string, any>): Promise<number>;
|
33
33
|
private assertPassesUniqueIndexes;
|
34
|
-
getUniqueIndexes(collection: string): Promise<
|
35
|
-
getIndexes(collection: string, shouldIncludeUnique?: boolean): Promise<
|
36
|
-
dropIndex(collection: string, index:
|
34
|
+
getUniqueIndexes(collection: string): Promise<IndexWithFilter[]>;
|
35
|
+
getIndexes(collection: string, shouldIncludeUnique?: boolean): Promise<IndexWithFilter[]>;
|
36
|
+
dropIndex(collection: string, index: Index): Promise<void>;
|
37
37
|
private assertIndexDoesNotExist;
|
38
|
-
private
|
39
|
-
createUniqueIndex(collection: string, index:
|
38
|
+
private doesInclude;
|
39
|
+
createUniqueIndex(collection: string, index: Index): Promise<void>;
|
40
40
|
createIndex(collection: string, fields: string[]): Promise<void>;
|
41
|
-
|
41
|
+
private normalizeIndex;
|
42
|
+
syncUniqueIndexes(collectionName: string, indexes: Index[]): Promise<void>;
|
42
43
|
syncIndexes(collectionName: string, indexes: string[][]): Promise<void>;
|
43
44
|
query<T>(query: string, params?: any[]): Promise<T[]>;
|
44
45
|
private queryToKey;
|
@@ -16,7 +16,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
16
16
|
var _a;
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
18
18
|
const dotenv_1 = __importDefault(require("dotenv"));
|
19
|
-
const differenceWith_1 = __importDefault(require("lodash/differenceWith"));
|
20
19
|
const get_1 = __importDefault(require("lodash/get"));
|
21
20
|
const isEqual_1 = __importDefault(require("lodash/isEqual"));
|
22
21
|
const isObject_1 = __importDefault(require("lodash/isObject"));
|
@@ -26,7 +25,7 @@ const SpruceError_1 = __importDefault(require("../errors/SpruceError"));
|
|
26
25
|
const AbstractMutexer_1 = __importDefault(require("../mutexers/AbstractMutexer"));
|
27
26
|
const generateId_1 = __importDefault(require("../utilities/generateId"));
|
28
27
|
const mongo_utility_1 = __importDefault(require("../utilities/mongo.utility"));
|
29
|
-
const
|
28
|
+
const database_utilities_1 = require("./database.utilities");
|
30
29
|
dotenv_1.default.config();
|
31
30
|
class NeDbDatabase extends AbstractMutexer_1.default {
|
32
31
|
constructor() {
|
@@ -290,7 +289,7 @@ class NeDbDatabase extends AbstractMutexer_1.default {
|
|
290
289
|
await this.randomDelay();
|
291
290
|
if (col._uniqueIndexes) {
|
292
291
|
for (const index of col._uniqueIndexes) {
|
293
|
-
const { fields, filter } = (0,
|
292
|
+
const { fields, filter } = (0, database_utilities_1.normalizeIndex)(index);
|
294
293
|
if (filter) {
|
295
294
|
let shouldSkip = false;
|
296
295
|
for (const key in filter) {
|
@@ -348,12 +347,12 @@ class NeDbDatabase extends AbstractMutexer_1.default {
|
|
348
347
|
async dropIndex(collection, index) {
|
349
348
|
var _a, _b;
|
350
349
|
const col = this.loadCollection(collection);
|
351
|
-
const { fields } = (0,
|
350
|
+
const { fields } = (0, database_utilities_1.normalizeIndex)(index);
|
352
351
|
await this.randomDelay();
|
353
352
|
let found = false;
|
354
353
|
let newIndexes = [];
|
355
354
|
for (const uniq of (_a = col._uniqueIndexes) !== null && _a !== void 0 ? _a : []) {
|
356
|
-
if (!(0, isEqual_1.default)(uniq, fields)) {
|
355
|
+
if (!(0, isEqual_1.default)(uniq.fields, fields)) {
|
357
356
|
newIndexes.push(uniq);
|
358
357
|
}
|
359
358
|
else {
|
@@ -367,7 +366,7 @@ class NeDbDatabase extends AbstractMutexer_1.default {
|
|
367
366
|
else {
|
368
367
|
newIndexes = [];
|
369
368
|
for (const index of (_b = col._indexes) !== null && _b !== void 0 ? _b : []) {
|
370
|
-
if (!(0, isEqual_1.default)(index, fields)) {
|
369
|
+
if (!(0, isEqual_1.default)(index.fields, fields)) {
|
371
370
|
newIndexes.push(index);
|
372
371
|
}
|
373
372
|
else {
|
@@ -385,37 +384,32 @@ class NeDbDatabase extends AbstractMutexer_1.default {
|
|
385
384
|
collectionName: 'test_collection',
|
386
385
|
});
|
387
386
|
}
|
388
|
-
assertIndexDoesNotExist(currentIndexes,
|
389
|
-
if (this.
|
387
|
+
assertIndexDoesNotExist(currentIndexes, index, collectionName) {
|
388
|
+
if (this.doesInclude(currentIndexes, index)) {
|
390
389
|
throw new SpruceError_1.default({
|
391
390
|
code: 'INDEX_EXISTS',
|
392
|
-
index: fields,
|
391
|
+
index: index.fields,
|
393
392
|
collectionName,
|
394
393
|
});
|
395
394
|
}
|
396
395
|
}
|
397
|
-
|
398
|
-
|
399
|
-
if ((0, isEqual_1.default)(existing, index)) {
|
400
|
-
return true;
|
401
|
-
}
|
402
|
-
}
|
403
|
-
return false;
|
396
|
+
doesInclude(haystack, needle) {
|
397
|
+
return (0, database_utilities_1.doesIndexesInclude)(haystack, needle);
|
404
398
|
}
|
405
399
|
async createUniqueIndex(collection, index) {
|
406
400
|
const col = this.loadCollection(collection);
|
407
401
|
if (!col._uniqueIndexes) {
|
408
402
|
col._uniqueIndexes = [];
|
409
403
|
}
|
410
|
-
const
|
404
|
+
const indexWithFilter = (0, database_utilities_1.normalizeIndex)(index);
|
411
405
|
await this.randomDelay();
|
412
|
-
this.assertIndexDoesNotExist(col._uniqueIndexes,
|
413
|
-
if (col._uniqueIndexes && !filter) {
|
406
|
+
this.assertIndexDoesNotExist(col._uniqueIndexes, indexWithFilter, collection);
|
407
|
+
if (col._uniqueIndexes && !indexWithFilter.filter) {
|
414
408
|
const tempUniqueIndexes = [...col._uniqueIndexes];
|
415
|
-
tempUniqueIndexes.push(
|
409
|
+
tempUniqueIndexes.push(indexWithFilter);
|
416
410
|
const documents = (await this.find(collection)) || [];
|
417
411
|
for (const index of tempUniqueIndexes) {
|
418
|
-
const { fields: uniqueFields } = (0,
|
412
|
+
const { fields: uniqueFields } = (0, database_utilities_1.normalizeIndex)(index);
|
419
413
|
let parsedExisting = [];
|
420
414
|
for (const doc of documents) {
|
421
415
|
const tempDoc = {};
|
@@ -433,7 +427,7 @@ class NeDbDatabase extends AbstractMutexer_1.default {
|
|
433
427
|
}
|
434
428
|
}
|
435
429
|
}
|
436
|
-
col._uniqueIndexes.push(
|
430
|
+
col._uniqueIndexes.push(indexWithFilter);
|
437
431
|
}
|
438
432
|
async createIndex(collection, fields) {
|
439
433
|
const col = this.loadCollection(collection);
|
@@ -441,20 +435,19 @@ class NeDbDatabase extends AbstractMutexer_1.default {
|
|
441
435
|
col._indexes = [];
|
442
436
|
}
|
443
437
|
await this.randomDelay();
|
444
|
-
this.assertIndexDoesNotExist(col._indexes, fields, collection);
|
445
|
-
col._indexes.push(fields);
|
438
|
+
this.assertIndexDoesNotExist(col._indexes, this.normalizeIndex(fields), collection);
|
439
|
+
col._indexes.push({ fields });
|
440
|
+
}
|
441
|
+
normalizeIndex(index) {
|
442
|
+
const { fields, filter } = (0, database_utilities_1.normalizeIndex)(index);
|
443
|
+
return { fields, filter };
|
446
444
|
}
|
447
445
|
async syncUniqueIndexes(collectionName, indexes) {
|
448
446
|
var _a;
|
449
447
|
const currentIndexes = await this.getUniqueIndexes(collectionName);
|
450
|
-
const toDelete =
|
451
|
-
for (const index of currentIndexes) {
|
452
|
-
if (!this.doesIndexExist(indexes, index)) {
|
453
|
-
toDelete.push(index);
|
454
|
-
}
|
455
|
-
}
|
448
|
+
const toDelete = (0, database_utilities_1.pluckMissingIndexes)(currentIndexes, indexes);
|
456
449
|
for (const index of indexes) {
|
457
|
-
if (!this.
|
450
|
+
if (!this.doesInclude(currentIndexes, index)) {
|
458
451
|
try {
|
459
452
|
await this.createUniqueIndex(collectionName, index);
|
460
453
|
}
|
@@ -472,9 +465,9 @@ class NeDbDatabase extends AbstractMutexer_1.default {
|
|
472
465
|
async syncIndexes(collectionName, indexes) {
|
473
466
|
var _a;
|
474
467
|
const currentIndexes = await this.getIndexes(collectionName);
|
475
|
-
const extraIndexes = (0,
|
468
|
+
const extraIndexes = (0, database_utilities_1.pluckMissingIndexes)(currentIndexes, indexes);
|
476
469
|
for (const index of indexes) {
|
477
|
-
if (!this.
|
470
|
+
if (!this.doesInclude(currentIndexes, index)) {
|
478
471
|
try {
|
479
472
|
await this.createIndex(collectionName, index);
|
480
473
|
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
import { IndexWithFilter, Index } from '../types/database.types';
|
2
|
+
export declare function doesIndexesInclude(haystack: Index[], needle: Index): boolean;
|
3
|
+
export declare function areIndexesEqual(left: Index, right: Index): boolean;
|
4
|
+
export declare function generateIndexName(indexWithFilter: IndexWithFilter): string;
|
5
|
+
export declare function normalizeIndex(index: Index): IndexWithFilter;
|
6
|
+
export declare function pluckMissingIndexes(left: Index[], right: Index[]): Index[];
|
@@ -0,0 +1,40 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.doesIndexesInclude = doesIndexesInclude;
|
7
|
+
exports.areIndexesEqual = areIndexesEqual;
|
8
|
+
exports.generateIndexName = generateIndexName;
|
9
|
+
exports.normalizeIndex = normalizeIndex;
|
10
|
+
exports.pluckMissingIndexes = pluckMissingIndexes;
|
11
|
+
const differenceWith_1 = __importDefault(require("lodash/differenceWith"));
|
12
|
+
function doesIndexesInclude(haystack, needle) {
|
13
|
+
for (const index of haystack !== null && haystack !== void 0 ? haystack : []) {
|
14
|
+
if (areIndexesEqual(index, needle)) {
|
15
|
+
return true;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
return false;
|
19
|
+
}
|
20
|
+
function areIndexesEqual(left, right) {
|
21
|
+
const name1 = generateIndexName(normalizeIndex(left));
|
22
|
+
const name2 = generateIndexName(normalizeIndex(right));
|
23
|
+
return name1 === name2;
|
24
|
+
}
|
25
|
+
function generateIndexName(indexWithFilter) {
|
26
|
+
let name = indexWithFilter.fields.join('_');
|
27
|
+
if (indexWithFilter.filter) {
|
28
|
+
name += '_filtered';
|
29
|
+
}
|
30
|
+
return name;
|
31
|
+
}
|
32
|
+
function normalizeIndex(index) {
|
33
|
+
const fields = Array.isArray(index) ? index : index.fields;
|
34
|
+
const filter = Array.isArray(index) ? undefined : index.filter;
|
35
|
+
fields.sort();
|
36
|
+
return { fields, filter };
|
37
|
+
}
|
38
|
+
function pluckMissingIndexes(left, right) {
|
39
|
+
return (0, differenceWith_1.default)(left, right, areIndexesEqual);
|
40
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { MongoClientOptions, MongoClient } from 'mongodb';
|
2
|
-
import { Database, DatabaseOptions,
|
2
|
+
import { Database, DatabaseOptions, Index, IndexWithFilter } from '../types/database.types';
|
3
3
|
import { QueryOptions } from '../types/query.types';
|
4
4
|
export declare const MONGO_TEST_URI = "mongodb://localhost:27017";
|
5
5
|
export default class MongoDatabase implements Database {
|
@@ -26,16 +26,21 @@ export default class MongoDatabase implements Database {
|
|
26
26
|
dropCollection(name: string): Promise<void>;
|
27
27
|
dropDatabase(): Promise<void>;
|
28
28
|
private listIndexes;
|
29
|
-
dropIndex(collection: string, index:
|
30
|
-
getUniqueIndexes(collection: string): Promise<
|
31
|
-
getIndexes(collection: string, shouldIncludeUnique?: boolean): Promise<
|
32
|
-
|
29
|
+
dropIndex(collection: string, index: Index): Promise<void>;
|
30
|
+
getUniqueIndexes(collection: string): Promise<IndexWithFilter[]>;
|
31
|
+
getIndexes(collection: string, shouldIncludeUnique?: boolean): Promise<IndexWithFilter[] | {
|
32
|
+
fields: string[];
|
33
|
+
filter: any;
|
34
|
+
}[]>;
|
35
|
+
createIndex(collection: string, index: Index): Promise<void>;
|
33
36
|
private assertIndexDoesNotExist;
|
34
|
-
private
|
35
|
-
syncIndexes(collectionName: string, indexes:
|
37
|
+
private doesInclude;
|
38
|
+
syncIndexes(collectionName: string, indexes: Index[]): Promise<void>;
|
39
|
+
private _syncIndexes;
|
36
40
|
createUniqueIndex(collection: string, index: string[] | IndexWithFilter): Promise<void>;
|
41
|
+
private generateIndexName;
|
37
42
|
private normalizeIndex;
|
38
|
-
syncUniqueIndexes(collectionName: string, indexes:
|
43
|
+
syncUniqueIndexes(collectionName: string, indexes: Index[]): Promise<void>;
|
39
44
|
update(collection: string, query: Record<string, any>, updates: Record<string, any>): Promise<number>;
|
40
45
|
updateOne(collection: string, query: Record<string, any>, updates: Record<string, any>): Promise<Record<string, any>>;
|
41
46
|
upsertOne(collection: string, query: Record<string, any>, updates: Record<string, any>): Promise<Record<string, any>>;
|