@deepidealab/n8n-nodes-tracira 0.6.0 → 0.8.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.
Files changed (34) hide show
  1. package/README.md +13 -13
  2. package/dist/credentials/TraciraApi.credentials.js +2 -2
  3. package/dist/credentials/TraciraApi.credentials.js.map +1 -1
  4. package/dist/nodes/Tracira/Tracira.node.d.ts +8 -0
  5. package/dist/nodes/Tracira/Tracira.node.js +340 -66
  6. package/dist/nodes/Tracira/Tracira.node.js.map +1 -1
  7. package/dist/nodes/Tracira/listSearch/getProjects.d.ts +2 -0
  8. package/dist/nodes/Tracira/listSearch/{getFlows.js → getProjects.js} +8 -8
  9. package/dist/nodes/Tracira/listSearch/getProjects.js.map +1 -0
  10. package/dist/nodes/Tracira/listSearch/{getFlows.d.ts → getTasks.d.ts} +1 -1
  11. package/dist/nodes/Tracira/listSearch/getTasks.js +18 -0
  12. package/dist/nodes/Tracira/listSearch/getTasks.js.map +1 -0
  13. package/dist/package.json +2 -2
  14. package/dist/tsconfig.tsbuildinfo +1 -1
  15. package/package.json +2 -2
  16. package/dist/nodes/Tracira/listSearch/getChecks.d.ts +0 -2
  17. package/dist/nodes/Tracira/listSearch/getChecks.js +0 -18
  18. package/dist/nodes/Tracira/listSearch/getChecks.js.map +0 -1
  19. package/dist/nodes/Tracira/listSearch/getFlows.js.map +0 -1
  20. package/dist/nodes/Tracira/listSearch/getModels.d.ts +0 -2
  21. package/dist/nodes/Tracira/listSearch/getModels.js +0 -18
  22. package/dist/nodes/Tracira/listSearch/getModels.js.map +0 -1
  23. package/dist/nodes/Tracira/resources/execution/get.d.ts +0 -2
  24. package/dist/nodes/Tracira/resources/execution/get.js +0 -21
  25. package/dist/nodes/Tracira/resources/execution/get.js.map +0 -1
  26. package/dist/nodes/Tracira/resources/execution/getAll.d.ts +0 -2
  27. package/dist/nodes/Tracira/resources/execution/getAll.js +0 -244
  28. package/dist/nodes/Tracira/resources/execution/getAll.js.map +0 -1
  29. package/dist/nodes/Tracira/resources/execution/index.d.ts +0 -2
  30. package/dist/nodes/Tracira/resources/execution/index.js +0 -73
  31. package/dist/nodes/Tracira/resources/execution/index.js.map +0 -1
  32. package/dist/nodes/Tracira/resources/execution/log.d.ts +0 -2
  33. package/dist/nodes/Tracira/resources/execution/log.js +0 -291
  34. package/dist/nodes/Tracira/resources/execution/log.js.map +0 -1
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Tracira = void 0;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
+ const getProjects_1 = require("./listSearch/getProjects");
6
+ const getTasks_1 = require("./listSearch/getTasks");
5
7
  const baseUrl = 'https://www.tracira.com/api';
6
8
  const logResourceDisplay = {
7
9
  resource: ['log'],
@@ -19,7 +21,7 @@ const getDisplay = {
19
21
  };
20
22
  const getAllDisplay = {
21
23
  resource: ['log'],
22
- operation: ['getAll'],
24
+ operation: ['search'],
23
25
  };
24
26
  const setDecisionDisplay = {
25
27
  resource: ['log'],
@@ -29,6 +31,10 @@ const flagDisplay = {
29
31
  resource: ['log'],
30
32
  operation: ['flag'],
31
33
  };
34
+ const uploadDisplay = {
35
+ resource: ['log'],
36
+ operation: ['upload'],
37
+ };
32
38
  const apiCallDisplay = {
33
39
  resource: ['api'],
34
40
  operation: ['call'],
@@ -36,15 +42,15 @@ const apiCallDisplay = {
36
42
  function stripEmpty(data) {
37
43
  return Object.fromEntries(Object.entries(data).filter(([, value]) => value !== '' && value !== undefined && value !== null));
38
44
  }
39
- function normalizeApiPath(path) {
45
+ function normalizeApiPath(path, node) {
40
46
  if (!path.trim())
41
47
  return '/';
42
48
  if (path.startsWith('http://') || path.startsWith('https://')) {
43
- throw new n8n_workflow_1.ApplicationError('Use a path relative to https://www.tracira.com/api, for example /logs');
49
+ throw new n8n_workflow_1.NodeOperationError(node, 'Use a path relative to https://www.tracira.com/api, for example /logs');
44
50
  }
45
51
  return path.startsWith('/') ? path : `/${path}`;
46
52
  }
47
- function parseJsonObject(text, fieldName) {
53
+ function parseJsonObject(text, fieldName, node) {
48
54
  if (!text.trim())
49
55
  return {};
50
56
  let parsed;
@@ -52,10 +58,10 @@ function parseJsonObject(text, fieldName) {
52
58
  parsed = JSON.parse(text);
53
59
  }
54
60
  catch {
55
- throw new n8n_workflow_1.ApplicationError(`${fieldName} must be valid JSON`);
61
+ throw new n8n_workflow_1.NodeOperationError(node, `${fieldName} must be valid JSON`);
56
62
  }
57
63
  if (parsed === null || Array.isArray(parsed) || typeof parsed !== 'object') {
58
- throw new n8n_workflow_1.ApplicationError(`${fieldName} must be a JSON object`);
64
+ throw new n8n_workflow_1.NodeOperationError(node, `${fieldName} must be a JSON object`);
59
65
  }
60
66
  return parsed;
61
67
  }
@@ -82,7 +88,7 @@ class Tracira {
82
88
  this.description = {
83
89
  displayName: 'Tracira',
84
90
  name: 'tracira',
85
- icon: 'file:tracira.svg',
91
+ icon: { light: 'file:tracira.svg', dark: 'file:tracira.dark.svg' },
86
92
  group: ['transform'],
87
93
  version: 1,
88
94
  subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
@@ -106,8 +112,8 @@ class Tracira {
106
112
  defaults: {
107
113
  name: 'Tracira',
108
114
  },
109
- inputs: ['main'],
110
- outputs: ['main'],
115
+ inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
116
+ outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
111
117
  credentials: [
112
118
  {
113
119
  name: 'traciraApi',
@@ -142,34 +148,40 @@ class Tracira {
142
148
  },
143
149
  options: [
144
150
  {
145
- name: 'Flag',
151
+ name: 'Create a Log',
152
+ value: 'log',
153
+ action: 'Create a log',
154
+ description: 'Send an AI output to Tracira and create a log for evaluation. Returns a verdict, confidence score, and explanation based on your configured rules.',
155
+ },
156
+ {
157
+ name: 'Flag a Log',
146
158
  value: 'flag',
147
- action: 'Flag a log for review',
159
+ action: 'Flag a log',
148
160
  description: 'Flag an evaluated log for human review, e.g. when an end-user reports an issue',
149
161
  },
150
162
  {
151
- name: 'Get',
163
+ name: 'Get a Log',
152
164
  value: 'get',
153
165
  action: 'Get a log',
154
- description: 'Fetch a single log by ID',
166
+ description: 'Fetch a single log by ID, including verdict, explanation, and human decision',
155
167
  },
156
168
  {
157
- name: 'Get Many',
158
- value: 'getAll',
159
- action: 'Get many logs',
160
- description: 'List logs from Tracira',
169
+ name: 'Search Logs',
170
+ value: 'search',
171
+ action: 'Search logs',
172
+ description: 'Return a filtered list of logs from Tracira. Filter by status, project, task name, or date range.',
161
173
  },
162
174
  {
163
- name: 'Log',
164
- value: 'log',
165
- action: 'Log an AI output',
166
- description: 'Send an AI output to Tracira for evaluation',
175
+ name: 'Set a Decision',
176
+ value: 'setDecision',
177
+ action: 'Set a decision',
178
+ description: 'Approve, reject, or send a flagged log back to the AI with a comment',
167
179
  },
168
180
  {
169
- name: 'Set Decision',
170
- value: 'setDecision',
171
- action: 'Set a decision for a log',
172
- description: 'Approve or reject a flagged log',
181
+ name: 'Upload a File',
182
+ value: 'upload',
183
+ action: 'Upload a file',
184
+ description: 'Upload a large file directly to Tracira storage, then attach it to a log by key',
173
185
  },
174
186
  ],
175
187
  default: 'log',
@@ -225,20 +237,20 @@ class Tracira {
225
237
  },
226
238
  options: [
227
239
  {
228
- name: 'Approved',
240
+ name: 'Approve',
229
241
  value: 'approved',
230
242
  },
231
243
  {
232
- name: 'Changed',
233
- value: 'changed',
234
- description: 'Send the log back to the AI with a comment to regenerate',
244
+ name: 'Reject',
245
+ value: 'rejected',
235
246
  },
236
247
  {
237
- name: 'Rejected',
238
- value: 'rejected',
248
+ name: 'Send Back for Changes',
249
+ value: 'changed',
250
+ description: 'Send the log back to the AI with a comment to regenerate',
239
251
  },
240
252
  ],
241
- description: 'The human review decision to record',
253
+ description: 'Approve or reject the flagged log, or send it back to the AI with a comment',
242
254
  },
243
255
  {
244
256
  displayName: 'Comment',
@@ -255,7 +267,7 @@ class Tracira {
255
267
  decision: ['changed'],
256
268
  },
257
269
  },
258
- description: 'The instruction sent back to the AI describing what to change. Required when Decision is Changed. The AI should regenerate the output and resubmit it with the Log operation, setting Revision Of to this log ID.',
270
+ description: 'The instruction sent back to the AI describing what to change. Required when Decision is Send Back for Changes. The AI should regenerate the output and resubmit it with the Create a Log operation, setting Revision Of to this log ID.',
259
271
  },
260
272
  {
261
273
  displayName: 'Log ID',
@@ -282,18 +294,66 @@ class Tracira {
282
294
  description: 'Optional reason for flagging, stored as the log explanation, for example the message your end-user submitted when reporting the issue',
283
295
  },
284
296
  {
285
- displayName: 'Project',
286
- name: 'projectName',
297
+ displayName: 'Input Binary Field',
298
+ name: 'binaryPropertyName',
287
299
  type: 'string',
288
300
  required: true,
301
+ default: 'data',
302
+ displayOptions: {
303
+ show: uploadDisplay,
304
+ },
305
+ hint: 'The name of the input field containing the binary file to upload',
306
+ description: 'Name of the input binary field holding the file (PDF, image, or audio) to upload. The file goes straight to storage, bypassing the request size limit. Up to 32 MB.',
307
+ },
308
+ {
309
+ displayName: 'File Name',
310
+ name: 'uploadFileName',
311
+ type: 'string',
312
+ default: '',
313
+ displayOptions: {
314
+ show: uploadDisplay,
315
+ },
316
+ description: 'Optional file name. Overrides the binary field name; its extension is used to detect the file type.',
317
+ },
318
+ {
319
+ displayName: 'Content Type',
320
+ name: 'uploadContentType',
321
+ type: 'string',
289
322
  default: '',
323
+ displayOptions: {
324
+ show: uploadDisplay,
325
+ },
326
+ description: 'Optional. Override the MIME type (e.g. application/pdf, image/png). Only needed when the file name has no recognizable extension.',
327
+ },
328
+ {
329
+ displayName: 'Project Name',
330
+ name: 'projectName',
331
+ type: 'resourceLocator',
332
+ required: true,
333
+ default: { mode: 'list', value: '' },
290
334
  displayOptions: {
291
335
  show: logOperationDisplay,
292
336
  },
293
- description: 'The Tracira project name for this log',
337
+ description: 'Select an existing project or enter a new name it will be auto-created in Tracira on first use',
338
+ modes: [
339
+ {
340
+ displayName: 'From List',
341
+ name: 'list',
342
+ type: 'list',
343
+ typeOptions: {
344
+ searchListMethod: 'getProjects',
345
+ searchable: true,
346
+ },
347
+ },
348
+ {
349
+ displayName: 'Name',
350
+ name: 'name',
351
+ type: 'string',
352
+ },
353
+ ],
294
354
  },
295
355
  {
296
- displayName: 'Output',
356
+ displayName: 'AI Output',
297
357
  name: 'output',
298
358
  type: 'string',
299
359
  typeOptions: {
@@ -304,10 +364,10 @@ class Tracira {
304
364
  displayOptions: {
305
365
  show: logOperationDisplay,
306
366
  },
307
- description: 'The AI-generated output to evaluate in Tracira',
367
+ description: 'The AI-generated output to evaluate against your Tracira rules',
308
368
  },
309
369
  {
310
- displayName: 'Input',
370
+ displayName: 'Text Prompt',
311
371
  name: 'input',
312
372
  type: 'string',
313
373
  typeOptions: {
@@ -317,27 +377,133 @@ class Tracira {
317
377
  displayOptions: {
318
378
  show: logOperationDisplay,
319
379
  },
320
- description: 'Optional prompt or input text that produced the output',
380
+ description: 'Optional text sent to your AI model alongside any attachments',
381
+ },
382
+ {
383
+ displayName: 'Attachments',
384
+ name: 'attachments',
385
+ type: 'fixedCollection',
386
+ typeOptions: {
387
+ multipleValues: true,
388
+ },
389
+ placeholder: 'Add Attachment',
390
+ default: {},
391
+ displayOptions: {
392
+ show: logOperationDisplay,
393
+ },
394
+ description: 'Files to attach to the log (the source the AI worked from). Tracira auto-detects whether each attachment is an image, audio file, or document.',
395
+ options: [
396
+ {
397
+ name: 'attachment',
398
+ displayName: 'Attachment',
399
+ values: [
400
+ {
401
+ displayName: 'Attachment Key',
402
+ name: 'key',
403
+ type: 'string',
404
+ default: '',
405
+ displayOptions: {
406
+ show: {
407
+ source: ['uploaded'],
408
+ },
409
+ },
410
+ description: 'The key returned by an Upload a File operation. Use this for large files (over 3 MB) that cannot be sent inline.',
411
+ },
412
+ {
413
+ displayName: 'File Name',
414
+ name: 'filename',
415
+ type: 'string',
416
+ default: '',
417
+ description: 'Optional original file name shown to reviewers',
418
+ },
419
+ {
420
+ displayName: 'Input Binary Field',
421
+ name: 'binaryProperty',
422
+ type: 'string',
423
+ default: 'data',
424
+ displayOptions: {
425
+ show: {
426
+ source: ['upload'],
427
+ },
428
+ },
429
+ hint: 'The name of the input field containing the binary file to attach',
430
+ description: 'The file is sent inline with this request. The whole request is limited to 4.5 MB, so keep inline files under ~3 MB. For larger files, use the Upload a File operation first, then attach with source "Tracira Upload".',
431
+ },
432
+ {
433
+ displayName: 'Source',
434
+ name: 'source',
435
+ type: 'options',
436
+ default: 'upload',
437
+ options: [
438
+ {
439
+ name: 'From URL',
440
+ value: 'url',
441
+ description: 'HTTPS URL to a publicly accessible file',
442
+ },
443
+ {
444
+ name: 'Tracira Upload',
445
+ value: 'uploaded',
446
+ description: 'A key returned by the Upload a File operation — use for files over ~3 MB',
447
+ },
448
+ {
449
+ name: 'Upload File',
450
+ value: 'upload',
451
+ description: 'Send a binary file inline with this request (keep under ~3 MB)',
452
+ },
453
+ ],
454
+ description: 'Where the file comes from',
455
+ },
456
+ {
457
+ displayName: 'URL',
458
+ name: 'url',
459
+ type: 'string',
460
+ default: '',
461
+ displayOptions: {
462
+ show: {
463
+ source: ['url'],
464
+ },
465
+ },
466
+ description: 'HTTPS URL to a publicly accessible image, audio file, or PDF',
467
+ },
468
+ ],
469
+ },
470
+ ],
321
471
  },
322
472
  {
323
- displayName: 'Task',
473
+ displayName: 'Task Name',
324
474
  name: 'taskName',
325
- type: 'string',
326
- default: '',
475
+ type: 'resourceLocator',
476
+ default: { mode: 'list', value: '' },
327
477
  displayOptions: {
328
478
  show: logOperationDisplay,
329
479
  },
330
- description: 'Optional Tracira task name',
480
+ description: 'Optional. Select an existing task or enter a new name (e.g. "Tone Validator", "Reply Generator").',
481
+ modes: [
482
+ {
483
+ displayName: 'From List',
484
+ name: 'list',
485
+ type: 'list',
486
+ typeOptions: {
487
+ searchListMethod: 'getTasks',
488
+ searchable: true,
489
+ },
490
+ },
491
+ {
492
+ displayName: 'Name',
493
+ name: 'name',
494
+ type: 'string',
495
+ },
496
+ ],
331
497
  },
332
498
  {
333
- displayName: 'Model',
499
+ displayName: 'AI Model',
334
500
  name: 'modelName',
335
501
  type: 'string',
336
502
  default: '',
337
503
  displayOptions: {
338
504
  show: logOperationDisplay,
339
505
  },
340
- description: 'Optional AI model name to record with the log',
506
+ description: 'Optional. The name of the AI model that produced this output, exactly as you use it — e.g. "gpt-4o", "claude-sonnet-4-5".',
341
507
  },
342
508
  {
343
509
  displayName: 'Wait for Verdict',
@@ -466,24 +632,56 @@ class Tracira {
466
632
  description: 'Filter logs by status',
467
633
  },
468
634
  {
469
- displayName: 'Project',
635
+ displayName: 'Project Name',
470
636
  name: 'projectFilter',
471
- type: 'string',
472
- default: '',
637
+ type: 'resourceLocator',
638
+ default: { mode: 'list', value: '' },
473
639
  displayOptions: {
474
640
  show: getAllDisplay,
475
641
  },
476
- description: 'Filter logs to a specific project name',
642
+ description: 'Optional. Filter logs to a specific project name.',
643
+ modes: [
644
+ {
645
+ displayName: 'From List',
646
+ name: 'list',
647
+ type: 'list',
648
+ typeOptions: {
649
+ searchListMethod: 'getProjects',
650
+ searchable: true,
651
+ },
652
+ },
653
+ {
654
+ displayName: 'Name',
655
+ name: 'name',
656
+ type: 'string',
657
+ },
658
+ ],
477
659
  },
478
660
  {
479
- displayName: 'Task',
661
+ displayName: 'Task Name',
480
662
  name: 'taskFilter',
481
- type: 'string',
482
- default: '',
663
+ type: 'resourceLocator',
664
+ default: { mode: 'list', value: '' },
483
665
  displayOptions: {
484
666
  show: getAllDisplay,
485
667
  },
486
- description: 'Filter logs to a specific task name',
668
+ description: 'Optional. Filter logs to a specific task name within a project.',
669
+ modes: [
670
+ {
671
+ displayName: 'From List',
672
+ name: 'list',
673
+ type: 'list',
674
+ typeOptions: {
675
+ searchListMethod: 'getTasks',
676
+ searchable: true,
677
+ },
678
+ },
679
+ {
680
+ displayName: 'Name',
681
+ name: 'name',
682
+ type: 'string',
683
+ },
684
+ ],
487
685
  },
488
686
  {
489
687
  displayName: 'Search Query',
@@ -496,7 +694,7 @@ class Tracira {
496
694
  description: 'Search across project, task, model, and context IDs',
497
695
  },
498
696
  {
499
- displayName: 'From',
697
+ displayName: 'From Date',
500
698
  name: 'from',
501
699
  type: 'dateTime',
502
700
  default: '',
@@ -506,7 +704,7 @@ class Tracira {
506
704
  description: 'Only include logs at or after this date',
507
705
  },
508
706
  {
509
- displayName: 'To',
707
+ displayName: 'To Date',
510
708
  name: 'to',
511
709
  type: 'dateTime',
512
710
  default: '',
@@ -642,8 +840,15 @@ class Tracira {
642
840
  },
643
841
  ],
644
842
  };
843
+ this.methods = {
844
+ listSearch: {
845
+ getProjects: getProjects_1.getProjects,
846
+ getTasks: getTasks_1.getTasks,
847
+ },
848
+ };
645
849
  }
646
850
  async execute() {
851
+ var _a, _b;
647
852
  const items = this.getInputData();
648
853
  const returnData = [];
649
854
  for (let itemIndex = 0; itemIndex < items.length; itemIndex++) {
@@ -664,15 +869,45 @@ class Tracira {
664
869
  });
665
870
  }
666
871
  }
872
+ const attachmentsParam = this.getNodeParameter('attachments', itemIndex, {});
873
+ const attachmentRows = (_a = attachmentsParam.attachment) !== null && _a !== void 0 ? _a : [];
874
+ const attachments = [];
875
+ for (const row of attachmentRows) {
876
+ if (row.source === 'upload') {
877
+ const binaryProperty = row.binaryProperty || 'data';
878
+ const binary = this.helpers.assertBinaryData(itemIndex, binaryProperty);
879
+ const buffer = await this.helpers.getBinaryDataBuffer(itemIndex, binaryProperty);
880
+ attachments.push(stripEmpty({
881
+ source: 'upload',
882
+ data: buffer.toString('base64'),
883
+ filename: row.filename || binary.fileName || 'file',
884
+ }));
885
+ continue;
886
+ }
887
+ const entry = stripEmpty({
888
+ source: row.source,
889
+ key: row.key,
890
+ url: row.url,
891
+ filename: row.filename,
892
+ });
893
+ if (entry.key !== undefined || entry.url !== undefined) {
894
+ attachments.push(entry);
895
+ }
896
+ }
667
897
  requestOptions = {
668
898
  method: 'POST',
669
899
  url: `${baseUrl}/logs`,
670
900
  body: stripEmpty({
671
- project: this.getNodeParameter('projectName', itemIndex),
901
+ project: this.getNodeParameter('projectName', itemIndex, '', {
902
+ extractValue: true,
903
+ }),
672
904
  output: this.getNodeParameter('output', itemIndex),
673
905
  input: this.getNodeParameter('input', itemIndex, ''),
674
- task: this.getNodeParameter('taskName', itemIndex, ''),
906
+ task: this.getNodeParameter('taskName', itemIndex, '', {
907
+ extractValue: true,
908
+ }),
675
909
  model: this.getNodeParameter('modelName', itemIndex, ''),
910
+ attachments: attachments.length ? attachments : undefined,
676
911
  actorId: options.actorId,
677
912
  callbackUrl: options.callbackUrl,
678
913
  callbackEvents: options.callbackEvents,
@@ -696,15 +931,19 @@ class Tracira {
696
931
  url: `${baseUrl}/logs/${encodeURIComponent(logId)}`,
697
932
  };
698
933
  }
699
- else if (resource === 'log' && operation === 'getAll') {
934
+ else if (resource === 'log' && operation === 'search') {
700
935
  const filters = this.getNodeParameter('filters', itemIndex, {});
701
936
  requestOptions = {
702
937
  method: 'GET',
703
938
  url: `${baseUrl}/logs`,
704
939
  qs: stripEmpty({
705
940
  status: this.getNodeParameter('status', itemIndex, ''),
706
- project: this.getNodeParameter('projectFilter', itemIndex, ''),
707
- task: this.getNodeParameter('taskFilter', itemIndex, ''),
941
+ project: this.getNodeParameter('projectFilter', itemIndex, '', {
942
+ extractValue: true,
943
+ }),
944
+ task: this.getNodeParameter('taskFilter', itemIndex, '', {
945
+ extractValue: true,
946
+ }),
708
947
  q: this.getNodeParameter('query', itemIndex, ''),
709
948
  from: this.getNodeParameter('from', itemIndex, ''),
710
949
  to: this.getNodeParameter('to', itemIndex, ''),
@@ -723,7 +962,7 @@ class Tracira {
723
962
  ? this.getNodeParameter('comment', itemIndex, '')
724
963
  : '';
725
964
  if (decision === 'changed' && !comment.trim()) {
726
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Comment is required when Decision is Changed', { itemIndex });
965
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Comment is required when Decision is Send Back for Changes', { itemIndex });
727
966
  }
728
967
  requestOptions = {
729
968
  method: 'PATCH',
@@ -746,13 +985,48 @@ class Tracira {
746
985
  }),
747
986
  };
748
987
  }
988
+ else if (resource === 'log' && operation === 'upload') {
989
+ const binaryPropertyName = this.getNodeParameter('binaryPropertyName', itemIndex, 'data');
990
+ const fileNameOverride = this.getNodeParameter('uploadFileName', itemIndex, '');
991
+ const contentTypeOverride = this.getNodeParameter('uploadContentType', itemIndex, '');
992
+ const binary = this.helpers.assertBinaryData(itemIndex, binaryPropertyName);
993
+ const buffer = await this.helpers.getBinaryDataBuffer(itemIndex, binaryPropertyName);
994
+ const filename = fileNameOverride || binary.fileName || 'file';
995
+ const presign = (await this.helpers.httpRequestWithAuthentication.call(this, 'traciraApi', {
996
+ method: 'POST',
997
+ url: `${baseUrl}/uploads`,
998
+ body: stripEmpty({
999
+ filename,
1000
+ contentType: contentTypeOverride || binary.mimeType,
1001
+ sizeBytes: buffer.length,
1002
+ }),
1003
+ }));
1004
+ const uploadUrl = presign.uploadUrl;
1005
+ const key = presign.key;
1006
+ const contentType = (_b = presign.contentType) !== null && _b !== void 0 ? _b : (contentTypeOverride || binary.mimeType);
1007
+ if (!uploadUrl || !key) {
1008
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Tracira did not return an upload URL', { itemIndex });
1009
+ }
1010
+ await this.helpers.httpRequest({
1011
+ method: 'PUT',
1012
+ url: uploadUrl,
1013
+ body: buffer,
1014
+ headers: { 'Content-Type': contentType },
1015
+ json: false,
1016
+ });
1017
+ returnData.push({
1018
+ json: { key, contentType },
1019
+ pairedItem: itemIndex,
1020
+ });
1021
+ continue;
1022
+ }
749
1023
  else if (resource === 'api' && operation === 'call') {
750
- const headers = parseJsonObject(this.getNodeParameter('apiHeadersJson', itemIndex, '{}'), 'Headers JSON');
751
- const qs = parseJsonObject(this.getNodeParameter('apiQueryJson', itemIndex, '{}'), 'Query String JSON');
1024
+ const headers = parseJsonObject(this.getNodeParameter('apiHeadersJson', itemIndex, '{}'), 'Headers JSON', this.getNode());
1025
+ const qs = parseJsonObject(this.getNodeParameter('apiQueryJson', itemIndex, '{}'), 'Query String JSON', this.getNode());
752
1026
  const body = parseOptionalJsonBody(this.getNodeParameter('apiBody', itemIndex, ''));
753
1027
  requestOptions = {
754
1028
  method: this.getNodeParameter('apiMethod', itemIndex),
755
- url: `${baseUrl}${normalizeApiPath(this.getNodeParameter('apiPath', itemIndex))}`,
1029
+ url: `${baseUrl}${normalizeApiPath(this.getNodeParameter('apiPath', itemIndex), this.getNode())}`,
756
1030
  headers,
757
1031
  qs,
758
1032
  body,
@@ -765,7 +1039,7 @@ class Tracira {
765
1039
  });
766
1040
  }
767
1041
  const response = await this.helpers.httpRequestWithAuthentication.call(this, 'traciraApi', requestOptions);
768
- if (resource === 'log' && operation === 'getAll' && Array.isArray(response === null || response === void 0 ? void 0 : response.executions)) {
1042
+ if (resource === 'log' && operation === 'search' && Array.isArray(response === null || response === void 0 ? void 0 : response.executions)) {
769
1043
  for (const log of response.executions) {
770
1044
  returnData.push({
771
1045
  json: log,