@treatwell/moleculer-essentials 1.0.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 (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -0
  3. package/dist/context-factory-BWO3xPWE.d.cts +520 -0
  4. package/dist/context-factory-BWO3xPWE.d.mts +520 -0
  5. package/dist/index-82e1CXJX.cjs +11 -0
  6. package/dist/index-BV1ZqQrU.mjs +351 -0
  7. package/dist/index-DNJWwcZu.mjs +8 -0
  8. package/dist/index-rZl77S1z.cjs +375 -0
  9. package/dist/index.cjs +1570 -0
  10. package/dist/index.d.cts +373 -0
  11. package/dist/index.d.mts +373 -0
  12. package/dist/index.mjs +1535 -0
  13. package/dist/mixins/database.mixin.cjs +1673 -0
  14. package/dist/mixins/database.mixin.d.cts +958 -0
  15. package/dist/mixins/database.mixin.d.mts +958 -0
  16. package/dist/mixins/database.mixin.mjs +1645 -0
  17. package/dist/mixins/encryptor.mixin.cjs +84 -0
  18. package/dist/mixins/encryptor.mixin.d.cts +31 -0
  19. package/dist/mixins/encryptor.mixin.d.mts +31 -0
  20. package/dist/mixins/encryptor.mixin.mjs +81 -0
  21. package/dist/mixins/global-store.mixin.cjs +56 -0
  22. package/dist/mixins/global-store.mixin.d.cts +39 -0
  23. package/dist/mixins/global-store.mixin.d.mts +39 -0
  24. package/dist/mixins/global-store.mixin.mjs +54 -0
  25. package/dist/mixins/jwt.mixin.cjs +118 -0
  26. package/dist/mixins/jwt.mixin.d.cts +43 -0
  27. package/dist/mixins/jwt.mixin.d.mts +43 -0
  28. package/dist/mixins/jwt.mixin.mjs +115 -0
  29. package/dist/mixins/queue.mixin.cjs +420 -0
  30. package/dist/mixins/queue.mixin.d.cts +150 -0
  31. package/dist/mixins/queue.mixin.d.mts +150 -0
  32. package/dist/mixins/queue.mixin.mjs +414 -0
  33. package/dist/mixins/redis.mixin.cjs +50 -0
  34. package/dist/mixins/redis.mixin.d.cts +27 -0
  35. package/dist/mixins/redis.mixin.d.mts +27 -0
  36. package/dist/mixins/redis.mixin.mjs +48 -0
  37. package/dist/mixins/redlock.mixin.cjs +76 -0
  38. package/dist/mixins/redlock.mixin.d.cts +30 -0
  39. package/dist/mixins/redlock.mixin.d.mts +30 -0
  40. package/dist/mixins/redlock.mixin.mjs +74 -0
  41. package/package.json +181 -0
@@ -0,0 +1,48 @@
1
+ import { Redis } from 'ioredis';
2
+ import { GlobalStoreMixin } from './global-store.mixin.mjs';
3
+ import { w as wrapMixin } from '../index-DNJWwcZu.mjs';
4
+
5
+ function RedisMixin(options, { reuseClient = true, getOptions } = {}) {
6
+ const kKey = Symbol("Redis Key Symbol");
7
+ return wrapMixin({
8
+ mixins: [GlobalStoreMixin()],
9
+ methods: {
10
+ getRedis() {
11
+ return this.redis;
12
+ }
13
+ },
14
+ async started() {
15
+ const finalOptions = {
16
+ ...options,
17
+ ...await getOptions?.(this)
18
+ };
19
+ const key = [
20
+ finalOptions.host,
21
+ finalOptions.port,
22
+ finalOptions.db,
23
+ finalOptions.username,
24
+ finalOptions.path,
25
+ reuseClient ? "" : Math.random()
26
+ ].filter(Boolean).join("|");
27
+ this[kKey] = key;
28
+ this.redis = this.getFromStore("redis", key);
29
+ if (!this.redis) {
30
+ this.redis = new Redis({
31
+ ...finalOptions,
32
+ lazyConnect: true
33
+ });
34
+ this.setClientToStore(
35
+ "redis",
36
+ key,
37
+ this.redis,
38
+ () => this.redis?.disconnect()
39
+ );
40
+ }
41
+ },
42
+ async stopped() {
43
+ await this.removeServiceFromStore("redis", this[kKey]);
44
+ }
45
+ });
46
+ }
47
+
48
+ export { RedisMixin };
@@ -0,0 +1,76 @@
1
+ 'use strict';
2
+
3
+ var moleculer = require('moleculer');
4
+ var ioredis = require('ioredis');
5
+ var Redlock = require('redlock');
6
+ var index = require('../index-82e1CXJX.cjs');
7
+ var mixins_globalStore_mixin = require('./global-store.mixin.cjs');
8
+
9
+ function RedlockMixin(options, { reuseClient = true, redLockOptions, getOptions }) {
10
+ const kKey = Symbol("Redlock Key Symbol");
11
+ return index.wrapMixin({
12
+ mixins: [mixins_globalStore_mixin.GlobalStoreMixin()],
13
+ methods: {
14
+ getRedlock() {
15
+ return this.redlock;
16
+ },
17
+ async withLock(lockKey, lockTTL, action) {
18
+ let lock;
19
+ try {
20
+ lock = await this.getRedlock().acquire(lockKey, lockTTL);
21
+ } catch {
22
+ throw new moleculer.Errors.MoleculerRetryableError("Locked", 503);
23
+ }
24
+ const lockInterval = setInterval(async () => {
25
+ try {
26
+ await lock.extend(lockTTL);
27
+ } catch (err) {
28
+ this.logger.warn(`Unable to extend lock ${lockKey}`, { err });
29
+ }
30
+ return lock.extend(lockTTL);
31
+ }, lockTTL / 2);
32
+ try {
33
+ return await action();
34
+ } finally {
35
+ clearInterval(lockInterval);
36
+ await lock.unlock();
37
+ }
38
+ }
39
+ },
40
+ async started() {
41
+ const finalOptions = {
42
+ ...options,
43
+ ...await getOptions?.(this)
44
+ };
45
+ const key = [
46
+ finalOptions.host,
47
+ finalOptions.port,
48
+ finalOptions.db,
49
+ finalOptions.username,
50
+ finalOptions.path,
51
+ reuseClient ? "" : Math.random()
52
+ ].filter(Boolean).join("|");
53
+ this[kKey] = key;
54
+ let redis = this.getFromStore("redis", key);
55
+ if (!redis) {
56
+ redis = new ioredis.Redis({
57
+ ...finalOptions,
58
+ lazyConnect: true
59
+ });
60
+ this.setClientToStore("redis", key, redis, () => redis?.disconnect());
61
+ }
62
+ this.redlock = new Redlock(
63
+ [redis],
64
+ redLockOptions
65
+ );
66
+ },
67
+ async stopped() {
68
+ if (this.getRedlock()) {
69
+ await this.getRedlock().quit();
70
+ }
71
+ await this.removeServiceFromStore("redis", this[kKey]);
72
+ }
73
+ });
74
+ }
75
+
76
+ exports.RedlockMixin = RedlockMixin;
@@ -0,0 +1,30 @@
1
+ import { a as CustomServiceSchema } from '../context-factory-BWO3xPWE.cjs';
2
+ import { Service } from 'moleculer';
3
+ import { RedisOptions, Redis } from 'ioredis';
4
+ import Redlock from 'redlock';
5
+ import 'bson';
6
+ import 'zod/v4';
7
+ import 'ajv/dist/2019.js';
8
+
9
+ type AllowedOptions = Omit<RedisOptions, 'lazyConnect'>;
10
+ type RedlockMixinOptions = {
11
+ redLockOptions: Redlock.Options;
12
+ reuseClient?: boolean;
13
+ getOptions?: <TService extends Service = Service>(svc: TService) => Promise<AllowedOptions>;
14
+ };
15
+ declare function RedlockMixin(options: AllowedOptions, { reuseClient, redLockOptions, getOptions }: RedlockMixinOptions): Partial<CustomServiceSchema<unknown, {
16
+ getRedlock(): Redlock;
17
+ withLock<T>(lockKey: string, lockTTL: number, action: () => Promise<T>): Promise<T>;
18
+ }, Partial<CustomServiceSchema<unknown, {
19
+ getStore(storeName: string): Map<string, {
20
+ services: Set<unknown>;
21
+ client: Redis;
22
+ onClose: () => Promise<void> | void;
23
+ }>;
24
+ getFromStore(storeName: string, key: string): Redis | null;
25
+ removeServiceFromStore(storeName: string, key: string): Promise<boolean>;
26
+ setClientToStore(storeName: string, key: string, client: Redis, onClose: () => Promise<void> | void): void;
27
+ }, unknown, unknown>>[], unknown>>;
28
+
29
+ export { RedlockMixin };
30
+ export type { RedlockMixinOptions };
@@ -0,0 +1,30 @@
1
+ import { a as CustomServiceSchema } from '../context-factory-BWO3xPWE.mjs';
2
+ import { Service } from 'moleculer';
3
+ import { RedisOptions, Redis } from 'ioredis';
4
+ import Redlock from 'redlock';
5
+ import 'bson';
6
+ import 'zod/v4';
7
+ import 'ajv/dist/2019.js';
8
+
9
+ type AllowedOptions = Omit<RedisOptions, 'lazyConnect'>;
10
+ type RedlockMixinOptions = {
11
+ redLockOptions: Redlock.Options;
12
+ reuseClient?: boolean;
13
+ getOptions?: <TService extends Service = Service>(svc: TService) => Promise<AllowedOptions>;
14
+ };
15
+ declare function RedlockMixin(options: AllowedOptions, { reuseClient, redLockOptions, getOptions }: RedlockMixinOptions): Partial<CustomServiceSchema<unknown, {
16
+ getRedlock(): Redlock;
17
+ withLock<T>(lockKey: string, lockTTL: number, action: () => Promise<T>): Promise<T>;
18
+ }, Partial<CustomServiceSchema<unknown, {
19
+ getStore(storeName: string): Map<string, {
20
+ services: Set<unknown>;
21
+ client: Redis;
22
+ onClose: () => Promise<void> | void;
23
+ }>;
24
+ getFromStore(storeName: string, key: string): Redis | null;
25
+ removeServiceFromStore(storeName: string, key: string): Promise<boolean>;
26
+ setClientToStore(storeName: string, key: string, client: Redis, onClose: () => Promise<void> | void): void;
27
+ }, unknown, unknown>>[], unknown>>;
28
+
29
+ export { RedlockMixin };
30
+ export type { RedlockMixinOptions };
@@ -0,0 +1,74 @@
1
+ import { Errors } from 'moleculer';
2
+ import { Redis } from 'ioredis';
3
+ import Redlock from 'redlock';
4
+ import { w as wrapMixin } from '../index-DNJWwcZu.mjs';
5
+ import { GlobalStoreMixin } from './global-store.mixin.mjs';
6
+
7
+ function RedlockMixin(options, { reuseClient = true, redLockOptions, getOptions }) {
8
+ const kKey = Symbol("Redlock Key Symbol");
9
+ return wrapMixin({
10
+ mixins: [GlobalStoreMixin()],
11
+ methods: {
12
+ getRedlock() {
13
+ return this.redlock;
14
+ },
15
+ async withLock(lockKey, lockTTL, action) {
16
+ let lock;
17
+ try {
18
+ lock = await this.getRedlock().acquire(lockKey, lockTTL);
19
+ } catch {
20
+ throw new Errors.MoleculerRetryableError("Locked", 503);
21
+ }
22
+ const lockInterval = setInterval(async () => {
23
+ try {
24
+ await lock.extend(lockTTL);
25
+ } catch (err) {
26
+ this.logger.warn(`Unable to extend lock ${lockKey}`, { err });
27
+ }
28
+ return lock.extend(lockTTL);
29
+ }, lockTTL / 2);
30
+ try {
31
+ return await action();
32
+ } finally {
33
+ clearInterval(lockInterval);
34
+ await lock.unlock();
35
+ }
36
+ }
37
+ },
38
+ async started() {
39
+ const finalOptions = {
40
+ ...options,
41
+ ...await getOptions?.(this)
42
+ };
43
+ const key = [
44
+ finalOptions.host,
45
+ finalOptions.port,
46
+ finalOptions.db,
47
+ finalOptions.username,
48
+ finalOptions.path,
49
+ reuseClient ? "" : Math.random()
50
+ ].filter(Boolean).join("|");
51
+ this[kKey] = key;
52
+ let redis = this.getFromStore("redis", key);
53
+ if (!redis) {
54
+ redis = new Redis({
55
+ ...finalOptions,
56
+ lazyConnect: true
57
+ });
58
+ this.setClientToStore("redis", key, redis, () => redis?.disconnect());
59
+ }
60
+ this.redlock = new Redlock(
61
+ [redis],
62
+ redLockOptions
63
+ );
64
+ },
65
+ async stopped() {
66
+ if (this.getRedlock()) {
67
+ await this.getRedlock().quit();
68
+ }
69
+ await this.removeServiceFromStore("redis", this[kKey]);
70
+ }
71
+ });
72
+ }
73
+
74
+ export { RedlockMixin };
package/package.json ADDED
@@ -0,0 +1,181 @@
1
+ {
2
+ "name": "@treatwell/moleculer-essentials",
3
+ "license": "MIT",
4
+ "type": "module",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/treatwell/moleculer-essentials"
8
+ },
9
+ "version": "1.0.0",
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.mjs",
12
+ "types": "./dist/index.d.cts",
13
+ "exports": {
14
+ ".": {
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ },
19
+ "import": {
20
+ "types": "./dist/index.d.mts",
21
+ "default": "./dist/index.mjs"
22
+ }
23
+ },
24
+ "./mixins/database": {
25
+ "require": {
26
+ "types": "./dist/mixins/database.mixin.d.cts",
27
+ "default": "./dist/mixins/database.mixin.cjs"
28
+ },
29
+ "import": {
30
+ "types": "./dist/mixins/database.mixin.d.mts",
31
+ "default": "./dist/mixins/database.mixin.mjs"
32
+ }
33
+ },
34
+ "./mixins/queue": {
35
+ "require": {
36
+ "types": "./dist/mixins/queue.mixin.d.cts",
37
+ "default": "./dist/mixins/queue.mixin.cjs"
38
+ },
39
+ "import": {
40
+ "types": "./dist/mixins/queue.mixin.d.mts",
41
+ "default": "./dist/mixins/queue.mixin.mjs"
42
+ }
43
+ },
44
+ "./mixins/encryptor": {
45
+ "require": {
46
+ "types": "./dist/mixins/encryptor.mixin.d.cts",
47
+ "default": "./dist/mixins/encryptor.mixin.cjs"
48
+ },
49
+ "import": {
50
+ "types": "./dist/mixins/encryptor.mixin.d.mts",
51
+ "default": "./dist/mixins/encryptor.mixin.mjs"
52
+ }
53
+ },
54
+ "./mixins/global-store": {
55
+ "require": {
56
+ "types": "./dist/mixins/global-store.mixin.d.cts",
57
+ "default": "./dist/mixins/global-store.mixin.cjs"
58
+ },
59
+ "import": {
60
+ "types": "./dist/mixins/global-store.mixin.d.mts",
61
+ "default": "./dist/mixins/global-store.mixin.mjs"
62
+ }
63
+ },
64
+ "./mixins/jwt": {
65
+ "require": {
66
+ "types": "./dist/mixins/jwt.mixin.d.cts",
67
+ "default": "./dist/mixins/jwt.mixin.cjs"
68
+ },
69
+ "import": {
70
+ "types": "./dist/mixins/jwt.mixin.d.mts",
71
+ "default": "./dist/mixins/jwt.mixin.mjs"
72
+ }
73
+ },
74
+ "./mixins/redis": {
75
+ "require": {
76
+ "types": "./dist/mixins/redis.mixin.d.cts",
77
+ "default": "./dist/mixins/redis.mixin.cjs"
78
+ },
79
+ "import": {
80
+ "types": "./dist/mixins/redis.mixin.d.mts",
81
+ "default": "./dist/mixins/redis.mixin.mjs"
82
+ }
83
+ },
84
+ "./mixins/redlock": {
85
+ "require": {
86
+ "types": "./dist/mixins/redlock.mixin.d.cts",
87
+ "default": "./dist/mixins/redlock.mixin.cjs"
88
+ },
89
+ "import": {
90
+ "types": "./dist/mixins/redlock.mixin.d.mts",
91
+ "default": "./dist/mixins/redlock.mixin.mjs"
92
+ }
93
+ }
94
+ },
95
+ "scripts": {
96
+ "build": "pkgroll --clean-dist",
97
+ "prepack": "run build",
98
+ "test": "vitest",
99
+ "test:types": "tsc --noEmit",
100
+ "test:lint": "eslint . --max-warnings=0 && prettier -c ."
101
+ },
102
+ "dependencies": {
103
+ "ajv": "^8.12.0",
104
+ "ajv-formats": "^2.1.1",
105
+ "ajv-keywords": "^5.1.0",
106
+ "bson": "^6.2.0",
107
+ "date-fns": "^2.21.3",
108
+ "lodash": "^4.17.20",
109
+ "moleculer": "^0.14.33",
110
+ "pino": "^8.20.0",
111
+ "pino-pretty": "^11.0.0"
112
+ },
113
+ "peerDependencies": {
114
+ "@aws-crypto/client-node": "^4.2.1",
115
+ "bullmq": "^5.12.10",
116
+ "ioredis": "^5.2.3",
117
+ "jsonwebtoken": "^9.0.2",
118
+ "jwks-rsa": "^3.0.1",
119
+ "mongodb": "^6.15.0",
120
+ "redlock": "^4.2.0",
121
+ "zod": "^3.25.0 || ^4.0.0"
122
+ },
123
+ "peerDependenciesMeta": {
124
+ "@aws-crypto/client-node": {
125
+ "optional": true
126
+ },
127
+ "bullmq": {
128
+ "optional": true
129
+ },
130
+ "ioredis": {
131
+ "optional": true
132
+ },
133
+ "jsonwebtoken": {
134
+ "optional": true
135
+ },
136
+ "jwks-rsa": {
137
+ "optional": true
138
+ },
139
+ "mongodb": {
140
+ "optional": true
141
+ },
142
+ "redlock": {
143
+ "optional": true
144
+ }
145
+ },
146
+ "devDependencies": {
147
+ "@aws-crypto/client-node": "^4.2.1",
148
+ "@eslint/js": "^9.33.0",
149
+ "@treatwell/eslint-plugin-moleculer": "^1.1.0",
150
+ "@tsconfig/node-lts": "^22.0.2",
151
+ "@types/jsonwebtoken": "^9.0.10",
152
+ "@types/lodash": "^4.17.20",
153
+ "@types/node": "^24.3.0",
154
+ "@types/redlock": "^4.0.2",
155
+ "bullmq": "^5.12.10",
156
+ "eslint": "^9.33.0",
157
+ "eslint-config-prettier": "^10.1.8",
158
+ "eslint-plugin-prettier": "^5.5.4",
159
+ "ioredis": "^5.2.3",
160
+ "jiti": "^2.5.1",
161
+ "jsonwebtoken": "^9.0.2",
162
+ "jwks-rsa": "^3.0.1",
163
+ "mongodb": "^6.15.0",
164
+ "mongodb-memory-server": "^10.2.0",
165
+ "pkgroll": "^2.15.3",
166
+ "prettier": "^3.6.2",
167
+ "redlock": "^4.2.0",
168
+ "semantic-release": "^24.2.7",
169
+ "typescript": "~5.9.2",
170
+ "typescript-eslint": "^8.40.0",
171
+ "vitest": "^3.2.4",
172
+ "zod": "^4.0.17"
173
+ },
174
+ "files": [
175
+ "dist"
176
+ ],
177
+ "publishConfig": {
178
+ "access": "public"
179
+ },
180
+ "packageManager": "yarn@4.9.2"
181
+ }