@storyous/mongodb 1.0.7 → 1.0.8

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.
Files changed (60) hide show
  1. package/dist/appData/index.d.ts +12 -0
  2. package/dist/appData/index.js +40 -0
  3. package/dist/concurrentTask.d.ts +9 -0
  4. package/dist/concurrentTask.js +20 -0
  5. package/dist/fixtures.d.ts +5 -0
  6. package/dist/fixtures.js +28 -0
  7. package/dist/getCollection.d.ts +3 -0
  8. package/dist/getCollection.js +9 -0
  9. package/dist/getMongoLocker.d.ts +10 -0
  10. package/dist/getMongoLocker.js +53 -0
  11. package/dist/index.d.ts +11 -0
  12. package/dist/index.js +27 -0
  13. package/dist/migrations/Migration.d.ts +6 -0
  14. package/dist/migrations/Migration.js +22 -0
  15. package/dist/migrations/MigrationsStore.d.ts +13 -0
  16. package/dist/migrations/MigrationsStore.js +65 -0
  17. package/dist/migrations/runMigrations.d.ts +12 -0
  18. package/dist/migrations/runMigrations.js +50 -0
  19. package/dist/migrations/template.d.ts +3 -0
  20. package/dist/migrations/template.js +11 -0
  21. package/dist/mongoClient.d.ts +8 -0
  22. package/dist/mongoClient.js +18 -0
  23. package/dist/mongoErrorCodes.d.ts +6 -0
  24. package/dist/mongoErrorCodes.js +11 -0
  25. package/dist/mongoLocker.d.ts +3 -0
  26. package/dist/mongoLocker.js +17 -0
  27. package/dist/withTransaction.d.ts +3 -0
  28. package/dist/withTransaction.js +21 -0
  29. package/lib/appData/index.d.ts +12 -0
  30. package/lib/concurrentTask.d.ts +9 -0
  31. package/lib/fixtures.d.ts +5 -0
  32. package/lib/getCollection.d.ts +3 -0
  33. package/lib/getMongoLocker.d.ts +10 -0
  34. package/lib/index.d.ts +11 -0
  35. package/lib/migrations/Migration.d.ts +6 -0
  36. package/lib/migrations/MigrationsStore.d.ts +13 -0
  37. package/lib/migrations/runMigrations.d.ts +12 -0
  38. package/lib/migrations/template.d.ts +3 -0
  39. package/lib/migrations/template.js +8 -4
  40. package/lib/migrations/template.ts +2 -1
  41. package/lib/mongoClient.d.ts +8 -0
  42. package/lib/mongoErrorCodes.d.ts +6 -0
  43. package/lib/mongoLocker.d.ts +3 -0
  44. package/lib/withTransaction.d.ts +3 -0
  45. package/package.json +9 -4
  46. package/__tests__/appData.test.js +0 -33
  47. package/__tests__/appData.test.ts +0 -35
  48. package/__tests__/fixtures.test.js +0 -40
  49. package/__tests__/fixtures.test.ts +0 -44
  50. package/__tests__/getMongoClient.js +0 -19
  51. package/__tests__/getMongoClient.ts +0 -24
  52. package/__tests__/migrations/1642152064249-test.js +0 -7
  53. package/__tests__/migrations/1642152064249-test.ts +0 -7
  54. package/__tests__/mongoLocker.test.js +0 -151
  55. package/__tests__/mongoLocker.test.ts +0 -191
  56. package/__tests__/runMigration.test.js +0 -21
  57. package/__tests__/runMigration.test.ts +0 -22
  58. package/__tests__/withTransaction.test.js +0 -40
  59. package/__tests__/withTransaction.test.ts +0 -67
  60. package/tsconfig.json +0 -7
@@ -0,0 +1,13 @@
1
+ import { CallbackError, Migration } from 'migrate';
2
+ import { Logger } from 'winston';
3
+ export default class MigrationsStore {
4
+ private _logger;
5
+ private _safeMigration;
6
+ constructor(_logger: Logger, path: string, _safeMigration: boolean);
7
+ save(set: Object, cb: CallbackError): void;
8
+ load(cb: (err: any, store: {
9
+ lastRun?: string;
10
+ migrations: Pick<Migration, 'title' | 'description' | 'timestamp'>[];
11
+ }) => void): void;
12
+ private _checkValidMigrations;
13
+ }
@@ -0,0 +1,12 @@
1
+ import { Logger } from 'winston';
2
+ /**
3
+ * In case of fail - logs the result and returns rejected promise
4
+ * @param {Logger} logger Logger
5
+ * @param {string} directory Path to directory where migrations are
6
+ * @param {boolean} continueOnError If app crashes on error or continue
7
+ * @param {boolean} safeMigration Do not allow to rewrite all migrations with empty array
8
+ */
9
+ export default function runMigrations(logger: Logger, directory: string, { continueOnError, safeMigration, }: {
10
+ continueOnError?: boolean | undefined;
11
+ safeMigration?: boolean | undefined;
12
+ }): Promise<void>;
@@ -0,0 +1,3 @@
1
+ import Migration from './Migration';
2
+ declare const _default: Migration;
3
+ export = _default;
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
- const mongodb_1 = require("@storyous/mongodb");
3
- module.exports = new mongodb_1.Migration('[ADD DESCRIPTION HERE]', async () => {
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const getCollection_1 = __importDefault(require("../getCollection"));
6
+ const Migration_1 = __importDefault(require("./Migration"));
7
+ module.exports = new Migration_1.default('[ADD DESCRIPTION HERE]', async () => {
4
8
  // add logic here
5
- await (0, mongodb_1.getCollection)('exampleCollection');
9
+ await (0, getCollection_1.default)('exampleCollection');
6
10
  });
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcGxhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZW1wbGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsK0NBQTZEO0FBRTdELGlCQUFTLElBQUksbUJBQVMsQ0FBQyx3QkFBd0IsRUFBRSxLQUFLLElBQUksRUFBRTtJQUN4RCxpQkFBaUI7SUFDakIsTUFBTSxJQUFBLHVCQUFhLEVBQUMsbUJBQW1CLENBQUMsQ0FBQztBQUM3QyxDQUFDLENBQUMsQ0FBQyJ9
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVtcGxhdGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0ZW1wbGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEscUVBQTZDO0FBQzdDLDREQUFvQztBQUVwQyxpQkFBUyxJQUFJLG1CQUFTLENBQUMsd0JBQXdCLEVBQUUsS0FBSyxJQUFJLEVBQUU7SUFDeEQsaUJBQWlCO0lBQ2pCLE1BQU0sSUFBQSx1QkFBYSxFQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDN0MsQ0FBQyxDQUFDLENBQUMifQ==
@@ -1,4 +1,5 @@
1
- import { getCollection, Migration } from '@storyous/mongodb';
1
+ import getCollection from '../getCollection';
2
+ import Migration from './Migration';
2
3
 
3
4
  export = new Migration('[ADD DESCRIPTION HERE]', async () => {
4
5
  // add logic here
@@ -0,0 +1,8 @@
1
+ import { MongoClient, MongoClientOptions, ObjectId } from 'mongodb';
2
+ export declare type Key = string | number | ObjectId;
3
+ declare const mongoClient: {
4
+ _client: MongoClient | null;
5
+ init(mongodbUrl: string, mongoOptions?: MongoClientOptions | undefined): void;
6
+ getClient(): MongoClient;
7
+ };
8
+ export default mongoClient;
@@ -0,0 +1,6 @@
1
+ declare const mongoErrorCodes: {
2
+ DUPLICATE_KEY_INSERT: number;
3
+ DUPLICATE_KEY_UPDATE: number;
4
+ DUPLICATE_KEY: number[];
5
+ };
6
+ export default mongoErrorCodes;
@@ -0,0 +1,3 @@
1
+ import { LockCallback, LockerOptions } from './getMongoLocker';
2
+ import { Key } from './mongoClient';
3
+ export default function <T>(key: Key, callback: LockCallback<T>, options?: LockerOptions): Promise<T>;
@@ -0,0 +1,3 @@
1
+ import { ClientSession, TransactionOptions } from 'mongodb';
2
+ declare const _default: <T>(callback: (session: ClientSession) => Promise<T>, options?: TransactionOptions | undefined) => Promise<T>;
3
+ export default _default;
package/package.json CHANGED
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "@storyous/mongodb",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "",
5
5
  "homepage": "https://github.com/Storyous/mono-utils#readme",
6
6
  "license": "ISC",
7
- "main": "lib/index",
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "lib"
12
+ ],
8
13
  "scripts": {
9
14
  "start": "tsc"
10
15
  },
@@ -29,7 +34,7 @@
29
34
  "registry": "https://registry.npmjs.org/"
30
35
  },
31
36
  "dependencies": {
32
- "@storyous/errors": "^1.0.5",
37
+ "@storyous/errors": "^1.0.6",
33
38
  "@types/lodash": "^4.14.182",
34
39
  "lodash": "^4.17.21",
35
40
  "migrate": "^1.8.0",
@@ -39,5 +44,5 @@
39
44
  "devDependencies": {
40
45
  "@types/sinon": "^10.0.11"
41
46
  },
42
- "gitHead": "4ea95d722ba6e85e9b6939128a2d37860fbb00f1"
47
+ "gitHead": "3884746d0e2c36dd11a390e18f2eb05f5c9db510"
43
48
  }
@@ -1,33 +0,0 @@
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
- require("./getMongoClient");
7
- const assert_1 = __importDefault(require("assert"));
8
- const mocha_1 = require("mocha");
9
- const mongodb_1 = require("mongodb");
10
- const lib_1 = require("../lib");
11
- (0, mocha_1.describe)('packages/mongodb/appData', () => {
12
- (0, mocha_1.it)('should ensureDocumentExists works', async () => {
13
- const testDocument = { _id: new mongodb_1.ObjectId() };
14
- const res = await lib_1.appData.ensureDocumentExists(testDocument);
15
- assert_1.default.deepStrictEqual(res?.acknowledged, true);
16
- const resAgain = await lib_1.appData.ensureDocumentExists(testDocument);
17
- assert_1.default.deepStrictEqual(resAgain, null);
18
- });
19
- (0, mocha_1.it)('should updateDocument works', async () => {
20
- const testDocument = { _id: new mongodb_1.ObjectId() };
21
- await lib_1.appData.ensureDocumentExists(testDocument);
22
- await lib_1.appData.updateDocument(testDocument._id, { $set: { foo: 'bar' } });
23
- const res = await lib_1.appData.getDocument(testDocument._id);
24
- assert_1.default.deepStrictEqual(res?.foo, 'bar');
25
- });
26
- (0, mocha_1.it)('should updateDocument works wit upsert', async () => {
27
- const testDocument = { _id: new mongodb_1.ObjectId() };
28
- await lib_1.appData.updateDocument(testDocument._id, { $set: { foo: 'bar' } }, true);
29
- const res = await lib_1.appData.getDocument(testDocument._id);
30
- assert_1.default.deepStrictEqual(res?.foo, 'bar');
31
- });
32
- });
33
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwRGF0YS50ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiYXBwRGF0YS50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsNEJBQTBCO0FBQzFCLG9EQUE0QjtBQUM1QixpQ0FBcUM7QUFDckMscUNBQW1DO0FBQ25DLGdDQUFpQztBQUVqQyxJQUFBLGdCQUFRLEVBQUMsMEJBQTBCLEVBQUUsR0FBRyxFQUFFO0lBRXRDLElBQUEsVUFBRSxFQUFDLG1DQUFtQyxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQy9DLE1BQU0sWUFBWSxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksa0JBQVEsRUFBRSxFQUFFLENBQUM7UUFFN0MsTUFBTSxHQUFHLEdBQUcsTUFBTSxhQUFPLENBQUMsb0JBQW9CLENBQUMsWUFBWSxDQUFRLENBQUM7UUFDcEUsZ0JBQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLFlBQVksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUVoRCxNQUFNLFFBQVEsR0FBRyxNQUFNLGFBQU8sQ0FBQyxvQkFBb0IsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNsRSxnQkFBTSxDQUFDLGVBQWUsQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDM0MsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLFVBQUUsRUFBQyw2QkFBNkIsRUFBRSxLQUFLLElBQUksRUFBRTtRQUN6QyxNQUFNLFlBQVksR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLGtCQUFRLEVBQUUsRUFBRSxDQUFDO1FBQzdDLE1BQU0sYUFBTyxDQUFDLG9CQUFvQixDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2pELE1BQU0sYUFBTyxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUV6RSxNQUFNLEdBQUcsR0FBRyxNQUFNLGFBQU8sQ0FBQyxXQUFXLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hELGdCQUFNLENBQUMsZUFBZSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDNUMsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLFVBQUUsRUFBQyx3Q0FBd0MsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNwRCxNQUFNLFlBQVksR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLGtCQUFRLEVBQUUsRUFBRSxDQUFDO1FBQzdDLE1BQU0sYUFBTyxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFL0UsTUFBTSxHQUFHLEdBQUcsTUFBTSxhQUFPLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4RCxnQkFBTSxDQUFDLGVBQWUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQzVDLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQyxDQUFDLENBQUMifQ==
@@ -1,35 +0,0 @@
1
- import './getMongoClient';
2
- import assert from 'assert';
3
- import { describe, it } from 'mocha';
4
- import { ObjectId } from 'mongodb';
5
- import { appData } from '../lib';
6
-
7
- describe('packages/mongodb/appData', () => {
8
-
9
- it('should ensureDocumentExists works', async () => {
10
- const testDocument = { _id: new ObjectId() };
11
-
12
- const res = await appData.ensureDocumentExists(testDocument) as any;
13
- assert.deepStrictEqual(res?.acknowledged, true);
14
-
15
- const resAgain = await appData.ensureDocumentExists(testDocument);
16
- assert.deepStrictEqual(resAgain, null);
17
- });
18
-
19
- it('should updateDocument works', async () => {
20
- const testDocument = { _id: new ObjectId() };
21
- await appData.ensureDocumentExists(testDocument);
22
- await appData.updateDocument(testDocument._id, { $set: { foo: 'bar' } });
23
-
24
- const res = await appData.getDocument(testDocument._id);
25
- assert.deepStrictEqual(res?.foo, 'bar');
26
- });
27
-
28
- it('should updateDocument works wit upsert', async () => {
29
- const testDocument = { _id: new ObjectId() };
30
- await appData.updateDocument(testDocument._id, { $set: { foo: 'bar' } }, true);
31
-
32
- const res = await appData.getDocument(testDocument._id);
33
- assert.deepStrictEqual(res?.foo, 'bar');
34
- });
35
- });
@@ -1,40 +0,0 @@
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
- const assert_1 = __importDefault(require("assert"));
7
- const lodash_1 = require("lodash");
8
- const mocha_1 = require("mocha");
9
- const mongodb_1 = require("mongodb");
10
- const lib_1 = require("../lib");
11
- const getMongoClient_1 = __importDefault(require("./getMongoClient"));
12
- (0, mocha_1.describe)('packages/mongodb/fixtures', () => {
13
- let mongoClient;
14
- let collection;
15
- const collectionName = 'currency';
16
- const oldArray = [
17
- { _id: new mongodb_1.ObjectId(), name: 'CZK' },
18
- { _id: new mongodb_1.ObjectId(), name: 'EUR' },
19
- ];
20
- const newArray = [
21
- ...oldArray,
22
- { _id: new mongodb_1.ObjectId(), name: 'USD' },
23
- ];
24
- (0, mocha_1.before)(async () => {
25
- mongoClient = await (0, getMongoClient_1.default)();
26
- collection = mongoClient.db().collection(collectionName);
27
- });
28
- (0, mocha_1.beforeEach)(async () => {
29
- await collection.drop().catch(lodash_1.noop);
30
- });
31
- (0, mocha_1.it)('should fixtures work', async () => {
32
- await lib_1.fixtures.ensureInCollection(oldArray, collection);
33
- assert_1.default.deepStrictEqual(await collection.countDocuments(), 2);
34
- await lib_1.fixtures.ensureInCollection(oldArray, collection);
35
- assert_1.default.deepStrictEqual(await collection.countDocuments(), 2);
36
- await lib_1.fixtures.ensureInCollection(newArray, collection);
37
- assert_1.default.deepStrictEqual(await collection.countDocuments(), 3);
38
- });
39
- });
40
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZml4dHVyZXMudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImZpeHR1cmVzLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsbUNBQThCO0FBQzlCLGlDQUVlO0FBQ2YscUNBQTREO0FBQzVELGdDQUFrQztBQUNsQyxzRUFBd0Q7QUFFeEQsSUFBQSxnQkFBUSxFQUFDLDJCQUEyQixFQUFFLEdBQUcsRUFBRTtJQUN2QyxJQUFJLFdBQXdCLENBQUM7SUFDN0IsSUFBSSxVQUFzQixDQUFDO0lBQzNCLE1BQU0sY0FBYyxHQUFHLFVBQVUsQ0FBQztJQUVsQyxNQUFNLFFBQVEsR0FBRztRQUNiLEVBQUUsR0FBRyxFQUFFLElBQUksa0JBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUU7UUFDcEMsRUFBRSxHQUFHLEVBQUUsSUFBSSxrQkFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRTtLQUN2QyxDQUFDO0lBRUYsTUFBTSxRQUFRLEdBQUc7UUFDYixHQUFHLFFBQVE7UUFDWCxFQUFFLEdBQUcsRUFBRSxJQUFJLGtCQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFO0tBQ3ZDLENBQUM7SUFFRixJQUFBLGNBQU0sRUFBQyxLQUFLLElBQUksRUFBRTtRQUNkLFdBQVcsR0FBRyxNQUFNLElBQUEsd0JBQXdCLEdBQUUsQ0FBQztRQUMvQyxVQUFVLEdBQUcsV0FBVyxDQUFDLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUM3RCxDQUFDLENBQUMsQ0FBQztJQUVILElBQUEsa0JBQVUsRUFBQyxLQUFLLElBQUksRUFBRTtRQUNsQixNQUFNLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsYUFBSSxDQUFDLENBQUM7SUFDeEMsQ0FBQyxDQUFDLENBQUM7SUFFSCxJQUFBLFVBQUUsRUFBQyxzQkFBc0IsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNsQyxNQUFNLGNBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDeEQsZ0JBQU0sQ0FBQyxlQUFlLENBQUMsTUFBTSxVQUFVLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFN0QsTUFBTSxjQUFRLENBQUMsa0JBQWtCLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1FBQ3hELGdCQUFNLENBQUMsZUFBZSxDQUFDLE1BQU0sVUFBVSxDQUFDLGNBQWMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRTdELE1BQU0sY0FBUSxDQUFDLGtCQUFrQixDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUN4RCxnQkFBTSxDQUFDLGVBQWUsQ0FBQyxNQUFNLFVBQVUsQ0FBQyxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRSxDQUFDLENBQUMsQ0FBQztBQUNQLENBQUMsQ0FBQyxDQUFDIn0=
@@ -1,44 +0,0 @@
1
- import assert from 'assert';
2
- import { noop } from 'lodash';
3
- import {
4
- before, beforeEach, describe, it,
5
- } from 'mocha';
6
- import { Collection, MongoClient, ObjectId } from 'mongodb';
7
- import { fixtures } from '../lib';
8
- import connectAndGetMongoClient from './getMongoClient';
9
-
10
- describe('packages/mongodb/fixtures', () => {
11
- let mongoClient: MongoClient;
12
- let collection: Collection;
13
- const collectionName = 'currency';
14
-
15
- const oldArray = [
16
- { _id: new ObjectId(), name: 'CZK' },
17
- { _id: new ObjectId(), name: 'EUR' },
18
- ];
19
-
20
- const newArray = [
21
- ...oldArray,
22
- { _id: new ObjectId(), name: 'USD' },
23
- ];
24
-
25
- before(async () => {
26
- mongoClient = await connectAndGetMongoClient();
27
- collection = mongoClient.db().collection(collectionName);
28
- });
29
-
30
- beforeEach(async () => {
31
- await collection.drop().catch(noop);
32
- });
33
-
34
- it('should fixtures work', async () => {
35
- await fixtures.ensureInCollection(oldArray, collection);
36
- assert.deepStrictEqual(await collection.countDocuments(), 2);
37
-
38
- await fixtures.ensureInCollection(oldArray, collection);
39
- assert.deepStrictEqual(await collection.countDocuments(), 2);
40
-
41
- await fixtures.ensureInCollection(newArray, collection);
42
- assert.deepStrictEqual(await collection.countDocuments(), 3);
43
- });
44
- });
@@ -1,19 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const mocha_1 = require("mocha");
4
- const lib_1 = require("../lib");
5
- let connectPromise;
6
- const connectAndGetMongoClient = async () => {
7
- if (!connectPromise) {
8
- lib_1.mongoClient.init('mongodb://127.0.0.1:27017', { directConnection: true });
9
- connectPromise = lib_1.mongoClient.getClient().connect();
10
- }
11
- await connectPromise;
12
- return lib_1.mongoClient.getClient();
13
- };
14
- (0, mocha_1.before)(() => connectAndGetMongoClient());
15
- (0, mocha_1.after)(async () => {
16
- await lib_1.mongoClient.getClient().close();
17
- });
18
- exports.default = connectAndGetMongoClient;
19
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0TW9uZ29DbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJnZXRNb25nb0NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLGlDQUFzQztBQUV0QyxnQ0FBcUM7QUFFckMsSUFBSSxjQUFvQyxDQUFDO0FBRXpDLE1BQU0sd0JBQXdCLEdBQUcsS0FBSyxJQUFJLEVBQUU7SUFDeEMsSUFBSSxDQUFDLGNBQWMsRUFBRTtRQUNqQixpQkFBVyxDQUFDLElBQUksQ0FBQywyQkFBMkIsRUFBRSxFQUFFLGdCQUFnQixFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDMUUsY0FBYyxHQUFHLGlCQUFXLENBQUMsU0FBUyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7S0FDdEQ7SUFFRCxNQUFNLGNBQWMsQ0FBQztJQUVyQixPQUFPLGlCQUFXLENBQUMsU0FBUyxFQUFFLENBQUM7QUFDbkMsQ0FBQyxDQUFDO0FBRUYsSUFBQSxjQUFNLEVBQUMsR0FBRyxFQUFFLENBQUMsd0JBQXdCLEVBQUUsQ0FBQyxDQUFDO0FBRXpDLElBQUEsYUFBSyxFQUFDLEtBQUssSUFBSSxFQUFFO0lBQ2IsTUFBTSxpQkFBVyxDQUFDLFNBQVMsRUFBRSxDQUFDLEtBQUssRUFBRSxDQUFDO0FBQzFDLENBQUMsQ0FBQyxDQUFDO0FBRUgsa0JBQWUsd0JBQXdCLENBQUMifQ==
@@ -1,24 +0,0 @@
1
- import { after, before } from 'mocha';
2
- import { MongoClient } from 'mongodb';
3
- import { mongoClient } from '../lib';
4
-
5
- let connectPromise: Promise<MongoClient>;
6
-
7
- const connectAndGetMongoClient = async () => {
8
- if (!connectPromise) {
9
- mongoClient.init('mongodb://127.0.0.1:27017', { directConnection: true });
10
- connectPromise = mongoClient.getClient().connect();
11
- }
12
-
13
- await connectPromise;
14
-
15
- return mongoClient.getClient();
16
- };
17
-
18
- before(() => connectAndGetMongoClient());
19
-
20
- after(async () => {
21
- await mongoClient.getClient().close();
22
- });
23
-
24
- export default connectAndGetMongoClient;
@@ -1,7 +0,0 @@
1
- "use strict";
2
- const mongodb_1 = require("@storyous/mongodb");
3
- module.exports = new mongodb_1.Migration('empty testing migration', async () => {
4
- const collection = await (0, mongodb_1.getCollection)('exampleCollection');
5
- await collection.createIndex({ updated: 1 });
6
- });
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMTY0MjE1MjA2NDI0OS10ZXN0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiMTY0MjE1MjA2NDI0OS10ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQ0FBNkQ7QUFFN0QsaUJBQVMsSUFBSSxtQkFBUyxDQUFDLHlCQUF5QixFQUFFLEtBQUssSUFBSSxFQUFFO0lBQ3pELE1BQU0sVUFBVSxHQUFHLE1BQU0sSUFBQSx1QkFBYSxFQUFDLG1CQUFtQixDQUFDLENBQUM7SUFFNUQsTUFBTSxVQUFVLENBQUMsV0FBVyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDakQsQ0FBQyxDQUFDLENBQUMifQ==
@@ -1,7 +0,0 @@
1
- import { getCollection, Migration } from '@storyous/mongodb';
2
-
3
- export = new Migration('empty testing migration', async () => {
4
- const collection = await getCollection('exampleCollection');
5
-
6
- await collection.createIndex({ updated: 1 });
7
- });
@@ -1,151 +0,0 @@
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
- const assert_1 = __importDefault(require("assert"));
7
- const lodash_1 = require("lodash");
8
- const mocha_1 = require("mocha");
9
- const sinon_1 = __importDefault(require("sinon"));
10
- const lib_1 = require("../lib");
11
- const getMongoClient_1 = __importDefault(require("./getMongoClient"));
12
- (0, mocha_1.describe)('packages/mongodb/mongoLocker', () => {
13
- let mongoClient;
14
- let collection;
15
- const collectionName = 'customLocks';
16
- (0, mocha_1.beforeEach)(async () => {
17
- mongoClient = await (0, getMongoClient_1.default)();
18
- collection = mongoClient.db().collection(collectionName);
19
- await collection.drop().catch(lodash_1.noop);
20
- });
21
- [
22
- { description: 'default mongoLocker instance', locker: () => lib_1.mongoLocker },
23
- { description: 'custom getMongoLocker', locker: () => (0, lib_1.getMongoLocker)(collection) },
24
- ]
25
- .forEach((suite) => {
26
- (0, mocha_1.describe)(suite.description, () => {
27
- let locker;
28
- (0, mocha_1.beforeEach)(async () => {
29
- locker = await suite.locker();
30
- });
31
- (0, mocha_1.it)('should acquire and release a lock', async () => {
32
- let i = 0;
33
- const callback = sinon_1.default.spy(() => ++i);
34
- const result1 = await locker('AAA', callback);
35
- assert_1.default.strictEqual(result1, 1);
36
- const result2 = await locker('AAA', callback);
37
- assert_1.default.strictEqual(result2, 2);
38
- assert_1.default.deepStrictEqual(callback.callCount, 2);
39
- });
40
- (0, mocha_1.it)('should not be possible to acquire the lock twice at once', async () => {
41
- const callback = sinon_1.default.spy(() => new Promise((resolve) => { setTimeout(resolve, 50); }));
42
- const callLocker = () => locker('AAA', callback, { noLaterThan: 0 });
43
- const concurrency = 10;
44
- const promises = (0, lodash_1.times)(concurrency, callLocker);
45
- // Node 10 or less does not support allSettled. Going through good old cycle in such case
46
- if (Promise.allSettled) {
47
- await Promise.allSettled(promises); // just to get rid of UnhandledRejectionErrors
48
- }
49
- else {
50
- // just to get rid of UnhandledRejectionErrors
51
- promises.forEach((promise) => promise.catch(() => { }));
52
- for (let i = 0; i < promises.length; i++) {
53
- try {
54
- await promises[i]; // eslint-disable-line
55
- }
56
- catch (err) {
57
- // That's ok, we expect there can be errors
58
- }
59
- }
60
- }
61
- const stats = {
62
- resolved: 0,
63
- failed: 0,
64
- };
65
- for (const promise of promises) {
66
- try {
67
- await promise; // eslint-disable-line no-await-in-loop
68
- stats.resolved++;
69
- }
70
- catch (err) {
71
- (0, assert_1.default)(/The lock is already acquired./.test(err?.message));
72
- stats.failed++;
73
- }
74
- }
75
- assert_1.default.deepStrictEqual(callback.callCount, 1, 'The callback should be called only once');
76
- assert_1.default.deepStrictEqual(stats, {
77
- resolved: 1,
78
- failed: concurrency - 1,
79
- });
80
- });
81
- (0, mocha_1.it)('should propagate an error and release the lock if the callback fails', async () => {
82
- await assert_1.default.rejects(() => locker('AAA', async () => {
83
- throw new Error('Some error occurred');
84
- }), /Some error occurred/);
85
- const callback = sinon_1.default.spy();
86
- await locker('AAA', callback);
87
- assert_1.default.strictEqual(callback.callCount, 1);
88
- });
89
- (0, mocha_1.it)('should be able to handle few concurrent tasks by waiting some time and acquire retries', async () => {
90
- const callTimes = [];
91
- const callback = sinon_1.default.spy(async () => {
92
- callTimes.push(new Date());
93
- await new Promise((resolve) => { setTimeout(resolve, 150); });
94
- callTimes.push(new Date());
95
- }); // default retryDelay is 200
96
- const callLocker = () => locker('AAA', callback);
97
- await Promise.all((0, lodash_1.times)(3, callLocker));
98
- assert_1.default.strictEqual(callback.callCount, 3);
99
- callTimes.forEach((time, i) => {
100
- if (i > 0) {
101
- (0, assert_1.default)(time > callTimes[i - 1], 'There was a parallel callback execution!');
102
- }
103
- });
104
- });
105
- (0, mocha_1.it)('should be possible to override a lock which expired yet', async () => {
106
- const expireIn = 500;
107
- const array = [];
108
- const key = 'AAA';
109
- const firstCallPromise = locker(key, async () => {
110
- array.push(1);
111
- // the method last too long
112
- await new Promise((resolve) => { setTimeout(resolve, 2 * expireIn); });
113
- array.push(3);
114
- }, { expireIn });
115
- await new Promise((resolve) => { setTimeout(resolve, expireIn); });
116
- const secondCallPromise = locker('AAA', async () => {
117
- array.push(2);
118
- }, { expireIn });
119
- await Promise.all([firstCallPromise, secondCallPromise]);
120
- assert_1.default.deepStrictEqual(array, [1, 2, 3]);
121
- });
122
- });
123
- });
124
- (0, mocha_1.describe)('getMongoLocker', () => {
125
- (0, mocha_1.it)('should create and TTL index on the right field', async () => {
126
- await mongoClient.db()
127
- .createCollection(collectionName);
128
- let indexes = await collection.indexes();
129
- assert_1.default.deepStrictEqual(indexes.length, 1); // ensure there is only mandatory _id index
130
- const locker = await (0, lib_1.getMongoLocker)(collection);
131
- indexes = await collection.indexes();
132
- assert_1.default.deepStrictEqual(indexes.length, 2, 'No or wrong indexes has been created!');
133
- assert_1.default.deepStrictEqual((0, lodash_1.pick)(indexes[1], 'key', 'expireAfterSeconds'), {
134
- expireAfterSeconds: 0,
135
- key: {
136
- expiresAt: 1,
137
- },
138
- }, 'No or wrong indexes has been created!');
139
- const startedAt = new Date();
140
- const someKey = 'someKey';
141
- const expireIn = 55000;
142
- await locker(someKey, async () => {
143
- const document = await collection.findOne({});
144
- assert_1.default.strictEqual(document?._id, someKey);
145
- (0, assert_1.default)(document.expiresAt >= new Date(startedAt.getTime() + expireIn), 'The expiresAt property has to be greater then startedAt + expiresIn');
146
- (0, assert_1.default)(document.expiresAt < new Date(Date.now() + expireIn), 'The acquiredAt property has to be younger then present + expiresIn');
147
- }, { expireIn });
148
- });
149
- });
150
- });
151
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uZ29Mb2NrZXIudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm1vbmdvTG9ja2VyLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxvREFBNEI7QUFDNUIsbUNBQTJDO0FBQzNDLGlDQUFpRDtBQUVqRCxrREFBMEI7QUFDMUIsZ0NBRWdCO0FBRWhCLHNFQUF3RDtBQUV4RCxJQUFBLGdCQUFRLEVBQUMsOEJBQThCLEVBQUUsR0FBRyxFQUFFO0lBRTFDLElBQUksV0FBd0IsQ0FBQztJQUM3QixJQUFJLFVBQXNCLENBQUM7SUFDM0IsTUFBTSxjQUFjLEdBQUcsYUFBYSxDQUFDO0lBRXJDLElBQUEsa0JBQVUsRUFBQyxLQUFLLElBQUksRUFBRTtRQUNsQixXQUFXLEdBQUcsTUFBTSxJQUFBLHdCQUF3QixHQUFFLENBQUM7UUFDL0MsVUFBVSxHQUFHLFdBQVcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDekQsTUFBTSxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLGFBQUksQ0FBQyxDQUFDO0lBQ3hDLENBQUMsQ0FBQyxDQUFDO0lBRUg7UUFDSSxFQUFFLFdBQVcsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsaUJBQVcsRUFBRTtRQUMxRSxFQUFFLFdBQVcsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBQSxvQkFBYyxFQUFDLFVBQVUsQ0FBQyxFQUFFO0tBQ3JGO1NBQ0ksT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFFZixJQUFBLGdCQUFRLEVBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUU7WUFFN0IsSUFBSSxNQUF3RixDQUFDO1lBRTdGLElBQUEsa0JBQVUsRUFBQyxLQUFLLElBQUksRUFBRTtnQkFDbEIsTUFBTSxHQUFHLE1BQU0sS0FBSyxDQUFDLE1BQU0sRUFBRSxD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