n8n-nodes-zalo-loma-funnel 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 (79) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/dist/bridge/zalo-bridge.d.ts +46 -0
  4. package/dist/bridge/zalo-bridge.d.ts.map +1 -0
  5. package/dist/bridge/zalo-bridge.js +213 -0
  6. package/dist/bridge/zalo-bridge.js.map +1 -0
  7. package/dist/credentials/zalo-api.credentials.d.ts +8 -0
  8. package/dist/credentials/zalo-api.credentials.d.ts.map +1 -0
  9. package/dist/credentials/zalo-api.credentials.js +82 -0
  10. package/dist/credentials/zalo-api.credentials.js.map +1 -0
  11. package/dist/index.d.ts +9 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +36 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/interfaces/auth.interface.d.ts +33 -0
  16. package/dist/interfaces/auth.interface.d.ts.map +1 -0
  17. package/dist/interfaces/auth.interface.js +3 -0
  18. package/dist/interfaces/auth.interface.js.map +1 -0
  19. package/dist/interfaces/config.interface.d.ts +37 -0
  20. package/dist/interfaces/config.interface.d.ts.map +1 -0
  21. package/dist/interfaces/config.interface.js +3 -0
  22. package/dist/interfaces/config.interface.js.map +1 -0
  23. package/dist/interfaces/index.d.ts +4 -0
  24. package/dist/interfaces/index.d.ts.map +1 -0
  25. package/dist/interfaces/index.js +20 -0
  26. package/dist/interfaces/index.js.map +1 -0
  27. package/dist/interfaces/zalo.interface.d.ts +74 -0
  28. package/dist/interfaces/zalo.interface.d.ts.map +1 -0
  29. package/dist/interfaces/zalo.interface.js +14 -0
  30. package/dist/interfaces/zalo.interface.js.map +1 -0
  31. package/dist/nodes/ZaloManage/zalo-manage.node.d.ts +6 -0
  32. package/dist/nodes/ZaloManage/zalo-manage.node.d.ts.map +1 -0
  33. package/dist/nodes/ZaloManage/zalo-manage.node.js +426 -0
  34. package/dist/nodes/ZaloManage/zalo-manage.node.js.map +1 -0
  35. package/dist/nodes/ZaloSend/zalo-send.node.d.ts +6 -0
  36. package/dist/nodes/ZaloSend/zalo-send.node.d.ts.map +1 -0
  37. package/dist/nodes/ZaloSend/zalo-send.node.js +538 -0
  38. package/dist/nodes/ZaloSend/zalo-send.node.js.map +1 -0
  39. package/dist/nodes/ZaloTrigger/zalo-trigger.node.d.ts +6 -0
  40. package/dist/nodes/ZaloTrigger/zalo-trigger.node.d.ts.map +1 -0
  41. package/dist/nodes/ZaloTrigger/zalo-trigger.node.js +308 -0
  42. package/dist/nodes/ZaloTrigger/zalo-trigger.node.js.map +1 -0
  43. package/dist/queues/in-memory-queue.d.ts +20 -0
  44. package/dist/queues/in-memory-queue.d.ts.map +1 -0
  45. package/dist/queues/in-memory-queue.js +68 -0
  46. package/dist/queues/in-memory-queue.js.map +1 -0
  47. package/dist/queues/index.d.ts +4 -0
  48. package/dist/queues/index.d.ts.map +1 -0
  49. package/dist/queues/index.js +8 -0
  50. package/dist/queues/index.js.map +1 -0
  51. package/dist/queues/queue.interface.d.ts +15 -0
  52. package/dist/queues/queue.interface.d.ts.map +1 -0
  53. package/dist/queues/queue.interface.js +3 -0
  54. package/dist/queues/queue.interface.js.map +1 -0
  55. package/dist/queues/redis-queue.d.ts +22 -0
  56. package/dist/queues/redis-queue.d.ts.map +1 -0
  57. package/dist/queues/redis-queue.js +65 -0
  58. package/dist/queues/redis-queue.js.map +1 -0
  59. package/dist/services/error-handler.service.d.ts +67 -0
  60. package/dist/services/error-handler.service.d.ts.map +1 -0
  61. package/dist/services/error-handler.service.js +201 -0
  62. package/dist/services/error-handler.service.js.map +1 -0
  63. package/dist/services/index.d.ts +4 -0
  64. package/dist/services/index.d.ts.map +1 -0
  65. package/dist/services/index.js +13 -0
  66. package/dist/services/index.js.map +1 -0
  67. package/dist/services/rate-limiter.service.d.ts +68 -0
  68. package/dist/services/rate-limiter.service.d.ts.map +1 -0
  69. package/dist/services/rate-limiter.service.js +149 -0
  70. package/dist/services/rate-limiter.service.js.map +1 -0
  71. package/dist/services/zalo-connection-manager.service.d.ts +85 -0
  72. package/dist/services/zalo-connection-manager.service.d.ts.map +1 -0
  73. package/dist/services/zalo-connection-manager.service.js +243 -0
  74. package/dist/services/zalo-connection-manager.service.js.map +1 -0
  75. package/dist/utils/auth-helpers.d.ts +25 -0
  76. package/dist/utils/auth-helpers.d.ts.map +1 -0
  77. package/dist/utils/auth-helpers.js +66 -0
  78. package/dist/utils/auth-helpers.js.map +1 -0
  79. package/package.json +75 -0
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZaloConnectionManager = void 0;
4
+ const zca_js_1 = require("zca-js");
5
+ /**
6
+ * Singleton manager for multi-account Zalo connections
7
+ * Handles connection lifecycle, health checks, and auto-reconnect
8
+ */
9
+ class ZaloConnectionManager {
10
+ constructor(config) {
11
+ this.connections = new Map();
12
+ this.config = {
13
+ autoReconnect: true,
14
+ reconnectIntervalMs: 5000,
15
+ maxReconnectAttempts: 10,
16
+ healthCheckIntervalMs: 30000,
17
+ ...config,
18
+ };
19
+ }
20
+ static getInstance(config) {
21
+ if (!ZaloConnectionManager.instance) {
22
+ ZaloConnectionManager.instance = new ZaloConnectionManager(config);
23
+ }
24
+ return ZaloConnectionManager.instance;
25
+ }
26
+ /**
27
+ * Connect to Zalo account using credentials
28
+ */
29
+ async connect(auth) {
30
+ const accountId = this.getAccountId(auth);
31
+ // Return existing connection if valid
32
+ const existing = this.connections.get(accountId);
33
+ if (existing?.isConnected) {
34
+ existing.lastActivity = Date.now();
35
+ return existing.api;
36
+ }
37
+ // Parse cookie string to Cookie array
38
+ const credentials = this.parseCredentials(auth);
39
+ // Create new connection
40
+ const zalo = new zca_js_1.Zalo();
41
+ const api = await zalo.login(credentials);
42
+ const connection = {
43
+ api,
44
+ auth,
45
+ accountId,
46
+ lastActivity: Date.now(),
47
+ isConnected: true,
48
+ reconnectAttempts: 0,
49
+ };
50
+ this.connections.set(accountId, connection);
51
+ this.startHealthCheck();
52
+ return api;
53
+ }
54
+ /**
55
+ * Parse auth to zca-js Credentials format
56
+ */
57
+ parseCredentials(auth) {
58
+ // Try to parse cookie as JSON array first
59
+ let cookie;
60
+ try {
61
+ const parsed = JSON.parse(auth.cookie);
62
+ if (Array.isArray(parsed)) {
63
+ cookie = parsed;
64
+ }
65
+ else {
66
+ // Single cookie object
67
+ cookie = [parsed];
68
+ }
69
+ }
70
+ catch {
71
+ // Cookie is a string, convert to Cookie array
72
+ cookie = this.parseCookieString(auth.cookie);
73
+ }
74
+ return {
75
+ imei: auth.imei,
76
+ cookie,
77
+ userAgent: auth.userAgent,
78
+ };
79
+ }
80
+ /**
81
+ * Parse cookie string (from browser) to Cookie array
82
+ */
83
+ parseCookieString(cookieStr) {
84
+ const cookies = [];
85
+ const pairs = cookieStr.split(';').map((p) => p.trim());
86
+ for (const pair of pairs) {
87
+ const [name, ...valueParts] = pair.split('=');
88
+ if (!name)
89
+ continue;
90
+ cookies.push({
91
+ domain: '.zalo.me',
92
+ expirationDate: Date.now() / 1000 + 86400 * 365,
93
+ hostOnly: false,
94
+ httpOnly: true,
95
+ name: name.trim(),
96
+ path: '/',
97
+ sameSite: 'lax',
98
+ secure: true,
99
+ session: false,
100
+ storeId: '0',
101
+ value: valueParts.join('='),
102
+ });
103
+ }
104
+ return cookies;
105
+ }
106
+ /**
107
+ * Get existing connection by account ID
108
+ */
109
+ getConnection(accountId) {
110
+ const conn = this.connections.get(accountId);
111
+ if (conn?.isConnected) {
112
+ conn.lastActivity = Date.now();
113
+ return conn.api;
114
+ }
115
+ return null;
116
+ }
117
+ /**
118
+ * Get connection by auth credentials
119
+ */
120
+ getConnectionByAuth(auth) {
121
+ return this.getConnection(this.getAccountId(auth));
122
+ }
123
+ /**
124
+ * Disconnect specific account
125
+ */
126
+ async disconnect(accountId) {
127
+ const conn = this.connections.get(accountId);
128
+ if (conn) {
129
+ conn.isConnected = false;
130
+ this.connections.delete(accountId);
131
+ }
132
+ }
133
+ /**
134
+ * Disconnect all accounts
135
+ */
136
+ async disconnectAll() {
137
+ this.stopHealthCheck();
138
+ for (const accountId of this.connections.keys()) {
139
+ await this.disconnect(accountId);
140
+ }
141
+ }
142
+ /**
143
+ * Check if account is connected
144
+ */
145
+ isConnected(accountId) {
146
+ return this.connections.get(accountId)?.isConnected ?? false;
147
+ }
148
+ /**
149
+ * Get all connected account IDs
150
+ */
151
+ getConnectedAccounts() {
152
+ return Array.from(this.connections.entries())
153
+ .filter(([, conn]) => conn.isConnected)
154
+ .map(([id]) => id);
155
+ }
156
+ /**
157
+ * Get account ID from auth credentials
158
+ * Uses accountId if provided, otherwise generates from cookie hash
159
+ */
160
+ getAccountId(auth) {
161
+ if (auth.accountId)
162
+ return auth.accountId;
163
+ // Generate deterministic ID from cookie
164
+ let hash = 0;
165
+ for (let i = 0; i < auth.cookie.length; i++) {
166
+ const char = auth.cookie.charCodeAt(i);
167
+ hash = (hash << 5) - hash + char;
168
+ hash = hash & hash;
169
+ }
170
+ return `zalo_${Math.abs(hash).toString(16)}`;
171
+ }
172
+ /**
173
+ * Start periodic health checks
174
+ */
175
+ startHealthCheck() {
176
+ if (this.healthCheckInterval)
177
+ return;
178
+ this.healthCheckInterval = setInterval(() => {
179
+ this.checkConnections();
180
+ }, this.config.healthCheckIntervalMs);
181
+ }
182
+ /**
183
+ * Stop health checks
184
+ */
185
+ stopHealthCheck() {
186
+ if (this.healthCheckInterval) {
187
+ clearInterval(this.healthCheckInterval);
188
+ this.healthCheckInterval = undefined;
189
+ }
190
+ }
191
+ /**
192
+ * Check all connections and reconnect if needed
193
+ */
194
+ async checkConnections() {
195
+ for (const [, conn] of this.connections.entries()) {
196
+ // Skip if recently active
197
+ const idleTime = Date.now() - conn.lastActivity;
198
+ if (idleTime < this.config.healthCheckIntervalMs)
199
+ continue;
200
+ // Mark as disconnected if idle too long
201
+ if (idleTime > this.config.healthCheckIntervalMs * 3) {
202
+ conn.isConnected = false;
203
+ }
204
+ }
205
+ }
206
+ /**
207
+ * Attempt to reconnect an account
208
+ */
209
+ async reconnect(auth) {
210
+ const accountId = this.getAccountId(auth);
211
+ const conn = this.connections.get(accountId);
212
+ if (conn && conn.reconnectAttempts >= this.config.maxReconnectAttempts) {
213
+ return null;
214
+ }
215
+ if (conn) {
216
+ conn.reconnectAttempts++;
217
+ }
218
+ try {
219
+ await this.disconnect(accountId);
220
+ return await this.connect(auth);
221
+ }
222
+ catch {
223
+ return null;
224
+ }
225
+ }
226
+ /**
227
+ * Get connection stats
228
+ */
229
+ getStats() {
230
+ const accounts = Array.from(this.connections.entries()).map(([id, conn]) => ({
231
+ id,
232
+ isConnected: conn.isConnected,
233
+ lastActivity: conn.lastActivity,
234
+ }));
235
+ return {
236
+ totalConnections: this.connections.size,
237
+ activeConnections: accounts.filter((a) => a.isConnected).length,
238
+ accounts,
239
+ };
240
+ }
241
+ }
242
+ exports.ZaloConnectionManager = ZaloConnectionManager;
243
+ //# sourceMappingURL=zalo-connection-manager.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zalo-connection-manager.service.js","sourceRoot":"","sources":["../../src/services/zalo-connection-manager.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import { IZaloApiAuth, IZaloSessionData } from '../interfaces/auth.interface';
2
+ /**
3
+ * Generate unique account ID if not exists
4
+ */
5
+ export declare function ensureAccountId(auth: IZaloApiAuth): string;
6
+ /**
7
+ * Parse session data from JSON string
8
+ */
9
+ export declare function parseSessionData(sessionData?: string): IZaloSessionData | null;
10
+ /**
11
+ * Serialize session data to JSON string
12
+ */
13
+ export declare function serializeSessionData(data: IZaloSessionData): string;
14
+ /**
15
+ * Mask sensitive data for logging (NEVER log raw values)
16
+ */
17
+ export declare function maskAuth(auth: IZaloApiAuth): Record<string, string>;
18
+ /**
19
+ * Validate required auth fields
20
+ */
21
+ export declare function validateAuth(auth: IZaloApiAuth): {
22
+ valid: boolean;
23
+ errors: string[];
24
+ };
25
+ //# sourceMappingURL=auth-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/auth-helpers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAE9E;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAE1D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAO9E;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,GAAG,MAAM,CAEnE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQnE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG;IAChD,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAmBA"}
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureAccountId = ensureAccountId;
4
+ exports.parseSessionData = parseSessionData;
5
+ exports.serializeSessionData = serializeSessionData;
6
+ exports.maskAuth = maskAuth;
7
+ exports.validateAuth = validateAuth;
8
+ const uuid_1 = require("uuid");
9
+ /**
10
+ * Generate unique account ID if not exists
11
+ */
12
+ function ensureAccountId(auth) {
13
+ return auth.accountId || (0, uuid_1.v4)();
14
+ }
15
+ /**
16
+ * Parse session data from JSON string
17
+ */
18
+ function parseSessionData(sessionData) {
19
+ if (!sessionData)
20
+ return null;
21
+ try {
22
+ return JSON.parse(sessionData);
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ }
28
+ /**
29
+ * Serialize session data to JSON string
30
+ */
31
+ function serializeSessionData(data) {
32
+ return JSON.stringify(data);
33
+ }
34
+ /**
35
+ * Mask sensitive data for logging (NEVER log raw values)
36
+ */
37
+ function maskAuth(auth) {
38
+ return {
39
+ accountId: auth.accountId || 'not-set',
40
+ accountName: auth.accountName || 'unnamed',
41
+ hasCookie: auth.cookie ? 'yes' : 'no',
42
+ hasImei: auth.imei ? 'yes' : 'no',
43
+ hasSession: auth.sessionData ? 'yes' : 'no',
44
+ };
45
+ }
46
+ /**
47
+ * Validate required auth fields
48
+ */
49
+ function validateAuth(auth) {
50
+ const errors = [];
51
+ if (!auth.cookie?.trim()) {
52
+ errors.push('Cookie is required');
53
+ }
54
+ if (!auth.imei?.trim()) {
55
+ errors.push('IMEI is required');
56
+ }
57
+ if (!auth.userAgent?.trim()) {
58
+ errors.push('User Agent is required');
59
+ }
60
+ // Basic cookie validation
61
+ if (auth.cookie && !auth.cookie.includes('zpw_sek')) {
62
+ errors.push('Cookie appears invalid: missing zpw_sek');
63
+ }
64
+ return { valid: errors.length === 0, errors };
65
+ }
66
+ //# sourceMappingURL=auth-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-helpers.js","sourceRoot":"","sources":["../../src/utils/auth-helpers.ts"],"names":[],"mappings":";;AAMA,0CAEC;AAKD,4CAOC;AAKD,oDAEC;AAKD,4BAQC;AAKD,oCAsBC;AAnED,+BAAoC;AAGpC;;GAEG;AACH,SAAgB,eAAe,CAAC,IAAkB;IAChD,OAAO,IAAI,CAAC,SAAS,IAAI,IAAA,SAAM,GAAE,CAAC;AACpC,CAAC;AAED;;GAEG;AACH,SAAgB,gBAAgB,CAAC,WAAoB;IACnD,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAqB,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAgB,oBAAoB,CAAC,IAAsB;IACzD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAgB,QAAQ,CAAC,IAAkB;IACzC,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,SAAS,IAAI,SAAS;QACtC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;QAC1C,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QACrC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QACjC,UAAU,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;KAC5C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,IAAkB;IAI7C,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IAClC,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACxC,CAAC;IAED,0BAA0B;IAC1B,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACpD,MAAM,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC"}
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "n8n-nodes-zalo-loma-funnel",
3
+ "version": "1.0.0",
4
+ "description": "n8n community nodes for Zalo messaging via zca-js",
5
+ "keywords": [
6
+ "n8n",
7
+ "n8n-community-node-package",
8
+ "zalo",
9
+ "messaging",
10
+ "automation"
11
+ ],
12
+ "license": "MIT",
13
+ "author": {
14
+ "name": "Loma Funnel",
15
+ "email": "contact@lomafunnel.com"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "https://github.com/thotran113254/n8n-node-zalo-loma-funnel.git"
20
+ },
21
+ "main": "dist/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "scripts": {
24
+ "build": "tsc",
25
+ "dev": "tsc --watch",
26
+ "lint": "eslint src --ext .ts",
27
+ "lint:fix": "eslint src --ext .ts --fix",
28
+ "format": "prettier --write src/**/*.ts",
29
+ "test": "jest",
30
+ "prepublishOnly": "npm run build",
31
+ "publish:patch": "node scripts/publish.js patch",
32
+ "publish:minor": "node scripts/publish.js minor",
33
+ "publish:major": "node scripts/publish.js major",
34
+ "version:show": "node scripts/version.js show",
35
+ "version:bump": "node scripts/version.js bump"
36
+ },
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "n8n": {
41
+ "n8nNodesApiVersion": 1,
42
+ "credentials": [
43
+ "dist/credentials/zalo-api.credentials.js"
44
+ ],
45
+ "nodes": [
46
+ "dist/nodes/ZaloTrigger/zalo-trigger.node.js",
47
+ "dist/nodes/ZaloSend/zalo-send.node.js",
48
+ "dist/nodes/ZaloManage/zalo-manage.node.js"
49
+ ]
50
+ },
51
+ "dependencies": {
52
+ "ioredis": "^5.4.1",
53
+ "uuid": "^9.0.1",
54
+ "zca-js": "^2.0.4"
55
+ },
56
+ "peerDependencies": {
57
+ "n8n-workflow": ">=1.0.0"
58
+ },
59
+ "devDependencies": {
60
+ "@types/jest": "^29.5.11",
61
+ "@types/node": "^20.10.0",
62
+ "@types/uuid": "^9.0.7",
63
+ "@typescript-eslint/eslint-plugin": "^6.15.0",
64
+ "@typescript-eslint/parser": "^6.15.0",
65
+ "eslint": "^8.56.0",
66
+ "jest": "^29.7.0",
67
+ "n8n-workflow": "^1.22.0",
68
+ "prettier": "^3.1.1",
69
+ "ts-jest": "^29.1.1",
70
+ "typescript": "^5.3.3"
71
+ },
72
+ "engines": {
73
+ "node": ">=18.0.0"
74
+ }
75
+ }