n8n-nodes-databar 0.1.3 → 0.2.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.
@@ -20,24 +20,12 @@
20
20
  * Resources & Operations:
21
21
  * - User: Get account info
22
22
  * - Enrichment: Run, Bulk Run (with async polling)
23
- * - Waterfall: List, Get, Run
24
- *
25
- * Note: Table operations are temporarily hidden but can be re-enabled in the code
23
+ * - Table: Insert Rows, Upsert Rows
24
+ * - Waterfall: Run (with async polling)
26
25
  */
27
26
  Object.defineProperty(exports, "__esModule", { value: true });
28
27
  exports.Databar = void 0;
29
28
  const n8n_workflow_1 = require("n8n-workflow");
30
- /**
31
- * Helper function to wait for a specified duration using a polling loop
32
- * This avoids using restricted globals like setTimeout/setInterval
33
- */
34
- async function wait(ms) {
35
- const start = Date.now();
36
- while (Date.now() - start < ms) {
37
- // Yield control to allow other operations
38
- await Promise.resolve();
39
- }
40
- }
41
29
  /**
42
30
  * Helper function to poll task status until completion
43
31
  *
@@ -75,7 +63,7 @@ async function pollTaskStatus(context, taskId, pollInterval, timeout) {
75
63
  throw new n8n_workflow_1.NodeOperationError(context.getNode(), `Task ${taskId} failed: ${error}`);
76
64
  }
77
65
  // Wait before polling again
78
- await wait(pollIntervalMs);
66
+ await (0, n8n_workflow_1.sleep)(pollIntervalMs);
79
67
  }
80
68
  }
81
69
  class Databar {
@@ -91,8 +79,8 @@ class Databar {
91
79
  defaults: {
92
80
  name: 'Databar',
93
81
  },
94
- inputs: ['main'],
95
- outputs: ['main'],
82
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
83
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
96
84
  credentials: [
97
85
  {
98
86
  name: 'databarApi',
@@ -118,15 +106,14 @@ class Databar {
118
106
  name: 'Enrichment',
119
107
  value: 'enrichment',
120
108
  },
109
+ {
110
+ name: 'Table',
111
+ value: 'table',
112
+ },
121
113
  {
122
114
  name: 'Waterfall',
123
115
  value: 'waterfall',
124
116
  },
125
- // Table resource temporarily hidden - can be re-enabled later
126
- // {
127
- // name: 'Table',
128
- // value: 'table',
129
- // },
130
117
  {
131
118
  name: 'Other',
132
119
  value: 'user',
@@ -177,102 +164,29 @@ class Databar {
177
164
  description: 'Run an enrichment task',
178
165
  action: 'Run enrichment',
179
166
  },
180
- {
181
- name: 'Bulk Run',
182
- value: 'bulkRun',
183
- description: 'Run enrichment on multiple records',
184
- action: 'Bulk run enrichment',
185
- },
167
+ // Bulk Run hidden for v1 - re-add to enable:
168
+ // { name: 'Bulk Run', value: 'bulkRun', description: 'Run enrichment on multiple records', action: 'Bulk run enrichment' },
186
169
  ],
187
170
  default: 'run',
188
171
  },
189
- // Enrichment: Selection Mode
190
- {
191
- displayName: 'Enrichment Selection',
192
- name: 'enrichmentSelectionMode',
193
- type: 'options',
194
- options: [
195
- {
196
- name: 'From List',
197
- value: 'list',
198
- description: 'Select from available enrichments',
199
- },
200
- {
201
- name: 'By ID',
202
- value: 'id',
203
- description: 'Enter enrichment ID manually',
204
- },
205
- ],
206
- displayOptions: {
207
- show: {
208
- resource: ['enrichment'],
209
- operation: ['run', 'bulkRun'],
210
- },
211
- },
212
- default: 'list',
213
- description: 'How to select the enrichment',
214
- },
215
- // Enrichment: Run/BulkRun - Enrichment Selection from List
172
+ // Enrichment: Run/BulkRun - Enrichment Selection
216
173
  {
217
174
  displayName: 'Enrichment',
218
175
  name: 'enrichmentId',
219
176
  type: 'options',
220
177
  typeOptions: {
221
178
  loadOptionsMethod: 'getEnrichments',
222
- searchable: true, // Enable client-side search
179
+ searchable: true,
223
180
  },
224
181
  displayOptions: {
225
182
  show: {
226
183
  resource: ['enrichment'],
227
184
  operation: ['run', 'bulkRun'],
228
- enrichmentSelectionMode: ['list'],
229
185
  },
230
186
  },
231
187
  default: '',
232
188
  required: true,
233
- description: 'Select the enrichment to use. If this dropdown is empty, switch to "By ID" mode above.',
234
- },
235
- // Enrichment: Run/BulkRun - Enrichment ID Manual Entry
236
- {
237
- displayName: 'Enrichment ID',
238
- name: 'enrichmentId',
239
- type: 'number',
240
- displayOptions: {
241
- show: {
242
- resource: ['enrichment'],
243
- operation: ['run', 'bulkRun'],
244
- enrichmentSelectionMode: ['id'],
245
- },
246
- },
247
- default: 0,
248
- required: true,
249
- description: 'Enter the enrichment ID (e.g., 1220 for Email Verifier)',
250
- },
251
- // Enrichment: Run - Parameter Input Mode
252
- {
253
- displayName: 'Parameter Input Mode',
254
- name: 'parameterMode',
255
- type: 'options',
256
- options: [
257
- {
258
- name: 'Guided Fields',
259
- value: 'fields',
260
- description: 'Fill in parameters using individual fields',
261
- },
262
- {
263
- name: 'Raw JSON',
264
- value: 'json',
265
- description: 'Enter parameters as JSON object',
266
- },
267
- ],
268
- displayOptions: {
269
- show: {
270
- resource: ['enrichment'],
271
- operation: ['run'],
272
- },
273
- },
274
- default: 'fields',
275
- description: 'Choose how to input enrichment parameters',
189
+ description: 'Select the enrichment to use. Switch to Expression mode to pass a dynamic enrichment ID.',
276
190
  },
277
191
  // Enrichment: Run - Parameters as Resource Mapper (Guided Fields)
278
192
  {
@@ -293,54 +207,17 @@ class Databar {
293
207
  valuesLabel: 'Parameters',
294
208
  addAllFields: true,
295
209
  multiKeyMatch: false,
210
+ supportAutoMap: false,
296
211
  },
297
212
  },
298
213
  displayOptions: {
299
214
  show: {
300
215
  resource: ['enrichment'],
301
216
  operation: ['run'],
302
- parameterMode: ['fields'],
303
217
  },
304
218
  },
305
219
  description: 'Fill in the enrichment parameters',
306
220
  },
307
- // Enrichment: Run - Template Helper for JSON Mode (Hidden field that loads template)
308
- {
309
- displayName: 'Template',
310
- name: 'jsonTemplateHelper',
311
- type: 'options',
312
- typeOptions: {
313
- loadOptionsMethod: 'getEnrichmentTemplate',
314
- loadOptionsDependsOn: ['enrichmentId'],
315
- },
316
- displayOptions: {
317
- show: {
318
- resource: ['enrichment'],
319
- operation: ['run'],
320
- parameterMode: ['json'],
321
- },
322
- },
323
- default: '{}',
324
- description: 'Click to see the parameter template, then copy it into the field below',
325
- },
326
- // Enrichment: Run - Parameters as JSON (Raw JSON)
327
- {
328
- displayName: 'Parameters (JSON)',
329
- name: 'paramsJson',
330
- type: 'json',
331
- displayOptions: {
332
- show: {
333
- resource: ['enrichment'],
334
- operation: ['run'],
335
- parameterMode: ['json'],
336
- },
337
- },
338
- default: '={{ $parameter["jsonTemplateHelper"] }}',
339
- placeholder: '{"email": "test@example.com"}',
340
- hint: '✨ Auto-filled from template above! Replace <text> placeholders with your actual data.',
341
- description: 'Parameters automatically populated from template. Replace placeholders with real values.',
342
- required: true,
343
- },
344
221
  // Enrichment: Bulk Run - Parameters JSON
345
222
  {
346
223
  displayName: 'Parameters (Array of Objects)',
@@ -406,115 +283,6 @@ class Databar {
406
283
  // ====================================
407
284
  // TABLE OPERATIONS
408
285
  // ====================================
409
- // Table operations temporarily hidden - can be re-enabled later
410
- // {
411
- // displayName: 'Operation',
412
- // name: 'operation',
413
- // type: 'options',
414
- // noDataExpression: true,
415
- // displayOptions: {
416
- // show: {
417
- // resource: ['table'],
418
- // },
419
- // },
420
- // options: [
421
- // {
422
- // name: 'Create',
423
- // value: 'create',
424
- // description: 'Create a new table',
425
- // action: 'Create table',
426
- // },
427
- // {
428
- // name: 'List',
429
- // value: 'list',
430
- // description: 'Get all workspace tables',
431
- // action: 'List tables',
432
- // },
433
- // {
434
- // name: 'Get Rows',
435
- // value: 'getRows',
436
- // description: 'Get table rows',
437
- // action: 'Get table rows',
438
- // },
439
- // {
440
- // name: 'Get Columns',
441
- // value: 'getColumns',
442
- // description: 'Get table columns',
443
- // action: 'Get table columns',
444
- // },
445
- // {
446
- // name: 'Run Enrichment',
447
- // value: 'runEnrichment',
448
- // description: 'Run table enrichment',
449
- // action: 'Run table enrichment',
450
- // },
451
- // ],
452
- // default: 'list',
453
- // },
454
- // Table: Get Rows/Columns/Run - Table Selection
455
- // {
456
- // displayName: 'Table',
457
- // name: 'tableUuid',
458
- // type: 'options',
459
- // typeOptions: {
460
- // loadOptionsMethod: 'getTables',
461
- // searchable: true,
462
- // },
463
- // displayOptions: {
464
- // show: {
465
- // resource: ['table'],
466
- // operation: ['getRows', 'getColumns', 'runEnrichment'],
467
- // },
468
- // },
469
- // default: '',
470
- // required: true,
471
- // description: 'Select the table to use',
472
- // },
473
- // Table: Get Rows - Pagination
474
- // {
475
- // displayName: 'Per Page',
476
- // name: 'perPage',
477
- // type: 'number',
478
- // displayOptions: {
479
- // show: {
480
- // resource: ['table'],
481
- // operation: ['getRows'],
482
- // },
483
- // },
484
- // default: 1000,
485
- // description: 'Number of items to return per page',
486
- // },
487
- // {
488
- // displayName: 'Page',
489
- // name: 'page',
490
- // type: 'number',
491
- // displayOptions: {
492
- // show: {
493
- // resource: ['table'],
494
- // operation: ['getRows'],
495
- // },
496
- // },
497
- // default: 1,
498
- // description: 'Page number to retrieve',
499
- // },
500
- // Table: Run Enrichment - Enrichment ID
501
- // {
502
- // displayName: 'Enrichment ID',
503
- // name: 'tableEnrichmentId',
504
- // type: 'string',
505
- // displayOptions: {
506
- // show: {
507
- // resource: ['table'],
508
- // operation: ['runEnrichment'],
509
- // },
510
- // },
511
- // default: '',
512
- // required: true,
513
- // description: 'The ID of the enrichment to run',
514
- // },
515
- // ====================================
516
- // WATERFALL OPERATIONS
517
- // ====================================
518
286
  {
519
287
  displayName: 'Operation',
520
288
  name: 'operation',
@@ -522,87 +290,155 @@ class Databar {
522
290
  noDataExpression: true,
523
291
  displayOptions: {
524
292
  show: {
525
- resource: ['waterfall'],
293
+ resource: ['table'],
526
294
  },
527
295
  },
528
296
  options: [
529
297
  {
530
- name: 'List',
531
- value: 'list',
532
- description: 'Get all available waterfalls',
533
- action: 'List waterfalls',
534
- },
535
- {
536
- name: 'Get',
537
- value: 'get',
538
- description: 'Get details of a specific waterfall',
539
- action: 'Get waterfall',
298
+ name: 'Insert Rows',
299
+ value: 'insertRows',
300
+ description: 'Insert one or more rows into a table',
301
+ action: 'Insert rows into table',
540
302
  },
541
303
  {
542
- name: 'Run',
543
- value: 'run',
544
- description: 'Run a waterfall task',
545
- action: 'Run waterfall',
304
+ name: 'Upsert Rows',
305
+ value: 'upsertRows',
306
+ description: 'Update rows by key or create new ones if no match is found',
307
+ action: 'Upsert rows in table',
546
308
  },
547
- // Bulk Run temporarily removed - can be re-added later if needed
548
- // {
549
- // name: 'Bulk Run',
550
- // value: 'bulkRun',
551
- // description: 'Run waterfall on multiple records',
552
- // action: 'Bulk run waterfall',
553
- // },
554
309
  ],
555
- default: 'list',
310
+ default: 'insertRows',
556
311
  },
557
- // Waterfall: Get/Run - Waterfall Selection
312
+ // Table: Selection from List
558
313
  {
559
- displayName: 'Waterfall',
560
- name: 'waterfallIdentifier',
314
+ displayName: 'Table',
315
+ name: 'tableId',
561
316
  type: 'options',
562
317
  typeOptions: {
563
- loadOptionsMethod: 'getWaterfalls',
318
+ loadOptionsMethod: 'getTables',
564
319
  searchable: true,
565
320
  },
566
321
  displayOptions: {
567
322
  show: {
568
- resource: ['waterfall'],
569
- operation: ['get', 'run'],
323
+ resource: ['table'],
570
324
  },
571
325
  },
572
326
  default: '',
573
327
  required: true,
574
- description: 'Select the waterfall to use',
328
+ description: 'Select the table to use. Switch to Expression mode to pass a dynamic table ID.',
575
329
  },
576
- // Waterfall: Run - Parameter Input Mode
330
+ // Table: Insert Rows - Fields (Resource Mapper)
577
331
  {
578
- displayName: 'Parameter Input Mode',
579
- name: 'waterfallParameterMode',
580
- type: 'options',
332
+ displayName: 'Fields',
333
+ name: 'rowFields',
334
+ type: 'resourceMapper',
335
+ noDataExpression: true,
336
+ default: {
337
+ mappingMode: 'defineBelow',
338
+ value: null,
339
+ },
340
+ required: true,
341
+ typeOptions: {
342
+ loadOptionsDependsOn: ['tableId'],
343
+ resourceMapper: {
344
+ resourceMapperMethod: 'getTableFields',
345
+ mode: 'add',
346
+ valuesLabel: 'Column',
347
+ addAllFields: true,
348
+ multiKeyMatch: false,
349
+ supportAutoMap: false,
350
+ },
351
+ },
352
+ displayOptions: {
353
+ show: {
354
+ resource: ['table'],
355
+ operation: ['insertRows'],
356
+ },
357
+ },
358
+ description: 'Column values for the row to insert. Each input item creates one row.',
359
+ },
360
+ // Table: Insert Rows - Additional Options
361
+ {
362
+ displayName: 'Options',
363
+ name: 'insertOptions',
364
+ type: 'collection',
365
+ placeholder: 'Add Option',
366
+ default: {},
367
+ displayOptions: {
368
+ show: {
369
+ resource: ['table'],
370
+ operation: ['insertRows'],
371
+ },
372
+ },
581
373
  options: [
582
374
  {
583
- name: 'Guided Fields',
584
- value: 'fields',
585
- description: 'Fill in parameters using individual fields',
375
+ displayName: 'Allow New Columns',
376
+ name: 'allowNewColumns',
377
+ type: 'boolean',
378
+ default: false,
379
+ description: 'Whether to automatically create columns that don\'t exist yet (created as text columns)',
586
380
  },
587
381
  {
588
- name: 'Raw JSON',
589
- value: 'json',
590
- description: 'Enter parameters as JSON object',
382
+ displayName: 'Dedupe',
383
+ name: 'dedupeEnabled',
384
+ type: 'boolean',
385
+ default: false,
386
+ description: 'Whether to skip rows that match existing rows on the specified keys',
387
+ },
388
+ {
389
+ displayName: 'Dedupe Keys',
390
+ name: 'dedupeKeys',
391
+ type: 'string',
392
+ default: '',
393
+ placeholder: 'domain, email',
394
+ description: 'Comma-separated column names used for duplicate detection',
395
+ displayOptions: {
396
+ show: {
397
+ dedupeEnabled: [true],
398
+ },
399
+ },
591
400
  },
592
401
  ],
402
+ },
403
+ // Table: Upsert Rows - Key Column
404
+ {
405
+ displayName: 'Column to Match On',
406
+ name: 'upsertKeyColumn',
407
+ type: 'options',
408
+ typeOptions: {
409
+ loadOptionsMethod: 'getTableColumns',
410
+ loadOptionsDependsOn: ['tableId'],
411
+ },
593
412
  displayOptions: {
594
413
  show: {
595
- resource: ['waterfall'],
596
- operation: ['run'],
414
+ resource: ['table'],
415
+ operation: ['upsertRows'],
597
416
  },
598
417
  },
599
- default: 'fields',
600
- description: 'Choose how to input waterfall parameters',
418
+ default: '',
419
+ required: true,
420
+ description: 'The column used to find an existing row. If a match is found, that row is updated; otherwise a new row is created.',
601
421
  },
602
- // Waterfall: Run - Parameters as Resource Mapper (Guided Fields)
422
+ // Table: Upsert Rows - Value to Search
603
423
  {
604
- displayName: 'Parameters',
605
- name: 'waterfallParamsFields',
424
+ displayName: 'Value to Search',
425
+ name: 'upsertKeyValue',
426
+ type: 'string',
427
+ displayOptions: {
428
+ show: {
429
+ resource: ['table'],
430
+ operation: ['upsertRows'],
431
+ },
432
+ },
433
+ default: '',
434
+ required: true,
435
+ placeholder: 'e.g. openai.com',
436
+ description: 'The value to look for in the selected column. Databar will search for a row where the column matches this value exactly. If found, that row\'s fields are updated; if not, a new row is inserted with this value and the fields you provide.',
437
+ },
438
+ // Table: Upsert Rows - Fields (Resource Mapper)
439
+ {
440
+ displayName: 'Fields',
441
+ name: 'upsertFields',
606
442
  type: 'resourceMapper',
607
443
  noDataExpression: true,
608
444
  default: {
@@ -611,60 +447,95 @@ class Databar {
611
447
  },
612
448
  required: true,
613
449
  typeOptions: {
614
- loadOptionsDependsOn: ['waterfallIdentifier'],
450
+ loadOptionsDependsOn: ['tableId'],
615
451
  resourceMapper: {
616
- resourceMapperMethod: 'getWaterfallFields',
452
+ resourceMapperMethod: 'getTableFields',
617
453
  mode: 'add',
618
- valuesLabel: 'Parameters',
454
+ valuesLabel: 'Column',
619
455
  addAllFields: true,
620
456
  multiKeyMatch: false,
457
+ supportAutoMap: false,
621
458
  },
622
459
  },
460
+ displayOptions: {
461
+ show: {
462
+ resource: ['table'],
463
+ operation: ['upsertRows'],
464
+ },
465
+ },
466
+ description: 'Column values to set on the matched or newly created row',
467
+ },
468
+ // ====================================
469
+ // WATERFALL OPERATIONS
470
+ // ====================================
471
+ {
472
+ displayName: 'Operation',
473
+ name: 'operation',
474
+ type: 'options',
475
+ noDataExpression: true,
623
476
  displayOptions: {
624
477
  show: {
625
478
  resource: ['waterfall'],
626
- operation: ['run'],
627
- waterfallParameterMode: ['fields'],
628
479
  },
629
480
  },
630
- description: 'Fill in the waterfall parameters',
481
+ options: [
482
+ {
483
+ name: 'Run',
484
+ value: 'run',
485
+ description: 'Run a waterfall task',
486
+ action: 'Run waterfall',
487
+ },
488
+ ],
489
+ default: 'run',
631
490
  },
632
- // Waterfall: Run - Template Helper for JSON Mode
491
+ // Waterfall: Run - Waterfall Selection
633
492
  {
634
- displayName: 'Template',
635
- name: 'waterfallJsonTemplateHelper',
493
+ displayName: 'Waterfall',
494
+ name: 'waterfallIdentifier',
636
495
  type: 'options',
637
496
  typeOptions: {
638
- loadOptionsMethod: 'getWaterfallTemplate',
639
- loadOptionsDependsOn: ['waterfallIdentifier'],
497
+ loadOptionsMethod: 'getWaterfalls',
498
+ searchable: true,
640
499
  },
641
500
  displayOptions: {
642
501
  show: {
643
502
  resource: ['waterfall'],
644
503
  operation: ['run'],
645
- waterfallParameterMode: ['json'],
646
504
  },
647
505
  },
648
- default: '{}',
649
- description: 'Click to see the parameter template, then copy it into the field below',
506
+ default: '',
507
+ required: true,
508
+ description: 'Select the waterfall to use',
650
509
  },
651
- // Waterfall: Run - Parameters as JSON (Raw JSON)
510
+ // Waterfall: Run - Parameters as Resource Mapper (Guided Fields)
652
511
  {
653
- displayName: 'Parameters (JSON)',
654
- name: 'params',
655
- type: 'json',
512
+ displayName: 'Parameters',
513
+ name: 'waterfallParamsFields',
514
+ type: 'resourceMapper',
515
+ noDataExpression: true,
516
+ default: {
517
+ mappingMode: 'defineBelow',
518
+ value: null,
519
+ },
520
+ required: true,
521
+ typeOptions: {
522
+ loadOptionsDependsOn: ['waterfallIdentifier'],
523
+ resourceMapper: {
524
+ resourceMapperMethod: 'getWaterfallFields',
525
+ mode: 'add',
526
+ valuesLabel: 'Parameters',
527
+ addAllFields: true,
528
+ multiKeyMatch: false,
529
+ supportAutoMap: false,
530
+ },
531
+ },
656
532
  displayOptions: {
657
533
  show: {
658
534
  resource: ['waterfall'],
659
535
  operation: ['run'],
660
- waterfallParameterMode: ['json'],
661
536
  },
662
537
  },
663
- default: '={{ $parameter["waterfallJsonTemplateHelper"] }}',
664
- placeholder: '{"first_name": "John", "last_name": "Doe", "company": "example.com"}',
665
- hint: '✨ Auto-filled from template above! Replace <text> placeholders with your actual data.',
666
- description: 'Parameters automatically populated from template. Replace placeholders with real values.',
667
- required: true,
538
+ description: 'Fill in the waterfall parameters',
668
539
  },
669
540
  // Waterfall: Run - Enrichments (Multi-select)
670
541
  {
@@ -682,6 +553,7 @@ class Databar {
682
553
  },
683
554
  },
684
555
  default: [],
556
+ required: true,
685
557
  description: 'Select which data providers to use in the waterfall. The waterfall will try each provider in order until a successful result is returned.',
686
558
  },
687
559
  // Waterfall: Run - Wait for Completion
@@ -774,9 +646,9 @@ class Databar {
774
646
  // Return error as an option so user knows what went wrong
775
647
  const errorMessage = error instanceof Error ? error.message : 'Failed to load enrichments';
776
648
  returnData.push({
777
- name: `⚠️ Error: ${errorMessage}`,
649
+ name: `Error: ${errorMessage}`,
778
650
  value: '',
779
- description: 'Switch to "By ID" mode to enter enrichment ID manually',
651
+ description: 'Could not load enrichments. Check your API key and try again.',
780
652
  });
781
653
  }
782
654
  return returnData;
@@ -838,7 +710,7 @@ class Databar {
838
710
  const availableEnrichments = waterfallData.available_enrichments || [];
839
711
  if (availableEnrichments.length === 0) {
840
712
  return [{
841
- name: '⚠️ No Data Providers Available',
713
+ name: 'No Data Providers Available',
842
714
  value: '',
843
715
  description: 'This waterfall has no available data providers configured.',
844
716
  }];
@@ -861,42 +733,88 @@ class Databar {
861
733
  catch (error) {
862
734
  const errorMessage = error instanceof Error ? error.message : String(error);
863
735
  return [{
864
- name: '⚠️ Error Loading Data Providers',
736
+ name: 'Error Loading Data Providers',
865
737
  value: '',
866
738
  description: `Could not fetch waterfall data providers. Error: ${errorMessage}`,
867
739
  }];
868
740
  }
869
741
  return returnData;
870
742
  },
871
- // Load tables - temporarily hidden, can be re-enabled later
872
- // async getTables(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
873
- // const returnData: INodePropertyOptions[] = [];
874
- // try {
875
- // const tables = await this.helpers.httpRequestWithAuthentication.call(
876
- // this,
877
- // 'databarApi',
878
- // {
879
- // method: 'GET',
880
- // url: 'https://api.databar.ai/v1/table/',
881
- // },
882
- // );
883
- // if (Array.isArray(tables)) {
884
- // for (const table of tables) {
885
- // const tableData = table as IDataObject;
886
- // returnData.push({
887
- // name: tableData.name as string,
888
- // value: tableData.identifier as string,
889
- // description: `Created: ${tableData.created_at}`,
890
- // });
891
- // }
892
- // }
893
- // // Sort by name
894
- // returnData.sort((a, b) => a.name.localeCompare(b.name));
895
- // } catch (error) {
896
- // // Silently fail
897
- // }
898
- // return returnData;
899
- // },
743
+ async getTables() {
744
+ const returnData = [];
745
+ try {
746
+ const tables = await this.helpers.httpRequestWithAuthentication.call(this, 'databarApi', {
747
+ method: 'GET',
748
+ url: 'https://api.databar.ai/v1/table/',
749
+ });
750
+ if (Array.isArray(tables)) {
751
+ for (const table of tables) {
752
+ const tableData = table;
753
+ returnData.push({
754
+ name: tableData.name,
755
+ value: tableData.identifier,
756
+ description: `Created: ${tableData.created_at}`,
757
+ });
758
+ }
759
+ }
760
+ returnData.sort((a, b) => a.name.localeCompare(b.name));
761
+ }
762
+ catch (error) {
763
+ const errorMessage = error instanceof Error ? error.message : 'Failed to load tables';
764
+ returnData.push({
765
+ name: `Error: ${errorMessage}`,
766
+ value: '',
767
+ description: 'Could not load tables. Check your API key and try again.',
768
+ });
769
+ }
770
+ return returnData;
771
+ },
772
+ async getTableColumns() {
773
+ const returnData = [];
774
+ try {
775
+ let tableId;
776
+ try {
777
+ const tableIdRaw = this.getCurrentNodeParameter('tableId');
778
+ if (tableIdRaw) {
779
+ tableId = tableIdRaw;
780
+ }
781
+ }
782
+ catch (error) {
783
+ // Parameter might not be set yet
784
+ }
785
+ if (!tableId) {
786
+ return [{
787
+ name: 'Select a Table First',
788
+ value: '',
789
+ }];
790
+ }
791
+ const columns = await this.helpers.httpRequestWithAuthentication.call(this, 'databarApi', {
792
+ method: 'GET',
793
+ url: `https://api.databar.ai/v1/table/${tableId}/columns`,
794
+ });
795
+ if (Array.isArray(columns)) {
796
+ for (const column of columns) {
797
+ const colData = column;
798
+ if (colData.data_processor_id)
799
+ continue;
800
+ returnData.push({
801
+ name: colData.name,
802
+ value: colData.internal_name,
803
+ description: `Type: ${colData.type_of_value || 'unknown'}`,
804
+ });
805
+ }
806
+ }
807
+ returnData.sort((a, b) => a.name.localeCompare(b.name));
808
+ }
809
+ catch (error) {
810
+ const errorMessage = error instanceof Error ? error.message : 'Failed to load columns';
811
+ returnData.push({
812
+ name: `Error: ${errorMessage}`,
813
+ value: '',
814
+ });
815
+ }
816
+ return returnData;
817
+ },
900
818
  /**
901
819
  * Get parameter template for selected enrichment
902
820
  *
@@ -956,17 +874,17 @@ class Databar {
956
874
  const singleLineJson = JSON.stringify(template); // Single line for expression
957
875
  const paramList = paramDescriptions.join('\n');
958
876
  return [{
959
- name: '📋 Template Loaded',
877
+ name: 'Template Loaded',
960
878
  value: singleLineJson,
961
- description: `Required Parameters:\n${paramList}\n\n📝 JSON Template:\n${templateJson}`,
879
+ description: `Required Parameters:\n${paramList}\n\nJSON Template:\n${templateJson}`,
962
880
  }];
963
881
  }
964
882
  catch (error) {
965
883
  const errorMessage = error instanceof Error ? error.message : String(error);
966
884
  return [{
967
- name: '⚠️ Error Loading Template',
885
+ name: 'Error Loading Template',
968
886
  value: '{}',
969
- description: `Could not fetch enrichment parameters. Error: ${errorMessage}\n\nTry:\n• Verify the enrichment ID is valid\n• Check your API key has access\n• Use the "Get" operation to see parameters manually`,
887
+ description: `Could not fetch enrichment parameters: ${errorMessage}`,
970
888
  }];
971
889
  }
972
890
  },
@@ -1029,22 +947,83 @@ class Databar {
1029
947
  const singleLineJson = JSON.stringify(template); // Single line for expression
1030
948
  const paramList = paramDescriptions.join('\n');
1031
949
  return [{
1032
- name: '📋 Template Loaded',
950
+ name: 'Template Loaded',
1033
951
  value: singleLineJson,
1034
- description: `Required Parameters:\n${paramList}\n\n📝 JSON Template:\n${templateJson}`,
952
+ description: `Required Parameters:\n${paramList}\n\nJSON Template:\n${templateJson}`,
1035
953
  }];
1036
954
  }
1037
955
  catch (error) {
1038
956
  const errorMessage = error instanceof Error ? error.message : String(error);
1039
957
  return [{
1040
- name: '⚠️ Error Loading Template',
958
+ name: 'Error Loading Template',
1041
959
  value: '{}',
1042
- description: `Could not fetch waterfall parameters. Error: ${errorMessage}\n\nTry:\n• Verify the waterfall identifier is valid\n• Check your API key has access\n• Use the "Get" operation to see parameters manually`,
960
+ description: `Could not fetch waterfall parameters: ${errorMessage}`,
1043
961
  }];
1044
962
  }
1045
963
  },
1046
964
  },
1047
965
  resourceMapping: {
966
+ /**
967
+ * Get table column definitions for the resource mapper.
968
+ * Fetches columns from the API and maps them to ResourceMapperField entries
969
+ * so n8n renders a per-column form UI.
970
+ */
971
+ async getTableFields() {
972
+ try {
973
+ let tableId;
974
+ try {
975
+ const tableIdRaw = this.getCurrentNodeParameter('tableId');
976
+ if (tableIdRaw) {
977
+ tableId = tableIdRaw;
978
+ }
979
+ }
980
+ catch (_error) {
981
+ // Parameter might not be set yet
982
+ }
983
+ if (!tableId) {
984
+ return { fields: [] };
985
+ }
986
+ const columns = await this.helpers.httpRequestWithAuthentication.call(this, 'databarApi', {
987
+ method: 'GET',
988
+ url: `https://api.databar.ai/v1/table/${tableId}/columns`,
989
+ });
990
+ if (!Array.isArray(columns) || columns.length === 0) {
991
+ return { fields: [] };
992
+ }
993
+ const typeMap = {
994
+ text: 'string',
995
+ longtext: 'string',
996
+ number: 'number',
997
+ integer: 'number',
998
+ float: 'number',
999
+ boolean: 'boolean',
1000
+ bool: 'boolean',
1001
+ };
1002
+ const userColumns = columns.filter((column) => {
1003
+ const col = column;
1004
+ return !col.data_processor_id;
1005
+ });
1006
+ const fields = userColumns.map((column) => {
1007
+ const col = column;
1008
+ const internalName = col.internal_name;
1009
+ const displayName = col.name;
1010
+ const colType = col.type_of_value || 'text';
1011
+ return {
1012
+ id: internalName,
1013
+ displayName: `${displayName} (${colType})`,
1014
+ required: false,
1015
+ defaultMatch: false,
1016
+ display: true,
1017
+ type: typeMap[colType] || 'string',
1018
+ canBeUsedToMatch: true,
1019
+ };
1020
+ });
1021
+ return { fields };
1022
+ }
1023
+ catch (_error) {
1024
+ return { fields: [] };
1025
+ }
1026
+ },
1048
1027
  /**
1049
1028
  * Get enrichment fields for resource mapper
1050
1029
  *
@@ -1245,7 +1224,10 @@ class Databar {
1245
1224
  method: 'GET',
1246
1225
  url: 'https://api.databar.ai/v1/user/me',
1247
1226
  });
1248
- returnData.push(response);
1227
+ returnData.push({
1228
+ json: response,
1229
+ pairedItem: { item: i },
1230
+ });
1249
1231
  }
1250
1232
  }
1251
1233
  // ====================================
@@ -1258,26 +1240,9 @@ class Databar {
1258
1240
  if (!enrichmentId || isNaN(enrichmentId)) {
1259
1241
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Please provide a valid enrichment ID', { itemIndex: i });
1260
1242
  }
1261
- const parameterMode = this.getNodeParameter('parameterMode', i, 'fields');
1262
1243
  const waitForCompletion = this.getNodeParameter('waitForCompletion', i, true);
1263
- // Get parameters based on input mode
1264
- let params;
1265
- if (parameterMode === 'fields') {
1266
- // Resource mapper mode - get structured fields
1267
- const paramsFields = this.getNodeParameter('paramsFields', i);
1268
- // Resource mapper returns an object with 'value' containing the actual data
1269
- params = paramsFields.value || {};
1270
- }
1271
- else {
1272
- // Raw JSON mode - parse JSON string
1273
- const paramsJson = this.getNodeParameter('paramsJson', i);
1274
- try {
1275
- params = JSON.parse(paramsJson);
1276
- }
1277
- catch (error) {
1278
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Parameters must be valid JSON object', { itemIndex: i });
1279
- }
1280
- }
1244
+ const paramsFields = this.getNodeParameter('paramsFields', i);
1245
+ const params = paramsFields.value || {};
1281
1246
  const response = await this.helpers.httpRequestWithAuthentication.call(this, 'databarApi', {
1282
1247
  method: 'POST',
1283
1248
  url: `https://api.databar.ai/v1/enrichments/${enrichmentId}/run`,
@@ -1291,10 +1256,16 @@ class Databar {
1291
1256
  const taskId = taskResponse.task_id;
1292
1257
  // Poll for completion
1293
1258
  const completedTask = await pollTaskStatus(this, taskId, pollInterval, timeout);
1294
- returnData.push(completedTask);
1259
+ returnData.push({
1260
+ json: completedTask,
1261
+ pairedItem: { item: i },
1262
+ });
1295
1263
  }
1296
1264
  else {
1297
- returnData.push(taskResponse);
1265
+ returnData.push({
1266
+ json: taskResponse,
1267
+ pairedItem: { item: i },
1268
+ });
1298
1269
  }
1299
1270
  }
1300
1271
  else if (operation === 'bulkRun') {
@@ -1325,136 +1296,90 @@ class Databar {
1325
1296
  const taskId = taskResponse.task_id;
1326
1297
  // Poll for completion
1327
1298
  const completedTask = await pollTaskStatus(this, taskId, pollInterval, timeout);
1328
- returnData.push(completedTask);
1299
+ returnData.push({
1300
+ json: completedTask,
1301
+ pairedItem: { item: i },
1302
+ });
1329
1303
  }
1330
1304
  else {
1331
- returnData.push(taskResponse);
1305
+ returnData.push({
1306
+ json: taskResponse,
1307
+ pairedItem: { item: i },
1308
+ });
1332
1309
  }
1333
1310
  }
1334
1311
  }
1335
1312
  // ====================================
1336
1313
  // TABLE OPERATIONS
1337
1314
  // ====================================
1338
- // Table operations temporarily hidden - can be re-enabled later
1339
- // else if (resource === 'table') {
1340
- // if (operation === 'create') {
1341
- // const response = await this.helpers.httpRequestWithAuthentication.call(
1342
- // this,
1343
- // 'databarApi',
1344
- // {
1345
- // method: 'POST',
1346
- // url: 'https://api.databar.ai/v1/table/create',
1347
- // body: {},
1348
- // },
1349
- // );
1350
- // returnData.push(response as IDataObject);
1351
- // } else if (operation === 'list') {
1352
- // const response = await this.helpers.httpRequestWithAuthentication.call(
1353
- // this,
1354
- // 'databarApi',
1355
- // {
1356
- // method: 'GET',
1357
- // url: 'https://api.databar.ai/v1/table/',
1358
- // },
1359
- // );
1360
- // if (Array.isArray(response)) {
1361
- // returnData.push(...(response as IDataObject[]));
1362
- // } else {
1363
- // returnData.push(response as IDataObject);
1364
- // }
1365
- // } else if (operation === 'getRows') {
1366
- // const tableUuid = this.getNodeParameter('tableUuid', i) as string;
1367
- // const perPage = this.getNodeParameter('perPage', i) as number;
1368
- // const page = this.getNodeParameter('page', i) as number;
1369
- //
1370
- // const response = await this.helpers.httpRequestWithAuthentication.call(
1371
- // this,
1372
- // 'databarApi',
1373
- // {
1374
- // method: 'GET',
1375
- // url: `https://api.databar.ai/v1/table/${tableUuid}/rows`,
1376
- // qs: { per_page: perPage, page },
1377
- // },
1378
- // );
1379
- // returnData.push(response as IDataObject);
1380
- // } else if (operation === 'getColumns') {
1381
- // const tableUuid = this.getNodeParameter('tableUuid', i) as string;
1382
- //
1383
- // const response = await this.helpers.httpRequestWithAuthentication.call(
1384
- // this,
1385
- // 'databarApi',
1386
- // {
1387
- // method: 'GET',
1388
- // url: `https://api.databar.ai/v1/table/${tableUuid}/columns`,
1389
- // },
1390
- // );
1391
- // if (Array.isArray(response)) {
1392
- // returnData.push(...(response as IDataObject[]));
1393
- // } else {
1394
- // returnData.push(response as IDataObject);
1395
- // }
1396
- // } else if (operation === 'runEnrichment') {
1397
- // const tableUuid = this.getNodeParameter('tableUuid', i) as string;
1398
- // const tableEnrichmentId = this.getNodeParameter('tableEnrichmentId', i) as string;
1399
- //
1400
- // const response = await this.helpers.httpRequestWithAuthentication.call(
1401
- // this,
1402
- // 'databarApi',
1403
- // {
1404
- // method: 'GET',
1405
- // url: `https://api.databar.ai/v1/table/${tableUuid}/run-enrichment/${tableEnrichmentId}`,
1406
- // },
1407
- // );
1408
- // returnData.push(response as IDataObject);
1409
- // }
1410
- // }
1411
- // ====================================
1412
- // WATERFALL OPERATIONS
1413
- // ====================================
1414
- else if (resource === 'waterfall') {
1415
- if (operation === 'list') {
1416
- const response = await this.helpers.httpRequestWithAuthentication.call(this, 'databarApi', {
1417
- method: 'GET',
1418
- url: 'https://api.databar.ai/v1/waterfalls/',
1419
- });
1420
- if (Array.isArray(response)) {
1421
- returnData.push(...response);
1315
+ else if (resource === 'table') {
1316
+ const tableId = this.getNodeParameter('tableId', i);
1317
+ if (!tableId) {
1318
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Please provide a valid table ID', { itemIndex: i });
1319
+ }
1320
+ if (operation === 'insertRows') {
1321
+ const rowFieldsMapper = this.getNodeParameter('rowFields', i);
1322
+ const insertOptions = this.getNodeParameter('insertOptions', i, {});
1323
+ const fields = rowFieldsMapper.value || {};
1324
+ const row = { fields };
1325
+ const options = {};
1326
+ if (insertOptions.allowNewColumns !== undefined) {
1327
+ options.allow_new_columns = insertOptions.allowNewColumns;
1422
1328
  }
1423
- else {
1424
- returnData.push(response);
1329
+ if (insertOptions.dedupeEnabled) {
1330
+ const keysStr = insertOptions.dedupeKeys || '';
1331
+ options.dedupe = {
1332
+ enabled: true,
1333
+ keys: keysStr.split(',').map((k) => k.trim()).filter((k) => k),
1334
+ };
1425
1335
  }
1336
+ const body = { rows: [row] };
1337
+ if (Object.keys(options).length > 0) {
1338
+ body.options = options;
1339
+ }
1340
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'databarApi', {
1341
+ method: 'POST',
1342
+ url: `https://api.databar.ai/v1/table/${tableId}/rows`,
1343
+ body,
1344
+ });
1345
+ returnData.push({
1346
+ json: response,
1347
+ pairedItem: { item: i },
1348
+ });
1426
1349
  }
1427
- else if (operation === 'get') {
1428
- const waterfallIdentifier = this.getNodeParameter('waterfallIdentifier', i);
1350
+ else if (operation === 'upsertRows') {
1351
+ const keyColumn = this.getNodeParameter('upsertKeyColumn', i);
1352
+ const keyValue = this.getNodeParameter('upsertKeyValue', i);
1353
+ const upsertFieldsMapper = this.getNodeParameter('upsertFields', i);
1354
+ if (!keyColumn) {
1355
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Please provide a key column name', { itemIndex: i });
1356
+ }
1357
+ const fields = upsertFieldsMapper.value || {};
1358
+ const row = {
1359
+ key: { [keyColumn]: keyValue },
1360
+ fields,
1361
+ };
1429
1362
  const response = await this.helpers.httpRequestWithAuthentication.call(this, 'databarApi', {
1430
- method: 'GET',
1431
- url: `https://api.databar.ai/v1/waterfalls/${waterfallIdentifier}`,
1363
+ method: 'POST',
1364
+ url: `https://api.databar.ai/v1/table/${tableId}/rows/upsert`,
1365
+ body: { rows: [row] },
1366
+ });
1367
+ returnData.push({
1368
+ json: response,
1369
+ pairedItem: { item: i },
1432
1370
  });
1433
- returnData.push(response);
1434
1371
  }
1435
- else if (operation === 'run') {
1372
+ }
1373
+ // ====================================
1374
+ // WATERFALL OPERATIONS
1375
+ // ====================================
1376
+ else if (resource === 'waterfall') {
1377
+ if (operation === 'run') {
1436
1378
  const waterfallIdentifier = this.getNodeParameter('waterfallIdentifier', i);
1437
- const parameterMode = this.getNodeParameter('waterfallParameterMode', i, 'fields');
1438
1379
  const enrichmentsRaw = this.getNodeParameter('enrichments', i, []);
1439
1380
  const waitForCompletion = this.getNodeParameter('waitForCompletion', i, true);
1440
- // Get parameters based on input mode
1441
- let params;
1442
- if (parameterMode === 'fields') {
1443
- // Resource mapper mode - get structured fields
1444
- const paramsFields = this.getNodeParameter('waterfallParamsFields', i);
1445
- // Resource mapper returns an object with 'value' containing the actual data
1446
- params = paramsFields.value || {};
1447
- }
1448
- else {
1449
- // Raw JSON mode - parse JSON string
1450
- const paramsJson = this.getNodeParameter('params', i);
1451
- try {
1452
- params = JSON.parse(paramsJson);
1453
- }
1454
- catch (error) {
1455
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Parameters must be valid JSON object', { itemIndex: i });
1456
- }
1457
- }
1381
+ const paramsFields = this.getNodeParameter('waterfallParamsFields', i);
1382
+ const params = paramsFields.value || {};
1458
1383
  // Convert enrichment IDs to numbers (multiOptions returns array of selected values)
1459
1384
  const enrichments = enrichmentsRaw.map((id) => {
1460
1385
  return typeof id === 'string' ? parseInt(id, 10) : id;
@@ -1472,10 +1397,16 @@ class Databar {
1472
1397
  const taskId = taskResponse.task_id;
1473
1398
  // Poll for completion
1474
1399
  const completedTask = await pollTaskStatus(this, taskId, pollInterval, timeout);
1475
- returnData.push(completedTask);
1400
+ returnData.push({
1401
+ json: completedTask,
1402
+ pairedItem: { item: i },
1403
+ });
1476
1404
  }
1477
1405
  else {
1478
- returnData.push(taskResponse);
1406
+ returnData.push({
1407
+ json: taskResponse,
1408
+ pairedItem: { item: i },
1409
+ });
1479
1410
  }
1480
1411
  }
1481
1412
  }
@@ -1483,13 +1414,16 @@ class Databar {
1483
1414
  catch (error) {
1484
1415
  if (this.continueOnFail()) {
1485
1416
  const errorMessage = error instanceof Error ? error.message : String(error);
1486
- returnData.push({ error: errorMessage });
1417
+ returnData.push({
1418
+ json: { error: errorMessage },
1419
+ pairedItem: { item: i },
1420
+ });
1487
1421
  continue;
1488
1422
  }
1489
1423
  throw error;
1490
1424
  }
1491
1425
  }
1492
- return [this.helpers.returnJsonArray(returnData)];
1426
+ return [returnData];
1493
1427
  }
1494
1428
  }
1495
1429
  exports.Databar = Databar;