n8n-nodes-tareno 1.3.0 → 1.3.1

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.
@@ -30,26 +30,10 @@ class Tareno {
30
30
  type: 'options',
31
31
  noDataExpression: true,
32
32
  options: [
33
- {
34
- name: 'Post',
35
- value: 'post',
36
- description: 'Create and manage social media posts',
37
- },
38
- {
39
- name: 'Media Library',
40
- value: 'media',
41
- description: 'Send content to Tareno Media Library',
42
- },
43
- {
44
- name: 'Account',
45
- value: 'account',
46
- description: 'Get connected social media accounts',
47
- },
48
- {
49
- name: 'Usage',
50
- value: 'usage',
51
- description: 'Get API usage statistics',
52
- },
33
+ { name: 'Post', value: 'post', description: 'Create and manage social media posts' },
34
+ { name: 'Media Library', value: 'media', description: 'Send content to Tareno Media Library' },
35
+ { name: 'Account', value: 'account', description: 'Get connected social media accounts' },
36
+ { name: 'Usage', value: 'usage', description: 'Get API usage statistics' },
53
37
  ],
54
38
  default: 'post',
55
39
  },
@@ -61,63 +45,34 @@ class Tareno {
61
45
  name: 'operation',
62
46
  type: 'options',
63
47
  noDataExpression: true,
64
- displayOptions: {
65
- show: {
66
- resource: ['post'],
67
- },
68
- },
48
+ displayOptions: { show: { resource: ['post'] } },
69
49
  options: [
70
- {
71
- name: 'Publish',
72
- value: 'publish',
73
- description: 'Publish a post immediately',
74
- action: 'Publish a post',
75
- },
76
- {
77
- name: 'Schedule',
78
- value: 'schedule',
79
- description: 'Schedule a post for later',
80
- action: 'Schedule a post',
81
- },
50
+ { name: 'Publish', value: 'publish', action: 'Publish a post' },
51
+ { name: 'Schedule', value: 'schedule', action: 'Schedule a post' },
82
52
  ],
83
53
  default: 'publish',
84
54
  },
85
- // Account Selection (Dynamic from API)
86
55
  {
87
56
  displayName: 'Account',
88
57
  name: 'accountId',
89
58
  type: 'options',
90
59
  required: true,
91
- typeOptions: {
92
- loadOptionsMethod: 'getAccounts',
93
- },
94
- displayOptions: {
95
- show: {
96
- resource: ['post'],
97
- },
98
- },
60
+ typeOptions: { loadOptionsMethod: 'getAccounts' },
61
+ displayOptions: { show: { resource: ['post'] } },
99
62
  default: '',
100
- description: 'Select a connected social media account',
101
63
  },
102
- // Format Selection for Instagram/Facebook
103
64
  {
104
65
  displayName: 'Format',
105
66
  name: 'format',
106
67
  type: 'options',
107
- displayOptions: {
108
- show: {
109
- resource: ['post'],
110
- },
111
- },
68
+ displayOptions: { show: { resource: ['post'] } },
112
69
  options: [
113
70
  { name: 'Feed Post', value: 'post' },
114
71
  { name: 'Story', value: 'story' },
115
72
  { name: 'Reel', value: 'reel' },
116
73
  ],
117
74
  default: 'post',
118
- description: 'Content format (applies to Instagram/Facebook)',
119
75
  },
120
- // Pinterest Board Selection
121
76
  {
122
77
  displayName: 'Pinterest Board',
123
78
  name: 'pinterestBoard',
@@ -126,96 +81,45 @@ class Tareno {
126
81
  loadOptionsMethod: 'getPinterestBoards',
127
82
  loadOptionsDependsOn: ['accountId'],
128
83
  },
129
- displayOptions: {
130
- show: {
131
- resource: ['post'],
132
- },
133
- },
84
+ displayOptions: { show: { resource: ['post'] } },
134
85
  default: '',
135
- description: 'Select a Pinterest board (only for Pinterest accounts)',
136
86
  },
137
- // Post Text
138
87
  {
139
88
  displayName: 'Text/Caption',
140
89
  name: 'text',
141
90
  type: 'string',
142
- typeOptions: {
143
- rows: 4,
144
- },
145
- displayOptions: {
146
- show: {
147
- resource: ['post'],
148
- },
149
- },
91
+ typeOptions: { rows: 4 },
92
+ displayOptions: { show: { resource: ['post'] } },
150
93
  default: '',
151
- description: 'The text content of your post',
152
94
  },
153
- // Media URLs
154
95
  {
155
96
  displayName: 'Media URLs',
156
97
  name: 'mediaUrls',
157
98
  type: 'string',
158
- typeOptions: {
159
- rows: 2,
160
- },
161
- displayOptions: {
162
- show: {
163
- resource: ['post'],
164
- },
165
- },
99
+ typeOptions: { rows: 2 },
100
+ displayOptions: { show: { resource: ['post'] } },
166
101
  default: '',
167
- description: 'Comma-separated list of media URLs (images/videos)',
102
+ description: 'Comma-separated list of media URLs',
168
103
  },
169
- // Schedule Time (only for schedule operation)
170
104
  {
171
105
  displayName: 'Schedule Time',
172
106
  name: 'scheduledAt',
173
107
  type: 'dateTime',
174
108
  required: true,
175
- displayOptions: {
176
- show: {
177
- resource: ['post'],
178
- operation: ['schedule'],
179
- },
180
- },
109
+ displayOptions: { show: { resource: ['post'], operation: ['schedule'] } },
181
110
  default: '',
182
- description: 'When to publish the post (ISO 8601 format)',
183
111
  },
184
- // Additional Options
185
112
  {
186
113
  displayName: 'Additional Options',
187
114
  name: 'additionalOptions',
188
115
  type: 'collection',
189
116
  placeholder: 'Add Option',
190
- displayOptions: {
191
- show: {
192
- resource: ['post'],
193
- },
194
- },
117
+ displayOptions: { show: { resource: ['post'] } },
195
118
  default: {},
196
119
  options: [
197
- {
198
- displayName: 'YouTube Title',
199
- name: 'youtubeTitle',
200
- type: 'string',
201
- default: '',
202
- description: 'Title for YouTube videos',
203
- },
204
- {
205
- displayName: 'YouTube Description',
206
- name: 'youtubeDescription',
207
- type: 'string',
208
- typeOptions: { rows: 3 },
209
- default: '',
210
- description: 'Description for YouTube videos',
211
- },
212
- {
213
- displayName: 'Pinterest Link',
214
- name: 'pinterestLink',
215
- type: 'string',
216
- default: '',
217
- description: 'URL to link the pin to',
218
- },
120
+ { displayName: 'YouTube Title', name: 'youtubeTitle', type: 'string', default: '' },
121
+ { displayName: 'YouTube Description', name: 'youtubeDescription', type: 'string', typeOptions: { rows: 3 }, default: '' },
122
+ { displayName: 'Pinterest Link', name: 'pinterestLink', type: 'string', default: '' },
219
123
  ],
220
124
  },
221
125
  // ========================
@@ -226,124 +130,68 @@ class Tareno {
226
130
  name: 'operation',
227
131
  type: 'options',
228
132
  noDataExpression: true,
229
- displayOptions: {
230
- show: {
231
- resource: ['media'],
232
- },
233
- },
133
+ displayOptions: { show: { resource: ['media'] } },
234
134
  options: [
235
- {
236
- name: 'Upload',
237
- value: 'upload',
238
- description: 'Upload media to Tareno library',
239
- action: 'Upload to media library',
240
- },
135
+ { name: 'Upload', value: 'upload', action: 'Upload to media library' },
241
136
  ],
242
137
  default: 'upload',
243
138
  },
244
- // Upload Mode
245
139
  {
246
140
  displayName: 'Upload Mode',
247
141
  name: 'uploadMode',
248
142
  type: 'options',
249
- displayOptions: {
250
- show: {
251
- resource: ['media'],
252
- },
253
- },
143
+ displayOptions: { show: { resource: ['media'] } },
254
144
  options: [
255
145
  { name: 'File (Binary)', value: 'file' },
256
146
  { name: 'URL', value: 'url' },
257
147
  ],
258
148
  default: 'file',
259
- description: 'Whether to upload a binary file or provide a URL',
260
149
  },
261
- // Binary Property (when Mode is File)
262
150
  {
263
151
  displayName: 'Input Data Field Name',
264
152
  name: 'binaryPropertyName',
265
153
  type: 'string',
266
154
  default: 'data',
267
155
  required: true,
268
- displayOptions: {
269
- show: {
270
- resource: ['media'],
271
- uploadMode: ['file'],
272
- },
273
- },
274
- description: 'The name of the binary property to upload',
156
+ displayOptions: { show: { resource: ['media'], uploadMode: ['file'] } },
275
157
  },
276
- // Media URL (when Mode is URL)
277
158
  {
278
159
  displayName: 'Media URL',
279
160
  name: 'mediaUrl',
280
161
  type: 'string',
281
162
  required: true,
282
- displayOptions: {
283
- show: {
284
- resource: ['media'],
285
- uploadMode: ['url'],
286
- },
287
- },
163
+ displayOptions: { show: { resource: ['media'], uploadMode: ['url'] } },
288
164
  default: '',
289
- description: 'URL of the media to upload to your library',
290
165
  },
291
- // Media name for library
292
166
  {
293
167
  displayName: 'File Name',
294
168
  name: 'fileName',
295
169
  type: 'string',
296
- displayOptions: {
297
- show: {
298
- resource: ['media'],
299
- },
300
- },
170
+ displayOptions: { show: { resource: ['media'] } },
301
171
  default: '',
302
- description: 'Optional name for the file (e.g., example.jpg)',
303
172
  },
304
173
  // ========================
305
- // ACCOUNT OPERATIONS
174
+ // OTHER RESOURCES
306
175
  // ========================
307
176
  {
308
177
  displayName: 'Operation',
309
178
  name: 'operation',
310
179
  type: 'options',
311
180
  noDataExpression: true,
312
- displayOptions: {
313
- show: {
314
- resource: ['account'],
315
- },
316
- },
181
+ displayOptions: { show: { resource: ['account'] } },
317
182
  options: [
318
- {
319
- name: 'Get All',
320
- value: 'getAll',
321
- description: 'Get all connected accounts',
322
- action: 'Get all accounts',
323
- },
183
+ { name: 'Get All', value: 'getAll', action: 'Get all accounts' },
324
184
  ],
325
185
  default: 'getAll',
326
186
  },
327
- // ========================
328
- // USAGE OPERATIONS
329
- // ========================
330
187
  {
331
188
  displayName: 'Operation',
332
189
  name: 'operation',
333
190
  type: 'options',
334
191
  noDataExpression: true,
335
- displayOptions: {
336
- show: {
337
- resource: ['usage'],
338
- },
339
- },
192
+ displayOptions: { show: { resource: ['usage'] } },
340
193
  options: [
341
- {
342
- name: 'Get Statistics',
343
- value: 'getStats',
344
- description: 'Get API usage statistics',
345
- action: 'Get usage statistics',
346
- },
194
+ { name: 'Get Statistics', value: 'getStats', action: 'Get usage statistics' },
347
195
  ],
348
196
  default: 'getStats',
349
197
  },
@@ -351,7 +199,6 @@ class Tareno {
351
199
  };
352
200
  this.methods = {
353
201
  loadOptions: {
354
- // Dynamically load connected accounts from API
355
202
  async getAccounts() {
356
203
  const credentials = await this.getCredentials('tarenoApi');
357
204
  const baseUrl = credentials.baseUrl || 'https://tareno.co';
@@ -359,58 +206,38 @@ class Tareno {
359
206
  const response = await this.helpers.httpRequest({
360
207
  method: 'GET',
361
208
  url: `${baseUrl}/api/external/accounts`,
362
- headers: {
363
- 'X-Tareno-API-Key': credentials.apiKey,
364
- },
209
+ headers: { 'X-Tareno-API-Key': credentials.apiKey },
365
210
  json: true,
366
211
  });
367
212
  if (response.accounts && Array.isArray(response.accounts)) {
368
- return response.accounts.map((account) => {
369
- const platformName = account.platform.charAt(0).toUpperCase() + account.platform.slice(1);
370
- const displayName = account.username || account.displayName || 'Unknown';
371
- return {
372
- name: `${platformName} - ${displayName}`,
373
- value: account.id,
374
- description: `Platform: ${account.platform}`,
375
- };
376
- });
213
+ return response.accounts.map((account) => ({
214
+ name: `${account.platform.charAt(0).toUpperCase() + account.platform.slice(1)} - ${account.username || account.displayName || 'Unknown'}`,
215
+ value: account.id,
216
+ }));
377
217
  }
378
218
  return [];
379
219
  }
380
220
  catch (error) {
381
- console.error('Failed to load accounts:', error);
382
- return [
383
- {
384
- name: 'Error loading accounts - check API key',
385
- value: '',
386
- },
387
- ];
221
+ return [];
388
222
  }
389
223
  },
390
- // Dynamically load Pinterest boards
391
224
  async getPinterestBoards() {
392
225
  const credentials = await this.getCredentials('tarenoApi');
393
226
  const baseUrl = credentials.baseUrl || 'https://tareno.co';
394
227
  const accountId = this.getNodeParameter('accountId', '');
395
- if (!accountId) {
228
+ if (!accountId)
396
229
  return [{ name: 'Select an account first', value: '' }];
397
- }
398
230
  try {
399
231
  const response = await this.helpers.httpRequest({
400
232
  method: 'GET',
401
233
  url: `${baseUrl}/api/external/pinterest/boards?accountId=${accountId}`,
402
- headers: {
403
- 'X-Tareno-API-Key': credentials.apiKey,
404
- },
234
+ headers: { 'X-Tareno-API-Key': credentials.apiKey },
405
235
  json: true,
406
236
  });
407
237
  if (response.boards && Array.isArray(response.boards)) {
408
- return response.boards.map((board) => ({
409
- name: board.name,
410
- value: board.id,
411
- }));
238
+ return response.boards.map((board) => ({ name: board.name, value: board.id }));
412
239
  }
413
- return [{ name: 'No boards found (or not a Pinterest account)', value: '' }];
240
+ return [{ name: 'No boards found', value: '' }];
414
241
  }
415
242
  catch (error) {
416
243
  return [{ name: 'Not a Pinterest account', value: '' }];
@@ -429,9 +256,6 @@ class Tareno {
429
256
  const resource = this.getNodeParameter('resource', i);
430
257
  const operation = this.getNodeParameter('operation', i);
431
258
  let responseData;
432
- // ========================
433
- // POST RESOURCE
434
- // ========================
435
259
  if (resource === 'post') {
436
260
  const accountId = this.getNodeParameter('accountId', i);
437
261
  const format = this.getNodeParameter('format', i);
@@ -439,42 +263,21 @@ class Tareno {
439
263
  const text = this.getNodeParameter('text', i);
440
264
  const mediaUrlsRaw = this.getNodeParameter('mediaUrls', i);
441
265
  const additionalOptions = this.getNodeParameter('additionalOptions', i);
442
- const mediaUrls = mediaUrlsRaw
443
- ? mediaUrlsRaw.split(',').map(url => url.trim()).filter(Boolean)
444
- : [];
445
- const body = {
446
- accountId,
447
- text,
448
- mediaUrls,
449
- metadata: {
450
- format,
451
- ...additionalOptions,
452
- },
453
- };
454
- // Add Pinterest board if selected
455
- if (pinterestBoard) {
266
+ const mediaUrls = mediaUrlsRaw ? mediaUrlsRaw.split(',').map(url => url.trim()).filter(Boolean) : [];
267
+ const body = { accountId, text, mediaUrls, metadata: { format, ...additionalOptions } };
268
+ if (pinterestBoard)
456
269
  body.metadata.pinterestBoard = pinterestBoard;
457
- }
458
- // Add schedule time if scheduling
459
- if (operation === 'schedule') {
460
- const scheduledAt = this.getNodeParameter('scheduledAt', i);
461
- body.scheduledAt = scheduledAt;
462
- }
270
+ if (operation === 'schedule')
271
+ body.scheduledAt = this.getNodeParameter('scheduledAt', i);
463
272
  responseData = await this.helpers.httpRequest({
464
273
  method: 'POST',
465
274
  url: `${baseUrl}/api/external/publish`,
466
- headers: {
467
- 'Content-Type': 'application/json',
468
- 'X-Tareno-API-Key': credentials.apiKey,
469
- },
275
+ headers: { 'X-Tareno-API-Key': credentials.apiKey },
470
276
  body,
471
277
  json: true,
472
278
  });
473
279
  }
474
- // ========================
475
- // MEDIA LIBRARY RESOURCE
476
- // ========================
477
- if (resource === 'media' && operation === 'upload') {
280
+ else if (resource === 'media' && operation === 'upload') {
478
281
  const uploadMode = this.getNodeParameter('uploadMode', i);
479
282
  const fileName = this.getNodeParameter('fileName', i);
480
283
  if (uploadMode === 'url') {
@@ -482,88 +285,58 @@ class Tareno {
482
285
  responseData = await this.helpers.httpRequest({
483
286
  method: 'POST',
484
287
  url: `${baseUrl}/api/external/media`,
485
- headers: {
486
- 'Content-Type': 'application/json',
487
- 'X-Tareno-API-Key': credentials.apiKey,
488
- },
489
- body: {
490
- mediaUrl,
491
- fileName: fileName || undefined,
492
- },
288
+ headers: { 'X-Tareno-API-Key': credentials.apiKey },
289
+ body: { mediaUrl, fileName: fileName || undefined },
493
290
  json: true,
494
291
  });
495
292
  }
496
293
  else {
497
- // Binary Upload
498
294
  const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
499
295
  const binaryData = this.helpers.assertBinaryData(i, binaryPropertyName);
500
296
  const binaryBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);
501
- // Use FormData for multipart upload
502
- // Note: N8N helpers.httpRequest has native multipart support
503
297
  responseData = await this.helpers.httpRequest({
504
298
  method: 'POST',
505
299
  url: `${baseUrl}/api/external/media`,
506
300
  headers: {
507
301
  'X-Tareno-API-Key': credentials.apiKey,
302
+ 'Content-Type': 'application/octet-stream',
303
+ 'X-File-Name': fileName || binaryData.fileName || 'upload',
304
+ 'X-Content-Type': binaryData.mimeType,
508
305
  },
509
- body: undefined, // ensure body is not set
510
- // @ts-ignore
511
- formData: {
512
- file: {
513
- value: binaryBuffer,
514
- options: {
515
- filename: fileName || binaryData.fileName || 'upload',
516
- contentType: binaryData.mimeType,
517
- },
518
- },
519
- },
520
- json: true,
306
+ body: binaryBuffer,
521
307
  });
308
+ // Parse JSON manually if n8n doesn't do it for non-JSON content types
309
+ if (typeof responseData === 'string') {
310
+ try {
311
+ responseData = JSON.parse(responseData);
312
+ }
313
+ catch (e) { }
314
+ }
522
315
  }
523
316
  }
524
- // ========================
525
- // ACCOUNT RESOURCE
526
- // ========================
527
- if (resource === 'account' && operation === 'getAll') {
317
+ else if (resource === 'account' && operation === 'getAll') {
528
318
  responseData = await this.helpers.httpRequest({
529
319
  method: 'GET',
530
320
  url: `${baseUrl}/api/external/accounts`,
531
- headers: {
532
- 'X-Tareno-API-Key': credentials.apiKey,
533
- },
321
+ headers: { 'X-Tareno-API-Key': credentials.apiKey },
534
322
  json: true,
535
323
  });
536
324
  }
537
- // ========================
538
- // USAGE RESOURCE
539
- // ========================
540
- if (resource === 'usage' && operation === 'getStats') {
325
+ else if (resource === 'usage' && operation === 'getStats') {
541
326
  responseData = await this.helpers.httpRequest({
542
327
  method: 'GET',
543
328
  url: `${baseUrl}/api/external/usage`,
544
- headers: {
545
- 'X-Tareno-API-Key': credentials.apiKey,
546
- },
329
+ headers: { 'X-Tareno-API-Key': credentials.apiKey },
547
330
  json: true,
548
331
  });
549
332
  }
550
- // Add result to output
551
333
  if (responseData) {
552
- if (Array.isArray(responseData)) {
553
- returnData.push(...responseData.map(item => ({ json: item })));
554
- }
555
- else {
556
- returnData.push({ json: responseData });
557
- }
334
+ returnData.push({ json: responseData });
558
335
  }
559
336
  }
560
337
  catch (error) {
561
338
  if (this.continueOnFail()) {
562
- returnData.push({
563
- json: {
564
- error: error.message,
565
- },
566
- });
339
+ returnData.push({ json: { error: error.message } });
567
340
  continue;
568
341
  }
569
342
  throw error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-tareno",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "N8N community nodes for Tareno - Social Media Management Platform",
5
5
  "license": "MIT",
6
6
  "homepage": "https://tareno.co",