@raevon/n8n-nodes-whatsapp 1.0.10 → 1.0.12

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.
@@ -58,6 +58,7 @@ export declare function getConnectionStatus(): {
58
58
  queueSize: number;
59
59
  sentToday: number;
60
60
  dailyLimit: number;
61
+ lastError: string | null;
61
62
  };
62
63
  export declare function parseIncomingMessage(msg: any): Record<string, any> | null;
63
64
  export {};
@@ -88,6 +88,8 @@ let reconnectTimer = null;
88
88
  let qrResolve = null;
89
89
  let latestQr = null;
90
90
  let generation = 0; // #10: Generation counter — prevents stale handlers on reconnect
91
+ let credsSavedPromise = null; // Track credential save completion
92
+ let lastDisconnectError = null; // Track last disconnect reason for output
91
93
  function todayStartIso() {
92
94
  return new Date().toISOString().slice(0, 10) + 'T00:00:00.000Z';
93
95
  }
@@ -161,12 +163,13 @@ async function initSocket(cfg, authPath) {
161
163
  sock.ev.on('creds.update', () => {
162
164
  if (gen !== generation)
163
165
  return; // #10: Ignore stale connection events
164
- saveCreds().catch((err) => {
166
+ // Track credential save completion — ensures session is persisted before execution ends
167
+ credsSavedPromise = saveCreds().catch((err) => {
165
168
  console.error('[WhatsApp] Failed to save credentials:', err.message);
166
169
  });
167
170
  });
168
171
  sock.ev.on('connection.update', async (update) => {
169
- var _a, _b;
172
+ var _a, _b, _c;
170
173
  if (gen !== generation)
171
174
  return; // #10: Ignore stale connection events
172
175
  const { connection, lastDisconnect, qr } = update;
@@ -184,22 +187,27 @@ async function initSocket(cfg, authPath) {
184
187
  socketStatus = 'connected';
185
188
  reconnectAttempts = 0;
186
189
  latestQr = null;
187
- console.log('[WhatsApp] Connected successfully');
190
+ lastDisconnectError = null;
188
191
  return;
189
192
  }
190
193
  if (connection === 'close') {
191
194
  const code = (_b = (_a = lastDisconnect === null || lastDisconnect === void 0 ? void 0 : lastDisconnect.error) === null || _a === void 0 ? void 0 : _a.output) === null || _b === void 0 ? void 0 : _b.statusCode;
195
+ const errorMsg = ((_c = lastDisconnect === null || lastDisconnect === void 0 ? void 0 : lastDisconnect.error) === null || _c === void 0 ? void 0 : _c.message) || 'Unknown error';
192
196
  const reason = baileys_1.DisconnectReason[code] || 'Unknown';
193
- console.log(`[WhatsApp] Connection closed: ${reason} (code: ${code})`);
197
+ // Store error for output in nodes
198
+ lastDisconnectError = `Code: ${code} (${reason}), Error: ${errorMsg}`;
194
199
  if (code === baileys_1.DisconnectReason.loggedOut) {
195
200
  socketStatus = 'logged_out';
196
201
  socketInstance = null;
197
- ++generation; // #10: Invalidate all handlers from this session
202
+ ++generation;
198
203
  }
199
204
  else {
200
205
  socketStatus = 'disconnected';
201
206
  socketInstance = null;
202
- scheduleReconnect(cfg);
207
+ // Don't auto-reconnect if we're in a loop — let the node handle it
208
+ if (reconnectAttempts < 3) {
209
+ scheduleReconnect(cfg);
210
+ }
203
211
  }
204
212
  }
205
213
  });
@@ -241,27 +249,26 @@ async function ensureConnected(cfg) {
241
249
  // Check if session exists on disk
242
250
  const resolvedPath = expandHome(cfg.sessionPath);
243
251
  const hasSession = node_fs_1.default.existsSync(resolvedPath) && node_fs_1.default.readdirSync(resolvedPath).length > 0;
244
- console.log(`[WhatsApp] Session path: ${resolvedPath}, exists: ${hasSession}`);
245
252
  if (!hasSession) {
246
253
  throw new n8n_workflow_1.NodeApiError({}, {
247
254
  message: 'No WhatsApp session found. Run the WhatsApp Connect node first to scan QR code.',
248
255
  });
249
256
  }
250
- // Check if current socket is actually alive
251
- console.log(`[WhatsApp] Current status: ${socketStatus}, socket exists: ${!!socketInstance}`);
257
+ // Check if current socket is alive — reuse if possible
252
258
  if (socketInstance && socketStatus === 'connected') {
253
259
  try {
254
- if (socketInstance.user) {
255
- console.log('[WhatsApp] Reusing existing connection');
256
- return socketInstance;
257
- }
260
+ // Test if socket is actually responding
261
+ await socketInstance.query({ tag: 'iq', attrs: { id: 'ping', to: 's.whatsapp.net', type: 'get', xmlns: 'w:p' } });
262
+ return socketInstance;
258
263
  }
259
264
  catch {
260
- console.log('[WhatsApp] Existing socket is dead, reconnecting...');
265
+ // Socket is dead, create new one
266
+ socketInstance = null;
267
+ socketStatus = 'stopped';
261
268
  }
262
269
  }
263
- // Session exists connect using saved credentials
264
- console.log('[WhatsApp] Connecting from saved session...');
270
+ // Create fresh connection from saved session
271
+ console.log('[WhatsApp] Creating fresh connection from saved session...');
265
272
  const sock = await initSocket(antiBanCfg, cfg.sessionPath);
266
273
  // Wait for connection to open (up to 20s)
267
274
  const connected = await new Promise((resolve) => {
@@ -282,6 +289,11 @@ async function ensureConnected(cfg) {
282
289
  message: `WhatsApp connection failed (status: ${socketStatus}). Try running Connect node again.`,
283
290
  });
284
291
  }
292
+ // Wait for credentials to be saved
293
+ if (credsSavedPromise) {
294
+ await credsSavedPromise;
295
+ credsSavedPromise = null;
296
+ }
285
297
  return sock;
286
298
  }
287
299
  // Non-blocking version for Connect node — starts socket, returns QR URL if needed, doesn't wait
@@ -319,6 +331,11 @@ async function connectOrGetQr(cfg) {
319
331
  }, 500);
320
332
  setTimeout(() => { clearInterval(check); resolve(); }, 15000);
321
333
  });
334
+ // Wait for credentials to be fully saved to disk before returning
335
+ if (credsSavedPromise) {
336
+ await credsSavedPromise;
337
+ credsSavedPromise = null;
338
+ }
322
339
  if (socketStatus === 'connected') {
323
340
  return { connected: true, message: 'Connected successfully' };
324
341
  }
@@ -465,6 +482,7 @@ function getConnectionStatus() {
465
482
  queueSize: queue ? queue.size + queue.pending : 0,
466
483
  sentToday: sentTodayCount,
467
484
  dailyLimit: (_a = socketConfig === null || socketConfig === void 0 ? void 0 : socketConfig.dailySendLimit) !== null && _a !== void 0 ? _a : 0,
485
+ lastError: lastDisconnectError,
468
486
  };
469
487
  }
470
488
  function parseIncomingMessage(msg) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raevon/n8n-nodes-whatsapp",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "description": "n8n community node for WhatsApp — send and receive messages with anti-ban protection via the Baileys library",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",