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.
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/bridge/zalo-bridge.d.ts +46 -0
- package/dist/bridge/zalo-bridge.d.ts.map +1 -0
- package/dist/bridge/zalo-bridge.js +213 -0
- package/dist/bridge/zalo-bridge.js.map +1 -0
- package/dist/credentials/zalo-api.credentials.d.ts +8 -0
- package/dist/credentials/zalo-api.credentials.d.ts.map +1 -0
- package/dist/credentials/zalo-api.credentials.js +82 -0
- package/dist/credentials/zalo-api.credentials.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/auth.interface.d.ts +33 -0
- package/dist/interfaces/auth.interface.d.ts.map +1 -0
- package/dist/interfaces/auth.interface.js +3 -0
- package/dist/interfaces/auth.interface.js.map +1 -0
- package/dist/interfaces/config.interface.d.ts +37 -0
- package/dist/interfaces/config.interface.d.ts.map +1 -0
- package/dist/interfaces/config.interface.js +3 -0
- package/dist/interfaces/config.interface.js.map +1 -0
- package/dist/interfaces/index.d.ts +4 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +20 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/interfaces/zalo.interface.d.ts +74 -0
- package/dist/interfaces/zalo.interface.d.ts.map +1 -0
- package/dist/interfaces/zalo.interface.js +14 -0
- package/dist/interfaces/zalo.interface.js.map +1 -0
- package/dist/nodes/ZaloManage/zalo-manage.node.d.ts +6 -0
- package/dist/nodes/ZaloManage/zalo-manage.node.d.ts.map +1 -0
- package/dist/nodes/ZaloManage/zalo-manage.node.js +426 -0
- package/dist/nodes/ZaloManage/zalo-manage.node.js.map +1 -0
- package/dist/nodes/ZaloSend/zalo-send.node.d.ts +6 -0
- package/dist/nodes/ZaloSend/zalo-send.node.d.ts.map +1 -0
- package/dist/nodes/ZaloSend/zalo-send.node.js +538 -0
- package/dist/nodes/ZaloSend/zalo-send.node.js.map +1 -0
- package/dist/nodes/ZaloTrigger/zalo-trigger.node.d.ts +6 -0
- package/dist/nodes/ZaloTrigger/zalo-trigger.node.d.ts.map +1 -0
- package/dist/nodes/ZaloTrigger/zalo-trigger.node.js +308 -0
- package/dist/nodes/ZaloTrigger/zalo-trigger.node.js.map +1 -0
- package/dist/queues/in-memory-queue.d.ts +20 -0
- package/dist/queues/in-memory-queue.d.ts.map +1 -0
- package/dist/queues/in-memory-queue.js +68 -0
- package/dist/queues/in-memory-queue.js.map +1 -0
- package/dist/queues/index.d.ts +4 -0
- package/dist/queues/index.d.ts.map +1 -0
- package/dist/queues/index.js +8 -0
- package/dist/queues/index.js.map +1 -0
- package/dist/queues/queue.interface.d.ts +15 -0
- package/dist/queues/queue.interface.d.ts.map +1 -0
- package/dist/queues/queue.interface.js +3 -0
- package/dist/queues/queue.interface.js.map +1 -0
- package/dist/queues/redis-queue.d.ts +22 -0
- package/dist/queues/redis-queue.d.ts.map +1 -0
- package/dist/queues/redis-queue.js +65 -0
- package/dist/queues/redis-queue.js.map +1 -0
- package/dist/services/error-handler.service.d.ts +67 -0
- package/dist/services/error-handler.service.d.ts.map +1 -0
- package/dist/services/error-handler.service.js +201 -0
- package/dist/services/error-handler.service.js.map +1 -0
- package/dist/services/index.d.ts +4 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +13 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/rate-limiter.service.d.ts +68 -0
- package/dist/services/rate-limiter.service.d.ts.map +1 -0
- package/dist/services/rate-limiter.service.js +149 -0
- package/dist/services/rate-limiter.service.js.map +1 -0
- package/dist/services/zalo-connection-manager.service.d.ts +85 -0
- package/dist/services/zalo-connection-manager.service.d.ts.map +1 -0
- package/dist/services/zalo-connection-manager.service.js +243 -0
- package/dist/services/zalo-connection-manager.service.js.map +1 -0
- package/dist/utils/auth-helpers.d.ts +25 -0
- package/dist/utils/auth-helpers.d.ts.map +1 -0
- package/dist/utils/auth-helpers.js +66 -0
- package/dist/utils/auth-helpers.js.map +1 -0
- 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
|
+
}
|