n8n-nodes-sotoros-gotenberg 1.0.4 → 1.0.6

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.
@@ -77,7 +77,8 @@ class Gotenberg {
77
77
  name: 'listPropertyName',
78
78
  type: 'string',
79
79
  default: 'items',
80
- description: 'Name of the JSON property that contains the array/list of items from the aggregation node (e.g., "items", "data")',
80
+ description: 'Name of the JSON property that contains the array/list of items from the aggregation node (e.g., "items", "data"). ' +
81
+ 'Leave empty if the aggregated item JSON itself is an array.',
81
82
  },
82
83
  {
83
84
  displayName: 'Binary Property',
@@ -199,17 +200,90 @@ class Gotenberg {
199
200
  };
200
201
  return mimeToExt[mimeType] || 'bin';
201
202
  };
203
+ // Вспомогательная функция для форматирования структуры данных с заменой длинных base64 строк
204
+ const formatDataStructure = (data, maxDepth = 5, currentDepth = 0) => {
205
+ if (currentDepth >= maxDepth) {
206
+ return '[max depth reached]';
207
+ }
208
+ // Если это null или undefined
209
+ if (data === null || data === undefined) {
210
+ return data;
211
+ }
212
+ // Если это примитивный тип
213
+ if (typeof data !== 'object') {
214
+ // Если это строка и она похожа на base64 (длинная строка из base64 символов)
215
+ if (typeof data === 'string' && data.length > 100 && /^[A-Za-z0-9+/=]+$/.test(data)) {
216
+ return `[binary data: ${data.length} bytes]`;
217
+ }
218
+ // Если это очень длинная строка (не base64, но все равно длинная)
219
+ if (typeof data === 'string' && data.length > 200) {
220
+ return `[long string: ${data.length} chars]`;
221
+ }
222
+ return data;
223
+ }
224
+ // Если это массив
225
+ if (Array.isArray(data)) {
226
+ return data.map((item, index) => {
227
+ // Ограничиваем вывод массивов до 10 элементов
228
+ if (index >= 10) {
229
+ return `[${data.length - 10} more items...]`;
230
+ }
231
+ return formatDataStructure(item, maxDepth, currentDepth + 1);
232
+ }).slice(0, 10);
233
+ }
234
+ // Если это объект
235
+ const formatted = {};
236
+ for (const key in data) {
237
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
238
+ const value = data[key];
239
+ // Специальная обработка для binary данных
240
+ if (key === 'data' && typeof value === 'string' && value.length > 50) {
241
+ formatted[key] = `[binary data: ${value.length} bytes]`;
242
+ }
243
+ else if (key === 'binary' && typeof value === 'object' && value !== null) {
244
+ // Для binary объектов показываем структуру, но заменяем data
245
+ formatted[key] = formatDataStructure(value, maxDepth, currentDepth + 1);
246
+ }
247
+ else {
248
+ formatted[key] = formatDataStructure(value, maxDepth, currentDepth + 1);
249
+ }
250
+ }
251
+ }
252
+ return formatted;
253
+ };
202
254
  try {
203
255
  // Извлекаем список из JSON свойства агрегированного элемента
204
- const listData = aggregatedItem.json[listPropertyName];
205
- if (!listData) {
206
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Property "${listPropertyName}" not found in aggregated item. Please check the property name.`);
256
+ let listData;
257
+ // Если listPropertyName пустой или не указан, проверяем, является ли сам json массивом
258
+ if (!listPropertyName || listPropertyName.trim() === '') {
259
+ if (Array.isArray(aggregatedItem.json)) {
260
+ listData = aggregatedItem.json;
261
+ }
262
+ else {
263
+ // Показываем доступные свойства для помощи пользователю
264
+ const availableProperties = Object.keys(aggregatedItem.json || {}).join(', ');
265
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `List Property is empty, but aggregated item JSON is not an array. ` +
266
+ `Available properties: ${availableProperties || 'none'}. ` +
267
+ `Please specify the property name that contains the array of items.`);
268
+ }
207
269
  }
208
- if (!Array.isArray(listData)) {
209
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Property "${listPropertyName}" is not an array. Expected an array of items from aggregation node.`);
270
+ else {
271
+ listData = aggregatedItem.json[listPropertyName];
272
+ if (!listData) {
273
+ // Показываем доступные свойства для помощи пользователю
274
+ const availableProperties = Object.keys(aggregatedItem.json || {}).join(', ');
275
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Property "${listPropertyName}" not found in aggregated item. ` +
276
+ `Available properties: ${availableProperties || 'none'}. ` +
277
+ `Please check the property name.`);
278
+ }
279
+ if (!Array.isArray(listData)) {
280
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Property "${listPropertyName}" is not an array. ` +
281
+ `Current type: ${typeof listData}. ` +
282
+ `Expected an array of items from aggregation node.`);
283
+ }
210
284
  }
211
285
  if (listData.length === 0) {
212
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The list in property "${listPropertyName}" is empty. No items to process.`);
286
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `The list ${listPropertyName ? `in property "${listPropertyName}"` : ''} is empty. No items to process.`);
213
287
  }
214
288
  // Создаем FormData для отправки в Gotenberg - один запрос для всех элементов списка
215
289
  const formData = new form_data_1.default();
@@ -270,7 +344,63 @@ class Gotenberg {
270
344
  }
271
345
  }
272
346
  if (totalFilesCount === 0) {
273
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'No valid binary files found in any items. Please make sure binary data exists.');
347
+ // Собираем информацию о структуре элементов списка
348
+ const sampleItems = listData.slice(0, 3).map((item, index) => {
349
+ const itemInfo = {
350
+ index,
351
+ type: typeof item,
352
+ isObject: typeof item === 'object' && item !== null,
353
+ hasBinary: 'binary' in (item || {}),
354
+ hasBinaryProperty: binaryPropertyName in (item || {}),
355
+ keys: item && typeof item === 'object' ? Object.keys(item) : [],
356
+ };
357
+ // Если есть binary свойство, показываем его структуру
358
+ if (item && typeof item === 'object') {
359
+ if ('binary' in item && item.binary) {
360
+ itemInfo.binaryKeys = Object.keys(item.binary);
361
+ itemInfo.binaryStructure = formatDataStructure(item.binary);
362
+ }
363
+ if (binaryPropertyName in item) {
364
+ itemInfo[binaryPropertyName] = formatDataStructure(item[binaryPropertyName]);
365
+ }
366
+ // Показываем структуру json части (без длинных строк)
367
+ if ('json' in item) {
368
+ itemInfo.jsonKeys = Object.keys(item.json || {});
369
+ itemInfo.jsonSample = formatDataStructure(item.json);
370
+ }
371
+ else {
372
+ // Если нет json, показываем структуру самого объекта
373
+ itemInfo.objectSample = formatDataStructure(item);
374
+ }
375
+ }
376
+ return itemInfo;
377
+ });
378
+ // Форматируем структуру данных для отладки
379
+ const formattedStructure = formatDataStructure({
380
+ aggregatedItem: {
381
+ jsonKeys: Object.keys(aggregatedItem.json || {}),
382
+ binaryKeys: Object.keys(aggregatedItem.binary || {}),
383
+ jsonSample: formatDataStructure(aggregatedItem.json),
384
+ },
385
+ listDataInfo: {
386
+ length: listData.length,
387
+ propertyName: listPropertyName || '(root array)',
388
+ sampleItems,
389
+ },
390
+ configuration: {
391
+ binaryPropertyName,
392
+ listPropertyName: listPropertyName || '(root array)',
393
+ },
394
+ });
395
+ const structureInfo = JSON.stringify(formattedStructure, null, 2);
396
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `No valid binary files found in any items. Please make sure binary data exists.\n\n` +
397
+ `Input data structure:\n${structureInfo}\n\n` +
398
+ `Tips:\n` +
399
+ `- Check that binaryPropertyName "${binaryPropertyName}" matches the property name in your items\n` +
400
+ `- Verify that binary data exists in the items (check the "binary" property or the specified property)\n` +
401
+ `- Make sure binary data has a "data" field with base64 content\n` +
402
+ `- If items have a "binary" property, binary data should be in binary["${binaryPropertyName}"]\n` +
403
+ `- If items have binary data directly, it should be in item["${binaryPropertyName}"]`);
274
404
  }
275
405
  // Добавляем опции в зависимости от операции
276
406
  if (operation === 'office' || operation === 'html' || operation === 'markdown') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-sotoros-gotenberg",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "n8n custom node for Gotenberg integration with binary data support",
5
5
  "keywords": [
6
6
  "n8n-community-node",