n8n-nodes-chat2crm 0.1.18 → 0.1.20

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/README.md CHANGED
@@ -1,34 +1,34 @@
1
- # Структура проекта
2
-
3
- ## Основные директории
4
-
5
- - **nodes/**
6
- - `Chat2CrmSend/` — Нода для отправки сообщений
7
- - `Chat2CrmSend.node.ts` — Основной файл ноды
8
- - `chat2crm.svg` — Иконка ноды
9
- - `Chat2CrmTrigger/` — Триггерная нода для прослушивания стримов
10
- - `Chat2CrmTrigger.node.ts` — Основной файл ноды
11
- - `chat2crm.svg` — Иконка ноды
12
- - `Infra/` — Инфраструктурные модули
13
- - `RedisConnection.ts` — Подключение к Redis
14
- - `StreamConfig.ts` — Конфигурация потоков Redis
15
-
16
- - **credentials/**
17
- - `Chat2CrmRedisApi.credentials.ts` — Credentials для Redis API
18
-
19
-
20
- ## Конфигурационные файлы
21
-
22
- - `index.js` — Точка входа модуля (экспорт узлов и credentials)
23
- - `package.json`
24
- - `package-lock.json`
25
- - `tsconfig.json`
26
- - `gulpfile.js`
27
- - `.eslintrc.js`
28
- - `.gitignore`
29
- - `.n8nignore`
30
-
31
- ## Документация
32
-
33
- - `README.md` — Документация проекта
1
+ # Структура проекта
2
+
3
+ ## Основные директории
4
+
5
+ - **nodes/**
6
+ - `Chat2CrmSend/` — Нода для отправки сообщений
7
+ - `Chat2CrmSend.node.ts` — Основной файл ноды
8
+ - `chat2crm.svg` — Иконка ноды
9
+ - `Chat2CrmTrigger/` — Триггерная нода для прослушивания стримов
10
+ - `Chat2CrmTrigger.node.ts` — Основной файл ноды
11
+ - `chat2crm.svg` — Иконка ноды
12
+ - `Infra/` — Инфраструктурные модули
13
+ - `RedisConnection.ts` — Подключение к Redis
14
+ - `StreamConfig.ts` — Конфигурация потоков Redis
15
+
16
+ - **credentials/**
17
+ - `Chat2CrmRedisApi.credentials.ts` — Credentials для Redis API
18
+
19
+
20
+ ## Конфигурационные файлы
21
+
22
+ - `index.js` — Точка входа модуля (экспорт узлов и credentials)
23
+ - `package.json`
24
+ - `package-lock.json`
25
+ - `tsconfig.json`
26
+ - `gulpfile.js`
27
+ - `.eslintrc.js`
28
+ - `.gitignore`
29
+ - `.n8nignore`
30
+
31
+ ## Документация
32
+
33
+ - `README.md` — Документация проекта
34
34
  - `QUICKSTART.md` — Руководство по быстрому старту
@@ -73,6 +73,7 @@ class Chat2CrmTrigger {
73
73
  const block = this.getNodeParameter('block', 1000);
74
74
  const count = this.getNodeParameter('count', 10);
75
75
  const pollIntervalSeconds = this.getNodeParameter('pollInterval', 0.5);
76
+ const isDebug = String(process.env.CHAT2CRM_TRIGGER_DEBUG ?? '').toLowerCase() === 'true';
76
77
  // Валидация входных данных
77
78
  if (!selectedStreams || selectedStreams.length === 0) {
78
79
  throw new n8n_workflow_1.ApplicationError('Please select at least one stream to monitor', { level: 'warning' });
@@ -100,95 +101,18 @@ class Chat2CrmTrigger {
100
101
  // ВАЖНО: Каждое соединение уже настроено на свою базу данных через параметр db
101
102
  const redis = await RedisConnection_1.createRedisConnection.call(this, credentials, db);
102
103
  redisConnections.set(db, redis);
103
- // ДИАГНОСТИКА: Сразу после создания соединения проверяем stream'ы
104
- try {
105
- const testKeys = await redis.keys('*');
106
- console.log(`[Chat2Crm Trigger] Keys in DB ${db} immediately after connection:`, testKeys);
107
- // Проверяем конкретно N8N_INCOMING_MESSAGE
108
- if (streamsByDb.get(db)?.includes('N8N_INCOMING_MESSAGE')) {
109
- try {
110
- const testInfo = await redis.xinfo('STREAM', 'N8N_INCOMING_MESSAGE');
111
- console.log(`[Chat2Crm Trigger] N8N_INCOMING_MESSAGE found immediately after connection!`, testInfo);
112
- }
113
- catch (e) {
114
- console.error(`[Chat2Crm Trigger] N8N_INCOMING_MESSAGE NOT found immediately after connection:`, e.message);
115
- }
116
- }
117
- }
118
- catch (error) {
119
- console.error(`[Chat2Crm Trigger] Error checking keys in DB ${db}:`, error.message);
120
- }
121
104
  }
122
105
  // Храним последние прочитанные ID для каждого stream
123
106
  const lastReadIds = new Map();
124
- // ИСПРАВЛЕНИЕ: Добавляем флаг для предотвращения параллельных вызовов
125
- let isReading = false;
126
- // ИСПРАВЛЕНИЕ: Добавляем Set для отслеживания уже обработанных messageId
127
- const processedMessageIds = new Set();
128
107
  // Собираем информацию о найденных streams для вывода
129
108
  const foundStreams = [];
130
109
  // Инициализируем lastReadIds для каждого stream и собираем информацию
131
110
  for (const [db, dbStreams] of streamsByDb.entries()) {
132
111
  const redis = redisConnections.get(db);
133
- // ИСПРАВЛЕНИЕ: Явно выбираем базу данных перед проверкой stream'ов
134
- try {
135
- const selectResult = await redis.select(db);
136
- console.log(`[Chat2Crm Trigger] SELECT ${db} result:`, selectResult);
137
- // ДИАГНОСТИКА: Проверяем текущую базу данных через CLIENT INFO или другой способ
138
- // Попробуем напрямую проверить stream после SELECT
139
- for (const stream of dbStreams) {
140
- try {
141
- console.log(`[Chat2Crm Trigger] Direct XINFO check for "${stream}" immediately after SELECT ${db}`);
142
- const directInfo = await redis.xinfo('STREAM', stream);
143
- console.log(`[Chat2Crm Trigger] Direct XINFO SUCCESS for "${stream}":`, directInfo);
144
- }
145
- catch (directError) {
146
- console.error(`[Chat2Crm Trigger] Direct XINFO FAILED for "${stream}":`, directError.message);
147
- }
148
- }
149
- // ДИАГНОСТИКА: Проверяем все stream'ы через SCAN
150
- const streamKeys = [];
151
- let cursor = '0';
152
- do {
153
- const [nextCursor, keys] = await redis.scan(cursor, 'MATCH', '*', 'COUNT', 100);
154
- cursor = nextCursor;
155
- for (const key of keys) {
156
- const keyType = await redis.type(key);
157
- if (keyType === 'stream') {
158
- streamKeys.push(key);
159
- }
160
- }
161
- } while (cursor !== '0');
162
- console.log(`[Chat2Crm Trigger] Found ${streamKeys.length} streams in DB ${db}:`, streamKeys);
163
- console.log(`[Chat2Crm Trigger] Looking for:`, dbStreams);
164
- // ДИАГНОСТИКА: Проверяем конкретно N8N_INCOMING_MESSAGE через разные методы
165
- if (dbStreams.includes('N8N_INCOMING_MESSAGE')) {
166
- console.log(`[Chat2Crm Trigger] Special check for N8N_INCOMING_MESSAGE in DB ${db}`);
167
- try {
168
- const exists = await redis.exists('N8N_INCOMING_MESSAGE');
169
- console.log(`[Chat2Crm Trigger] EXISTS check for N8N_INCOMING_MESSAGE:`, exists);
170
- }
171
- catch (e) {
172
- console.error(`[Chat2Crm Trigger] EXISTS check failed:`, e.message);
173
- }
174
- try {
175
- const type = await redis.type('N8N_INCOMING_MESSAGE');
176
- console.log(`[Chat2Crm Trigger] TYPE check for N8N_INCOMING_MESSAGE:`, type);
177
- }
178
- catch (e) {
179
- console.error(`[Chat2Crm Trigger] TYPE check failed:`, e.message);
180
- }
181
- }
182
- }
183
- catch (error) {
184
- console.error(`[Chat2Crm Trigger] Failed to select DB ${db}:`, error.message);
185
- }
186
112
  for (const stream of dbStreams) {
187
113
  try {
188
- console.log(`[Chat2Crm Trigger] Checking stream "${stream}" in DB ${db}`);
189
114
  // Пытаемся получить информацию о stream
190
115
  const streamInfo = await redis.xinfo('STREAM', stream);
191
- console.log(`[Chat2Crm Trigger] Stream "${stream}" found! Info:`, streamInfo);
192
116
  if (streamInfo && Array.isArray(streamInfo)) {
193
117
  // Ищем 'last-entry' в информации о stream
194
118
  const lastEntryIndex = streamInfo.indexOf('last-entry');
@@ -200,28 +124,30 @@ class Chat2CrmTrigger {
200
124
  foundStreams.push({ db, stream, exists: true, lastId });
201
125
  }
202
126
  else {
203
- lastReadIds.set(stream, '$');
127
+ // Stream exists but empty -> start from 0-0; XREAD returns entries with id > lastId
128
+ lastReadIds.set(stream, '0-0');
204
129
  foundStreams.push({ db, stream, exists: true });
205
130
  }
206
131
  }
207
132
  else {
208
- lastReadIds.set(stream, '$');
133
+ lastReadIds.set(stream, '0-0');
209
134
  foundStreams.push({ db, stream, exists: true });
210
135
  }
211
136
  }
212
137
  else {
213
- lastReadIds.set(stream, '$');
138
+ lastReadIds.set(stream, '0-0');
214
139
  foundStreams.push({ db, stream, exists: true });
215
140
  }
216
141
  }
217
142
  catch (error) {
218
- // Если stream не существует или ошибка, используем '$' для новых сообщений
143
+ // Если stream не существует, считаем что он пустой и будем читать новые записи с момента появления
144
+ // Важно: используем '0-0' (а не '$'), чтобы не было "проскальзываний" между poll-итерациями
219
145
  if (error.message?.includes('no such key') || error.message?.includes('not found')) {
220
- lastReadIds.set(stream, '$');
146
+ lastReadIds.set(stream, '0-0');
221
147
  foundStreams.push({ db, stream, exists: false });
222
148
  }
223
149
  else {
224
- lastReadIds.set(stream, '$');
150
+ lastReadIds.set(stream, '0-0');
225
151
  foundStreams.push({ db, stream, exists: false });
226
152
  }
227
153
  }
@@ -246,121 +172,125 @@ class Chat2CrmTrigger {
246
172
  let isClosing = false;
247
173
  // Функция для чтения сообщений
248
174
  const readMessages = async () => {
249
- // ИСПРАВЛЕНИЕ: Предотвращаем параллельные вызовы
250
- if (isReading || isClosing) {
175
+ // Проверяем, не закрывается ли триггер
176
+ if (isClosing) {
251
177
  return;
252
178
  }
253
- isReading = true;
254
- try {
255
- for (const [db, dbStreams] of streamsByDb.entries()) {
179
+ for (const [db, dbStreams] of streamsByDb.entries()) {
180
+ // Проверяем снова перед каждой итерацией
181
+ if (isClosing) {
182
+ break;
183
+ }
184
+ const redis = redisConnections.get(db);
185
+ // Читаем каждый stream отдельно через XREAD
186
+ // XREAD читает напрямую из stream, независимо от consumer groups
187
+ for (const stream of dbStreams) {
256
188
  if (isClosing) {
257
189
  break;
258
190
  }
259
- const redis = redisConnections.get(db);
260
- for (const stream of dbStreams) {
191
+ try {
192
+ const lastId = lastReadIds.get(stream) || '0-0';
193
+ // Используем более короткий block time для возможности быстрого закрытия
194
+ const blockTime = isClosing ? 0 : Math.min(block, MAX_BLOCK_TIME_FOR_RESPONSIVENESS_MS);
195
+ // Используем XREAD чтобы читать все сообщения напрямую из stream
196
+ // Это позволяет читать сообщения даже если они уже обработаны другими consumer'ами
197
+ if (isDebug) {
198
+ console.log(`[Chat2Crm Trigger] XREAD stream="${stream}" db=${db} lastId="${lastId}" block=${blockTime} count=${count}`);
199
+ }
200
+ const messages = await redis.xread('COUNT', count, 'BLOCK', blockTime, 'STREAMS', stream, lastId);
201
+ // Проверяем снова после блокирующей операции
261
202
  if (isClosing) {
262
- break;
203
+ return;
263
204
  }
264
- try {
265
- const lastId = lastReadIds.get(stream) || '$';
266
- const blockTime = isClosing ? 0 : Math.min(block, MAX_BLOCK_TIME_FOR_RESPONSIVENESS_MS);
267
- const messages = await redis.xread('COUNT', count, 'BLOCK', blockTime, 'STREAMS', stream, lastId);
268
- if (isClosing) {
269
- return;
270
- }
271
- if (messages && Array.isArray(messages) && messages.length > 0) {
272
- const streamData = messages[0];
273
- const [streamName, streamMessages] = streamData;
274
- if (Array.isArray(streamMessages) && streamMessages.length > 0) {
275
- // ИСПРАВЛЕНИЕ: Фильтруем уже обработанные сообщения
276
- const newMessages = streamMessages.filter(([messageId]) => {
277
- const messageKey = `${streamName}:${messageId}`;
278
- if (processedMessageIds.has(messageKey)) {
279
- return false; // Пропускаем уже обработанное сообщение
280
- }
281
- processedMessageIds.add(messageKey);
282
- return true;
283
- });
284
- // ИСПРАВЛЕНИЕ: Обновляем lastReadId сразу после чтения, ДО обработки
285
- const lastMessageId = streamMessages[streamMessages.length - 1][0];
286
- lastReadIds.set(streamName, lastMessageId);
287
- // ИСПРАВЛЕНИЕ: Обрабатываем только новые сообщения
288
- for (const [messageId, fields] of newMessages) {
289
- if (isClosing) {
290
- break;
291
- }
292
- const messageData = {};
293
- for (let j = 0; j < fields.length; j += 2) {
294
- messageData[fields[j]] = fields[j + 1];
205
+ if (messages && Array.isArray(messages) && messages.length > 0) {
206
+ // XREAD возвращает массив с одним элементом [streamName, messages]
207
+ const streamData = messages[0];
208
+ const [streamName, streamMessages] = streamData;
209
+ if (Array.isArray(streamMessages) && streamMessages.length > 0) {
210
+ // Обновляем lastReadId на последний прочитанный ID
211
+ const lastMessageId = streamMessages[streamMessages.length - 1][0];
212
+ lastReadIds.set(streamName, lastMessageId);
213
+ for (const [messageId, fields] of streamMessages) {
214
+ if (isClosing) {
215
+ break;
216
+ }
217
+ const messageData = {};
218
+ // Parse fields
219
+ for (let j = 0; j < fields.length; j += 2) {
220
+ messageData[fields[j]] = fields[j + 1];
221
+ }
222
+ // Parse commands if it's a string
223
+ if (messageData.commands && typeof messageData.commands === 'string') {
224
+ try {
225
+ messageData.commands = JSON.parse(messageData.commands);
295
226
  }
296
- if (messageData.commands && typeof messageData.commands === 'string') {
297
- try {
298
- messageData.commands = JSON.parse(messageData.commands);
299
- }
300
- catch (e) {
301
- // Ignore parse errors
302
- }
227
+ catch (e) {
228
+ // Ignore parse errors
303
229
  }
304
- const executionData = {
305
- json: {
306
- messageId,
307
- stream: streamName,
308
- data: messageData,
309
- commandList: messageData,
310
- },
311
- };
312
- this.emit([[executionData]]);
313
- }
314
- // ИСПРАВЛЕНИЕ: Очищаем старые записи из Set для предотвращения утечки памяти
315
- // Оставляем только последние 1000 обработанных ID
316
- if (processedMessageIds.size > 1000) {
317
- const entries = Array.from(processedMessageIds);
318
- const toRemove = entries.slice(0, entries.length - 1000);
319
- toRemove.forEach(id => processedMessageIds.delete(id));
320
230
  }
231
+ // Триггерим workflow с данными сообщения
232
+ const executionData = {
233
+ json: {
234
+ messageId,
235
+ stream: streamName,
236
+ data: messageData,
237
+ commandList: messageData,
238
+ },
239
+ };
240
+ this.emit([[executionData]]);
321
241
  }
322
242
  }
323
243
  }
324
- catch (error) {
325
- if (isClosing && (error.message?.includes('Connection is closed') || error.message?.includes('disconnect'))) {
326
- return;
327
- }
328
- if (error.message?.includes('Invalid stream ID') || error.message?.includes('no such key')) {
329
- continue;
330
- }
331
- console.error(`[Chat2Crm Trigger] Error reading stream ${stream} from Redis DB ${db}:`, error);
244
+ }
245
+ catch (error) {
246
+ // Игнорируем ошибки при закрытии
247
+ if (isClosing && (error.message?.includes('Connection is closed') || error.message?.includes('disconnect'))) {
248
+ return;
249
+ }
250
+ // Игнорируем ошибки для несуществующих streams
251
+ if (error.message?.includes('Invalid stream ID') || error.message?.includes('no such key')) {
252
+ continue;
332
253
  }
254
+ // Логируем только критические ошибки
255
+ console.error(`[Chat2Crm Trigger] Error reading stream ${stream} from Redis DB ${db}:`, error);
333
256
  }
334
257
  }
335
258
  }
336
- finally {
337
- // ИСПРАВЛЕНИЕ: Всегда сбрасываем флаг, даже при ошибке
338
- isReading = false;
339
- }
340
259
  };
341
- // Начинаем polling с более коротким интервалом
342
- let interval = null;
343
- const startPolling = () => {
344
- interval = setInterval(async () => {
345
- if (!isClosing) {
260
+ // Запускаем один последовательный polling loop (без setInterval), чтобы не было наложения вызовов
261
+ let pollingPromise = null;
262
+ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
263
+ const runPollingLoop = async () => {
264
+ try {
265
+ while (!isClosing) {
346
266
  await readMessages();
267
+ // Если block=0, добавляем небольшой интервал чтобы не прожигать CPU
268
+ if (!isClosing) {
269
+ await sleep(pollInterval);
270
+ }
271
+ }
272
+ }
273
+ catch (error) {
274
+ // Важно: не даём polling loop'у "повесить" деактивацию воркфлоу
275
+ if (!isClosing) {
276
+ console.error('[Chat2Crm Trigger] Polling loop crashed:', error);
347
277
  }
348
- }, pollInterval);
278
+ }
279
+ };
280
+ pollingPromise = runPollingLoop();
281
+ const withTimeout = async (promise, timeoutMs) => {
282
+ return await Promise.race([
283
+ promise,
284
+ new Promise((_, reject) => setTimeout(() => reject(new Error('close timeout')), timeoutMs)),
285
+ ]);
349
286
  };
350
- startPolling();
351
- // Первый запуск сразу
352
- await readMessages();
353
287
  // Возвращаем объект с функцией closeFunction для cleanup
354
288
  return {
355
289
  closeFunction: async () => {
356
290
  console.log(`[Chat2Crm Trigger] Closing trigger, cleaning up resources...`);
357
291
  isClosing = true; // Устанавливаем флаг закрытия
358
292
  try {
359
- if (interval) {
360
- clearInterval(interval);
361
- interval = null;
362
- }
363
- // Используем disconnect() вместо quit() для более быстрого закрытия
293
+ // ВАЖНО: СНАЧАЛА рвём соединения, чтобы прервать возможный зависший XREAD (особенно через SSH)
364
294
  for (const [db, redis] of redisConnections.entries()) {
365
295
  try {
366
296
  redis.disconnect();
@@ -370,6 +300,15 @@ class Chat2CrmTrigger {
370
300
  }
371
301
  }
372
302
  redisConnections.clear();
303
+ // Не даём unpublish/deactivate висеть бесконечно: ждём loop ограниченное время
304
+ if (pollingPromise) {
305
+ try {
306
+ await withTimeout(pollingPromise.catch(() => undefined), 1000);
307
+ }
308
+ catch {
309
+ // Игнорируем таймаут, главное — быстро закрыть триггер
310
+ }
311
+ }
373
312
  console.log(`[Chat2Crm Trigger] Cleanup completed`);
374
313
  }
375
314
  catch (error) {
@@ -80,12 +80,6 @@ exports.STREAM_DEFINITIONS = [
80
80
  description: 'Outgoing messages from N8N (DB 1)',
81
81
  db: 1,
82
82
  },
83
- {
84
- name: 'N8N Chat Control',
85
- value: 'N8N_CHAT_CONTROL',
86
- description: 'Chat control messages for N8N (DB 1)',
87
- db: 1,
88
- },
89
83
  ];
90
84
  /**
91
85
  * Маппинг stream names к номерам баз данных
@@ -98,7 +92,6 @@ exports.STREAM_DB_MAP = {
98
92
  crm_outgoing_status: 1,
99
93
  N8N_INCOMING_MESSAGE: 1,
100
94
  N8N_OUTGOING_MESSAGE: 1,
101
- N8N_CHAT_CONTROL: 1,
102
95
  // Поддержка старого формата (строчными) для обратной совместимости
103
96
  n8n_incoming_message: 1,
104
97
  n8n_outgoing_message: 1,
package/index.js CHANGED
@@ -1,69 +1,3 @@
1
- // ========================================
2
- // PROXY CONFIGURATION - ЛОГИРОВАНИЕ ПРОКСИ
3
- // ========================================
4
- const proxyVars = {
5
- 'all_proxy': process.env.all_proxy,
6
- 'ALL_PROXY': process.env.ALL_PROXY,
7
- 'http_proxy': process.env.http_proxy,
8
- 'HTTP_PROXY': process.env.HTTP_PROXY,
9
- 'https_proxy': process.env.https_proxy,
10
- 'HTTPS_PROXY': process.env.HTTPS_PROXY,
11
- 'no_proxy': process.env.no_proxy,
12
- 'NO_PROXY': process.env.NO_PROXY,
13
- };
14
-
15
- // Находим активный прокси (lowercase имеет приоритет)
16
- const activeProxy = process.env.all_proxy || process.env.ALL_PROXY ||
17
- process.env.http_proxy || process.env.HTTP_PROXY ||
18
- process.env.https_proxy || process.env.HTTPS_PROXY;
19
-
20
- // Выводим информацию о прокси БОЛЬШИМИ БУКВАМИ, чтобы было видно
21
- console.log('\n');
22
- console.log('╔════════════════════════════════════════════════════════════════╗');
23
- console.log('║ PROXY CONFIGURATION ║');
24
- console.log('╚════════════════════════════════════════════════════════════════╝');
25
- console.log('');
26
-
27
- if (activeProxy) {
28
- // Маскируем пароль в логах
29
- const maskedProxy = activeProxy.replace(/:\/\/[^:]+:[^@]+@/, '://***:***@');
30
-
31
- console.log('✅ PROXY IS CONFIGURED AND ACTIVE');
32
- console.log('');
33
- console.log('Active Proxy URL:', maskedProxy);
34
- console.log('NO_PROXY:', process.env.no_proxy || process.env.NO_PROXY || 'not set');
35
- console.log('');
36
- console.log('All proxy environment variables:');
37
- Object.entries(proxyVars).forEach(([key, value]) => {
38
- if (value) {
39
- const masked = key.toLowerCase().includes('proxy') && !key.toLowerCase().includes('no')
40
- ? value.replace(/:\/\/[^:]+:[^@]+@/, '://***:***@')
41
- : value;
42
- console.log(` ${key.padEnd(15)} = ${masked}`);
43
- }
44
- });
45
- console.log('');
46
- console.log('⚠️ All HTTP/HTTPS requests from n8n nodes will use this proxy');
47
- console.log('⚠️ Redis connections (TCP) do NOT use HTTP proxy');
48
- } else {
49
- console.log('❌ NO PROXY CONFIGURED');
50
- console.log('');
51
- console.log('Available proxy environment variables (all empty):');
52
- Object.keys(proxyVars).forEach(key => {
53
- console.log(` ${key.padEnd(15)} = ${proxyVars[key] || '(not set)'}`);
54
- });
55
- console.log('');
56
- console.log('To enable proxy, set in .env file:');
57
- console.log(' ALL_PROXY=http://user:pass@host:port');
58
- console.log(' all_proxy=http://user:pass@host:port');
59
- }
60
-
61
- console.log('');
62
- console.log('╔════════════════════════════════════════════════════════════════╗');
63
- console.log('║ END OF PROXY CONFIGURATION ║');
64
- console.log('╚════════════════════════════════════════════════════════════════╝');
65
- console.log('\n');
66
-
67
1
  module.exports = {
68
2
  nodes: [
69
3
  require('./dist/nodes/Chat2CrmTrigger/Chat2CrmTrigger.node.js'),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-chat2crm",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "n8n node for Chat2Crm Redis integration",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
@@ -11,7 +11,7 @@
11
11
  "main": "index.js",
12
12
  "scripts": {
13
13
  "build": "rm -rf dist && tsc && gulp build:icons",
14
- "dev": "npm run build && node -r dotenv/config -r ./proxy-logger.js node_modules/.bin/n8n",
14
+ "dev": "npm run build && N8N_LOG_LEVEL=debug npx n8n",
15
15
  "dev:watch": "tsc --watch",
16
16
  "format": "prettier nodes credentials --write",
17
17
  "lint": "eslint \"nodes/**/*.ts\" \"credentials/**/*.ts\" \"package.json\"",