equipped 4.0.2 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +68 -0
  3. package/lib/cache/cache.d.ts +2 -2
  4. package/lib/cache/types/redis-cache.d.ts +3 -3
  5. package/lib/cache/types/redis-cache.js +7 -12
  6. package/lib/db/_instance.d.ts +39 -0
  7. package/lib/db/_instance.js +65 -0
  8. package/lib/db/debezium.d.ts +10 -0
  9. package/lib/db/debezium.js +11 -0
  10. package/lib/db/index.d.ts +2 -0
  11. package/lib/{mongoose → db}/index.js +0 -7
  12. package/lib/db/mongoose/changes.d.ts +8 -0
  13. package/lib/db/mongoose/changes.js +99 -0
  14. package/lib/db/mongoose/index.d.ts +15 -0
  15. package/lib/db/mongoose/index.js +73 -0
  16. package/lib/db/mongoose/query.d.ts +3 -0
  17. package/lib/{mongoose → db/mongoose}/query.js +14 -30
  18. package/lib/{mongoose → db}/query.d.ts +21 -24
  19. package/lib/db/query.js +20 -0
  20. package/lib/errors/customError.d.ts +1 -1
  21. package/lib/errors/index.d.ts +4 -4
  22. package/lib/errors/index.js +4 -4
  23. package/lib/errors/types/accessTokenExpired.js +2 -2
  24. package/lib/errors/types/accountNotVerifiedError.js +2 -2
  25. package/lib/errors/types/badRequestError.js +2 -2
  26. package/lib/errors/types/invalidToken.js +2 -2
  27. package/lib/errors/types/notAuthenticatedError.js +2 -2
  28. package/lib/errors/types/notAuthorizedError.js +2 -2
  29. package/lib/errors/types/notFoundError.js +2 -2
  30. package/lib/errors/types/refreshTokenMisusedError.js +2 -2
  31. package/lib/errors/types/validationError.js +2 -2
  32. package/lib/events/index.d.ts +22 -0
  33. package/lib/events/index.js +15 -0
  34. package/lib/events/kafka.d.ts +11 -0
  35. package/lib/events/kafka.js +85 -0
  36. package/lib/events/rabbit.d.ts +11 -4
  37. package/lib/events/rabbit.js +72 -38
  38. package/lib/exit.d.ts +1 -0
  39. package/lib/exit.js +7 -2
  40. package/lib/index.d.ts +4 -3
  41. package/lib/index.js +6 -4
  42. package/lib/instance/index.d.ts +24 -0
  43. package/lib/instance/index.js +92 -0
  44. package/lib/instance/settings.d.ts +26 -0
  45. package/lib/instance/settings.js +28 -0
  46. package/lib/listeners/emitter.d.ts +1 -0
  47. package/lib/listeners/emitter.js +20 -12
  48. package/lib/logger/index.d.ts +1 -4
  49. package/lib/logger/index.js +12 -5
  50. package/lib/server/app.d.ts +11 -0
  51. package/lib/{express → server}/app.js +12 -28
  52. package/lib/server/controllers/index.js +39 -0
  53. package/lib/{express → server}/controllers/request.d.ts +7 -3
  54. package/lib/server/controllers/request.js +74 -0
  55. package/lib/{express → server}/index.d.ts +2 -1
  56. package/lib/{express → server}/index.js +3 -0
  57. package/lib/{express/app.d.ts → server/routes.d.ts} +2 -8
  58. package/lib/server/routes.js +36 -0
  59. package/lib/utils/json.d.ts +1 -0
  60. package/lib/utils/json.js +12 -0
  61. package/lib/utils/retry.d.ts +2 -0
  62. package/lib/utils/retry.js +16 -0
  63. package/lib/utils/tokens.js +2 -2
  64. package/lib/validations/index.d.ts +26 -25
  65. package/package.json +24 -16
  66. package/lib/events/events.d.ts +0 -17
  67. package/lib/events/events.js +0 -26
  68. package/lib/express/controllers/index.js +0 -76
  69. package/lib/express/controllers/request.js +0 -48
  70. package/lib/instance.d.ts +0 -43
  71. package/lib/instance.js +0 -115
  72. package/lib/mongoose/changeStreams.d.ts +0 -25
  73. package/lib/mongoose/changeStreams.js +0 -93
  74. package/lib/mongoose/index.d.ts +0 -4
  75. package/lib/{express → server}/controllers/index.d.ts +0 -0
  76. package/lib/{express → server}/middlewares/errorHandler.d.ts +0 -0
  77. package/lib/{express → server}/middlewares/errorHandler.js +0 -0
  78. package/lib/{express → server}/middlewares/index.d.ts +2 -2
  79. package/lib/{express → server}/middlewares/index.js +2 -2
  80. package/lib/{express → server}/middlewares/notFoundHandler.d.ts +0 -0
  81. package/lib/{express → server}/middlewares/notFoundHandler.js +1 -1
  82. package/lib/{express → server}/middlewares/parseAuthUser.d.ts +0 -0
  83. package/lib/{express → server}/middlewares/parseAuthUser.js +2 -2
  84. /package/lib/{express → server}/middlewares/requireAuthUser.d.ts +0 -0
  85. /package/lib/{express → server}/middlewares/requireAuthUser.js +0 -0
  86. /package/lib/{express → server}/middlewares/requireRefreshUser.d.ts +0 -0
  87. /package/lib/{express → server}/middlewares/requireRefreshUser.js +0 -0
  88. /package/lib/{express → server}/statusCodes.d.ts +0 -0
  89. /package/lib/{express → server}/statusCodes.js +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,44 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [4.1.0](https://github.com/kevinand11/equipped/compare/v4.0.2-alpha.3...v4.1.0) (2023-03-07)
6
+
7
+
8
+ ### Features
9
+
10
+ * access db name from mongoose ([febdee0](https://github.com/kevinand11/equipped/commit/febdee0264fe0f7d2de02fcd08a380a8c93df68c))
11
+ * add fanout option for event subscribers ([4f0c060](https://github.com/kevinand11/equipped/commit/4f0c060aa2d99fd6128499d49e1f163d1e93a721))
12
+ * add helmet and supertest ([71ddcad](https://github.com/kevinand11/equipped/commit/71ddcad4e2b191913a890e7480619f1df527fde1))
13
+ * add Id to mongo db ([55a8728](https://github.com/kevinand11/equipped/commit/55a872827a427a65a9be25ce464468935a4c5674))
14
+ * add kafka eventbus ([22f79d4](https://github.com/kevinand11/equipped/commit/22f79d48e48cc7c5695a43089f6a724f479ed81c))
15
+ * automatically start subscribers in Instance.startConnections ([96a07c9](https://github.com/kevinand11/equipped/commit/96a07c923a90b9203920ab490c4554098dfab5e8))
16
+ * enable defaults, getters and virtuals on lean docs ([69f9d2b](https://github.com/kevinand11/equipped/commit/69f9d2b5f26072e91d411cc1dd5e676264a6a586))
17
+ * enable lean documents for query ([ce04a8a](https://github.com/kevinand11/equipped/commit/ce04a8a326025916a32ce017634328c37c09a7e0))
18
+ * enable pre images for all collections ([710457d](https://github.com/kevinand11/equipped/commit/710457d1132cd380a0890b191f98fece4473729f))
19
+ * hydrate cs docs with getters and virtuals ([c93809a](https://github.com/kevinand11/equipped/commit/c93809ab8f2f4597fb310c68dc8d95b9f901aedd))
20
+ * new changestream api ([923660b](https://github.com/kevinand11/equipped/commit/923660b11c1ab6f799c030b37dc6ce06c3b90ebb))
21
+ * server request ip ([371dac1](https://github.com/kevinand11/equipped/commit/371dac18ef729c88da0e8885e1e63e581e8b979b))
22
+ * socket emitters fanout ([65a36db](https://github.com/kevinand11/equipped/commit/65a36db9671205a30fe8aabd3b1763714e94f886))
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * hydrate _id from changes ([65e6539](https://github.com/kevinand11/equipped/commit/65e6539bfc9644421152af3ad5c0436a2b4ed3dc))
28
+ * loop over db connections ([eb3f548](https://github.com/kevinand11/equipped/commit/eb3f548f2e7a2f172cb4ead8ff655df0fc8f3b95))
29
+ * remove cache setInTransaction ([4f1b3c0](https://github.com/kevinand11/equipped/commit/4f1b3c0db37621162065c69fc24eab744675da27))
30
+ * setup debezium connection to mongo ([3d36283](https://github.com/kevinand11/equipped/commit/3d3628349910d8ba0633578b6578f09e682b8145))
31
+
32
+ ### [4.0.2-alpha.3](https://github.com/kevinand11/equipped/compare/v4.0.2-alpha.2...v4.0.2-alpha.3) (2023-02-19)
33
+
34
+ ### [4.0.2-alpha.2](https://github.com/kevinand11/equipped/compare/v4.0.2-alpha.1...v4.0.2-alpha.2) (2023-02-19)
35
+
36
+ ### [4.0.2-alpha.1](https://github.com/kevinand11/equipped/compare/v4.0.2...v4.0.2-alpha.1) (2023-02-19)
37
+
38
+
39
+ ### Features
40
+
41
+ * make db change abstract ([e747c3f](https://github.com/kevinand11/equipped/commit/e747c3f2f74dc178521c3ee4d9a79efc8b160d32))
42
+
5
43
  ### [4.0.2](https://github.com/kevinand11/equipped/compare/v4.0.1...v4.0.2) (2023-02-16)
6
44
 
7
45
  ### [4.0.1](https://github.com/kevinand11/equipped/compare/v4.0.0-alpha-10...v4.0.1) (2023-02-16)
package/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # Equipped
2
+
3
+ <br>
4
+
5
+ ## Installation
6
+
7
+ This is a [Node.js](https://nodejs.org/en/) module available through the [npm registry](https://www.npmjs.com/package/equipped).
8
+ Before installing, [download and install Node.js](https://nodejs.org/en/download/). Node.js 4.2.4 or higher is required.
9
+ If this is a brand new project, make sure to create a `package.json` first with the [`npm init` command](https://docs.npmjs.com/creating-a-package-json-file).
10
+ Installation is done using the [`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
11
+
12
+ ### Using npm:
13
+ npm install equipped
14
+
15
+ ### Using yarn:
16
+ yarn add equipped
17
+
18
+ ### Using CDN:
19
+
20
+ [Equipped jsDelivr CDN](https://www.jsdelivr.com/package/npm/equipped)
21
+
22
+ <br>
23
+
24
+ ## Basic Usage
25
+ Before use, the package must be initialized in the entry point into your application, with the required settings.
26
+ ```ts
27
+ import { Instance } from 'equipped'
28
+
29
+ Instance.initialize({
30
+ isDev: true, // Are you running in a dev environment
31
+ appId: 'testing', // An id to identify your application
32
+ mongoDbURI: 'mongodb://...', // A mongodb url if you want to use a database
33
+ redisURI: 'redis://localhost:6379', // A redis url if you want to use a redis cache. Confirm all other functionality you intend to use do not depend on the cache, even if you are not using a cache directly
34
+ ...other settings
35
+ })
36
+ ```
37
+
38
+ <br>
39
+
40
+ After the app has been initialized, the Instance class returns a singleton that provides access to most functionality provided by Equipped
41
+ ```ts
42
+ import { Instance } from 'equipped'
43
+
44
+ const appInstance = Instance.get()
45
+ ```
46
+
47
+ <br>
48
+
49
+ To start a server
50
+ ```ts
51
+ import { makeController, StatusCodes } from 'equipped'
52
+
53
+ // Aggregate all your routes into an array. This can be defined in the file or imported from your controllers etc
54
+ appInstance.server.routes = [
55
+ {
56
+ path: '/',
57
+ method: 'get',
58
+ controllers: [makeController(async () => {
59
+ return {
60
+ result: 'Hello world',
61
+ status: StatusCodes.Ok
62
+ }
63
+ })]
64
+ }
65
+ ]
66
+
67
+ await appInstance.server.start(8080)
68
+ ```
@@ -1,7 +1,7 @@
1
1
  export declare abstract class Cache {
2
- abstract connect(): Promise<void>;
2
+ abstract start(): Promise<void>;
3
+ abstract close(): Promise<void>;
3
4
  abstract set(key: string, data: string, ttlInSecs: number): Promise<void>;
4
- abstract setInTransaction(key: string, data: string, ttlInSecs: number): Promise<[string, string]>;
5
5
  abstract get(key: string): Promise<string | null>;
6
6
  abstract delete(key: string): Promise<void>;
7
7
  }
@@ -2,10 +2,10 @@ import { createClient } from 'redis';
2
2
  import { Cache } from '../cache';
3
3
  export declare class RedisCache extends Cache {
4
4
  client: ReturnType<typeof createClient>;
5
- constructor(connection: string);
6
- connect(): Promise<void>;
5
+ constructor();
6
+ start(): Promise<void>;
7
+ close(): Promise<void>;
7
8
  delete(key: string): Promise<void>;
8
9
  get(key: string): Promise<string | null>;
9
10
  set(key: string, data: string, ttlInSecs: number): Promise<void>;
10
- setInTransaction(key: string, data: string, ttlInSecs: number): Promise<[string, string]>;
11
11
  }
@@ -6,18 +6,19 @@ const exit_1 = require("../../exit");
6
6
  const instance_1 = require("../../instance");
7
7
  const cache_1 = require("../cache");
8
8
  class RedisCache extends cache_1.Cache {
9
- constructor(connection) {
9
+ constructor() {
10
10
  super();
11
- this.client = (0, redis_1.createClient)({ url: connection });
11
+ this.client = (0, redis_1.createClient)({ url: instance_1.Instance.get().settings.redisURI });
12
12
  this.client.on('error', async (error) => {
13
- await instance_1.Instance.get().logger.error('Redis failed with error:', error);
14
- process.exit(1);
13
+ (0, exit_1.exit)(`Redis failed with error: ${error}`);
15
14
  });
16
- (0, exit_1.addWaitBeforeExit)(() => this.client.quit());
17
15
  }
18
- async connect() {
16
+ async start() {
19
17
  await this.client.connect();
20
18
  }
19
+ async close() {
20
+ this.client.quit();
21
+ }
21
22
  async delete(key) {
22
23
  await this.client.del(key);
23
24
  }
@@ -30,11 +31,5 @@ class RedisCache extends cache_1.Cache {
30
31
  else
31
32
  this.client.set(key, data);
32
33
  }
33
- async setInTransaction(key, data, ttlInSecs) {
34
- return await this.client.multi()
35
- .get(key)
36
- .setEx(key, ttlInSecs, data)
37
- .exec();
38
- }
39
34
  }
40
35
  exports.RedisCache = RedisCache;
@@ -0,0 +1,39 @@
1
+ import { BaseEntity } from '../structure';
2
+ import { DebeziumSetup } from './debezium';
3
+ import { QueryParams, QueryResults } from './query';
4
+ export declare abstract class Db {
5
+ #private;
6
+ abstract change<Model, Entity extends BaseEntity>(collection: any, callbacks: DbChangeCallbacks<Model, Entity>, mapper: (model: Model | null) => Entity | null): DbChange<Model, Entity>;
7
+ abstract query<Model>(collection: any, params: QueryParams): Promise<QueryResults<Model>>;
8
+ protected _addToDbChanges(dbChange: DbChange<any, any>): this;
9
+ startAllDbChanges(): Promise<void>;
10
+ abstract start(): Promise<void>;
11
+ abstract close(): Promise<void>;
12
+ }
13
+ export declare abstract class DbChange<Model, Entity extends BaseEntity> {
14
+ #private;
15
+ constructor(callbacks: DbChangeCallbacks<Model, Entity>, mapper: (model: Model | null) => Entity | null);
16
+ abstract start(): Promise<void>;
17
+ get callbacks(): Readonly<DbChangeCallbacks<Model, Entity>>;
18
+ get mapper(): (model: Model | null) => Entity | null;
19
+ protected _setup(key: string, data: DebeziumSetup): Promise<boolean>;
20
+ }
21
+ type DeepPartial<T> = {
22
+ [P in keyof T]?: DeepPartial<T[P]>;
23
+ };
24
+ export type DbChangeCallbacks<Model, Entity> = {
25
+ created?: (data: {
26
+ before: null;
27
+ after: Entity;
28
+ }) => Promise<void>;
29
+ updated?: (data: {
30
+ before: Entity;
31
+ after: Entity;
32
+ changes: DeepPartial<Model>;
33
+ }) => Promise<void>;
34
+ deleted?: (data: {
35
+ before: Entity;
36
+ after: null;
37
+ }) => Promise<void>;
38
+ };
39
+ export {};
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
8
+ if (kind === "m") throw new TypeError("Private method is not writable");
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ var _Db_dbChanges, _DbChange_callbacks, _DbChange_mapper;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.DbChange = exports.Db = void 0;
19
+ const axios_1 = __importDefault(require("axios"));
20
+ const exit_1 = require("../exit");
21
+ const instance_1 = require("../instance");
22
+ const debezium_1 = require("./debezium");
23
+ class Db {
24
+ constructor() {
25
+ _Db_dbChanges.set(this, []);
26
+ }
27
+ _addToDbChanges(dbChange) {
28
+ __classPrivateFieldGet(this, _Db_dbChanges, "f").push(dbChange);
29
+ return this;
30
+ }
31
+ async startAllDbChanges() {
32
+ await Promise.all(__classPrivateFieldGet(this, _Db_dbChanges, "f").map((change) => change.start()));
33
+ }
34
+ }
35
+ exports.Db = Db;
36
+ _Db_dbChanges = new WeakMap();
37
+ class DbChange {
38
+ constructor(callbacks, mapper) {
39
+ _DbChange_callbacks.set(this, {});
40
+ _DbChange_mapper.set(this, void 0);
41
+ __classPrivateFieldSet(this, _DbChange_callbacks, callbacks, "f");
42
+ __classPrivateFieldSet(this, _DbChange_mapper, mapper, "f");
43
+ }
44
+ get callbacks() {
45
+ return Object.freeze(__classPrivateFieldGet(this, _DbChange_callbacks, "f"));
46
+ }
47
+ get mapper() {
48
+ return __classPrivateFieldGet(this, _DbChange_mapper, "f");
49
+ }
50
+ async _setup(key, data) {
51
+ data = { ...debezium_1.DefaultDebeziumSetup, ...data };
52
+ const topics = await axios_1.default.put(`/connectors/${key}/config`, data, { baseURL: instance_1.Instance.get().settings.debeziumUrl })
53
+ .then(async () => {
54
+ const res = await axios_1.default.get(`/connectors/${key}/topics`, { baseURL: instance_1.Instance.get().settings.debeziumUrl });
55
+ return res.data[key]?.topics ?? [];
56
+ })
57
+ .catch((err) => {
58
+ (0, exit_1.exit)(`Failed to setup debezium for ${key}: ${err.message}`);
59
+ return [];
60
+ });
61
+ return topics[0] === key;
62
+ }
63
+ }
64
+ exports.DbChange = DbChange;
65
+ _DbChange_callbacks = new WeakMap(), _DbChange_mapper = new WeakMap();
@@ -0,0 +1,10 @@
1
+ export type DebeziumSetup = Partial<{
2
+ 'connector.class': string;
3
+ 'topic.prefix': string;
4
+ 'key.converter': string;
5
+ 'key.converter.schemas.enable': string;
6
+ 'value.converter': string;
7
+ 'value.converter.schemas.enable': string;
8
+ }> & Record<string, string>;
9
+ export declare const TopicPrefix = "equipped";
10
+ export declare const DefaultDebeziumSetup: DebeziumSetup;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultDebeziumSetup = exports.TopicPrefix = void 0;
4
+ exports.TopicPrefix = 'equipped';
5
+ exports.DefaultDebeziumSetup = {
6
+ 'topic.prefix': exports.TopicPrefix,
7
+ 'key.converter': 'org.apache.kafka.connect.json.JsonConverter',
8
+ 'key.converter.schemas.enable': 'false',
9
+ 'value.converter': 'org.apache.kafka.connect.json.JsonConverter',
10
+ 'value.converter.schemas.enable': 'false'
11
+ };
@@ -0,0 +1,2 @@
1
+ export * from './query';
2
+ export { DbChangeCallbacks } from './_instance';
@@ -13,12 +13,5 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
13
13
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
- var __importDefault = (this && this.__importDefault) || function (mod) {
17
- return (mod && mod.__esModule) ? mod : { "default": mod };
18
- };
19
16
  Object.defineProperty(exports, "__esModule", { value: true });
20
- exports.mongoose = void 0;
21
- const mongoose_1 = __importDefault(require("mongoose"));
22
- exports.mongoose = mongoose_1.default;
23
17
  __exportStar(require("./query"), exports);
24
- __exportStar(require("./changeStreams"), exports);
@@ -0,0 +1,8 @@
1
+ import mongoose from 'mongoose';
2
+ import { BaseEntity } from '../../structure';
3
+ import { DbChange, DbChangeCallbacks } from '../_instance';
4
+ export declare class MongoDbChange<Model, Entity extends BaseEntity> extends DbChange<Model, Entity> {
5
+ #private;
6
+ constructor(model: mongoose.Model<Model>, callbacks: DbChangeCallbacks<Model, Entity>, mapper: (model: Model | null) => Entity | null);
7
+ start(): Promise<void>;
8
+ }
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ var _MongoDbChange_started, _MongoDbChange_model;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.MongoDbChange = void 0;
19
+ const mongoose_1 = __importDefault(require("mongoose"));
20
+ const exit_1 = require("../../exit");
21
+ const instance_1 = require("../../instance");
22
+ const retry_1 = require("../../utils/retry");
23
+ const validations_1 = require("../../validations");
24
+ const debezium_1 = require("../debezium");
25
+ const _instance_1 = require("../_instance");
26
+ class MongoDbChange extends _instance_1.DbChange {
27
+ constructor(model, callbacks, mapper) {
28
+ super(callbacks, mapper);
29
+ _MongoDbChange_started.set(this, false);
30
+ _MongoDbChange_model.set(this, void 0);
31
+ __classPrivateFieldSet(this, _MongoDbChange_model, model, "f");
32
+ }
33
+ async start() {
34
+ if (__classPrivateFieldGet(this, _MongoDbChange_started, "f"))
35
+ return;
36
+ __classPrivateFieldSet(this, _MongoDbChange_started, true, "f");
37
+ const model = __classPrivateFieldGet(this, _MongoDbChange_model, "f");
38
+ const dbName = model.db.name;
39
+ const colName = model.collection.name;
40
+ const dbColName = `${dbName}.${colName}`;
41
+ const topic = `${debezium_1.TopicPrefix}.${dbColName}`;
42
+ (0, retry_1.retry)(async () => {
43
+ const { hosts, replicaSet, credentials } = model.collection.conn.getClient().options;
44
+ const started = await this._setup(topic, {
45
+ 'connector.class': 'io.debezium.connector.mongodb.MongoDbConnector',
46
+ 'capture.mode': 'change_streams_update_full_with_pre_image',
47
+ 'mongodb.hosts': `${replicaSet}/` + hosts.map((h) => `${h.host}:${h.port}`).join(','),
48
+ ...(credentials ? {
49
+ 'mongodb.user': credentials.username,
50
+ 'mongodb.pass': credentials.password,
51
+ 'mongodb.auth-source': credentials.source
52
+ } : {}),
53
+ 'collection.include.list': dbColName
54
+ });
55
+ const TestId = new mongoose_1.default.Types.ObjectId('__equipped__');
56
+ if (!started) {
57
+ await model.findByIdAndUpdate(TestId, { $set: { colName } }, { upsert: true });
58
+ await model.findByIdAndDelete(TestId);
59
+ throw new Error(`Wait a few minutes for db changes for ${colName} to initialize...`);
60
+ }
61
+ const hydrate = (data) => model.hydrate({
62
+ ...data, _id: new mongoose_1.default.Types.ObjectId(data._id['$oid'])
63
+ }).toObject({ getters: true, virtuals: true });
64
+ if (started)
65
+ await instance_1.Instance.get().eventBus
66
+ .createSubscriber(topic, async (data) => {
67
+ const op = data.op;
68
+ let before = JSON.parse(data.before ?? 'null');
69
+ let after = JSON.parse(data.after ?? 'null');
70
+ if (before?.__id === TestId || after?.__id === TestId)
71
+ return;
72
+ if (before)
73
+ before = hydrate(before);
74
+ if (after)
75
+ after = hydrate(after);
76
+ if (op === 'c' && this.callbacks.created && after)
77
+ await this.callbacks.created({
78
+ before: null,
79
+ after: this.mapper(after)
80
+ });
81
+ else if (op === 'u' && this.callbacks.updated && before)
82
+ await this.callbacks.updated({
83
+ before: this.mapper(before),
84
+ after: this.mapper(after),
85
+ changes: validations_1.Validation.Differ.from(validations_1.Validation.Differ.diff(before, after))
86
+ });
87
+ else if (op === 'd' && this.callbacks.deleted && before)
88
+ await this.callbacks.deleted({
89
+ before: this.mapper(before),
90
+ after: null
91
+ });
92
+ })
93
+ .subscribe();
94
+ }, 10, 60000)
95
+ .catch((err) => (0, exit_1.exit)(err.message));
96
+ }
97
+ }
98
+ exports.MongoDbChange = MongoDbChange;
99
+ _MongoDbChange_started = new WeakMap(), _MongoDbChange_model = new WeakMap();
@@ -0,0 +1,15 @@
1
+ import mongoose from 'mongoose';
2
+ import { BaseEntity } from '../../structure';
3
+ import { QueryParams, QueryResults } from '../query';
4
+ import { Db, DbChangeCallbacks } from '../_instance';
5
+ import { MongoDbChange } from './changes';
6
+ export declare class MongoDb extends Db {
7
+ #private;
8
+ get Schema(): typeof mongoose.Schema;
9
+ get Id(): mongoose.Types.ObjectId;
10
+ use(dbName?: string): mongoose.Connection;
11
+ change<Model, Entity extends BaseEntity>(model: mongoose.Model<Model>, callbacks: DbChangeCallbacks<Model, Entity>, mapper: (model: Model | null) => Entity | null): MongoDbChange<Model, Entity>;
12
+ query<Model>(model: mongoose.Model<Model>, params: QueryParams): Promise<QueryResults<Model>>;
13
+ start(): Promise<void>;
14
+ close(): Promise<void>;
15
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
8
+ if (kind === "m") throw new TypeError("Private method is not writable");
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
11
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ var _MongoDb_instances, _MongoDb_started, _MongoDb_connections_get;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.MongoDb = void 0;
19
+ const mongoose_1 = __importDefault(require("mongoose"));
20
+ const mongoose_lean_defaults_1 = __importDefault(require("mongoose-lean-defaults"));
21
+ const mongoose_lean_getters_1 = __importDefault(require("mongoose-lean-getters"));
22
+ const mongoose_lean_virtuals_1 = __importDefault(require("mongoose-lean-virtuals"));
23
+ const instance_1 = require("../../instance");
24
+ const _instance_1 = require("../_instance");
25
+ const changes_1 = require("./changes");
26
+ const query_1 = require("./query");
27
+ class MongoDb extends _instance_1.Db {
28
+ constructor() {
29
+ super(...arguments);
30
+ _MongoDb_instances.add(this);
31
+ _MongoDb_started.set(this, false);
32
+ }
33
+ get Schema() {
34
+ return mongoose_1.default.Schema;
35
+ }
36
+ get Id() {
37
+ return new mongoose_1.default.Types.ObjectId();
38
+ }
39
+ use(dbName = 'default') {
40
+ const conn = dbName === 'default' ? mongoose_1.default.connection : mongoose_1.default.connection.useDb(dbName, { useCache: true });
41
+ conn.plugin(mongoose_lean_defaults_1.default).plugin(mongoose_lean_virtuals_1.default).plugin(mongoose_lean_getters_1.default);
42
+ return conn;
43
+ }
44
+ change(model, callbacks, mapper) {
45
+ const change = new changes_1.MongoDbChange(model, callbacks, mapper);
46
+ this._addToDbChanges(change);
47
+ return change;
48
+ }
49
+ async query(model, params) {
50
+ return await (0, query_1.parseMongodbQueryParams)(model, params);
51
+ }
52
+ async start() {
53
+ if (__classPrivateFieldGet(this, _MongoDb_started, "f"))
54
+ return;
55
+ __classPrivateFieldSet(this, _MongoDb_started, true, "f");
56
+ mongoose_1.default.set('strictQuery', true);
57
+ await mongoose_1.default.connect(instance_1.Instance.get().settings.mongoDbURI);
58
+ await Promise.all([mongoose_1.default.connection, ...__classPrivateFieldGet(this, _MongoDb_instances, "a", _MongoDb_connections_get)].map((conn) => {
59
+ return Object.values(conn.models)
60
+ .map(async (model) => {
61
+ await conn.db.command({ collMod: model.collection.name, changeStreamPreAndPostImages: { enabled: true } });
62
+ });
63
+ }).flat());
64
+ }
65
+ async close() {
66
+ await Promise.all(__classPrivateFieldGet(this, _MongoDb_instances, "a", _MongoDb_connections_get).map(async (conn) => conn.close()));
67
+ await mongoose_1.default.disconnect();
68
+ }
69
+ }
70
+ exports.MongoDb = MongoDb;
71
+ _MongoDb_started = new WeakMap(), _MongoDb_instances = new WeakSet(), _MongoDb_connections_get = function _MongoDb_connections_get() {
72
+ return mongoose_1.default.connection.otherDbs ?? [];
73
+ };
@@ -0,0 +1,3 @@
1
+ import mongoose from 'mongoose';
2
+ import { QueryParams, QueryResults } from '../query';
3
+ export declare const parseMongodbQueryParams: <Model>(model: mongoose.Model<Model, {}, {}, {}, mongoose.IfAny<Model, any, mongoose.Document<unknown, {}, Model> & Omit<mongoose.Require_id<Model>, never>>, any>, params: QueryParams) => Promise<QueryResults<Model>>;
@@ -1,28 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.parseQueryParams = exports.Conditions = exports.QueryKeys = void 0;
4
- const instance_1 = require("../instance");
5
- var QueryKeys;
6
- (function (QueryKeys) {
7
- QueryKeys["and"] = "and";
8
- QueryKeys["or"] = "or";
9
- })(QueryKeys = exports.QueryKeys || (exports.QueryKeys = {}));
10
- var Conditions;
11
- (function (Conditions) {
12
- Conditions["lt"] = "lt";
13
- Conditions["lte"] = "lte";
14
- Conditions["gt"] = "gt";
15
- Conditions["gte"] = "gte";
16
- Conditions["eq"] = "eq";
17
- Conditions["ne"] = "ne";
18
- Conditions["in"] = "in";
19
- Conditions["nin"] = "nin";
20
- Conditions["exists"] = "exists";
21
- })(Conditions = exports.Conditions || (exports.Conditions = {}));
22
- const parseQueryParams = async (collection, params) => {
3
+ exports.parseMongodbQueryParams = void 0;
4
+ const instance_1 = require("../../instance");
5
+ const query_1 = require("../query");
6
+ const parseMongodbQueryParams = async (model, params) => {
23
7
  const query = [];
24
- const whereType = Object.values(QueryKeys).indexOf(params.whereType) !== -1 ? params.whereType : QueryKeys.and;
25
- const authType = Object.values(QueryKeys).indexOf(params.authType) !== -1 ? params.authType : QueryKeys.and;
8
+ const whereType = Object.values(query_1.QueryKeys).indexOf(params.whereType) !== -1 ? params.whereType : query_1.QueryKeys.and;
9
+ const authType = Object.values(query_1.QueryKeys).indexOf(params.authType) !== -1 ? params.authType : query_1.QueryKeys.and;
26
10
  const where = buildWhereQuery(params.where ?? [], whereType);
27
11
  if (where)
28
12
  query.push(where);
@@ -46,8 +30,8 @@ const parseQueryParams = async (collection, params) => {
46
30
  const limit = Number(params.limit) <= settings.paginationDefaultLimit ? Number(params.limit) : settings.paginationDefaultLimit;
47
31
  let page = Number.isNaN(Number(params.page)) ? 0 : Number(params.page);
48
32
  page = page < 1 ? 1 : page;
49
- const total = await collection.countDocuments(totalClause).exec();
50
- let builtQuery = collection.find(totalClause);
33
+ const total = await model.countDocuments(totalClause);
34
+ let builtQuery = model.find(totalClause).lean({ virtuals: true, getters: true, defaults: true });
51
35
  if (sort.length)
52
36
  builtQuery = builtQuery.sort(Object.fromEntries(sort));
53
37
  if (!all && limit) {
@@ -55,7 +39,7 @@ const parseQueryParams = async (collection, params) => {
55
39
  if (page)
56
40
  builtQuery = builtQuery.skip((page - 1) * limit);
57
41
  }
58
- const results = await builtQuery.exec();
42
+ const results = await builtQuery;
59
43
  const start = 1;
60
44
  const last = Math.ceil(total / limit) || 1;
61
45
  const next = page >= last ? null : page + 1;
@@ -67,18 +51,18 @@ const parseQueryParams = async (collection, params) => {
67
51
  docs: {
68
52
  limit, total, count: results.length
69
53
  },
70
- results: results.map((r) => r.toJSON())
54
+ results: results
71
55
  };
72
56
  };
73
- exports.parseQueryParams = parseQueryParams;
74
- const buildWhereQuery = (params, key = QueryKeys.and) => {
57
+ exports.parseMongodbQueryParams = parseMongodbQueryParams;
58
+ const buildWhereQuery = (params, key = query_1.QueryKeys.and) => {
75
59
  const where = params.map((param) => {
76
- if (Object.values(QueryKeys).includes(param.condition))
60
+ if (Object.values(query_1.QueryKeys).includes(param.condition))
77
61
  return buildWhereQuery(param.value, param.condition);
78
62
  const { field } = param;
79
63
  const checkedField = field === 'id' ? '_id' : (field ?? '');
80
64
  const checkedValue = param.value === undefined ? '' : param.value;
81
- const checkedCondition = Object.keys(Conditions).indexOf(param.condition) > -1 ? param.condition : Conditions.eq;
65
+ const checkedCondition = Object.keys(query_1.Conditions).indexOf(param.condition) > -1 ? param.condition : query_1.Conditions.eq;
82
66
  return ({
83
67
  field: checkedField,
84
68
  value: checkedValue,