@bambuser/n8n-nodes-livecommerce 0.1.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.
@@ -0,0 +1,1432 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BambuserShows = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const resolveOrigin_1 = require("../../lib/resolveOrigin");
6
+ const splitList = (s) => s.split(',').map(t => t.trim()).filter(Boolean);
7
+ const filterEmpty = (obj) => Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== '' && v !== undefined && v !== null));
8
+ const parseBoolOption = (v) => v === 'true' ? true : v === 'false' ? false : undefined;
9
+ const buildOperationHandlers = (ctx, baseUrl) => ({
10
+ // ─── Show ─────────────────────────────────────────────────────────────────
11
+ 'show:get': async (i) => ({
12
+ method: 'GET',
13
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}`,
14
+ }),
15
+ 'show:getMany': async (i) => ({
16
+ method: 'GET',
17
+ url: `${baseUrl}/shows`,
18
+ qs: filterEmpty({
19
+ limit: ctx.getNodeParameter('limit', i, 10),
20
+ after: ctx.getNodeParameter('after', i, ''),
21
+ state: ctx.getNodeParameter('state', i, ''),
22
+ contributor: ctx.getNodeParameter('contributor', i, ''),
23
+ tag: ctx.getNodeParameter('filterTag', i, ''),
24
+ isPublished: ctx.getNodeParameter('isPublished', i, ''),
25
+ isTestShow: ctx.getNodeParameter('isTestShow', i, ''),
26
+ }),
27
+ }),
28
+ 'show:create': async (i) => {
29
+ const fields = ctx.getNodeParameter('fields', i);
30
+ const extra = filterEmpty(fields.values ?? {});
31
+ if (typeof extra.published === 'string')
32
+ extra.published = parseBoolOption(extra.published);
33
+ return {
34
+ method: 'POST',
35
+ url: `${baseUrl}/shows`,
36
+ headers: { 'Content-Type': 'application/json' },
37
+ body: { title: ctx.getNodeParameter('title', i), ...extra },
38
+ };
39
+ },
40
+ 'show:update': async (i) => {
41
+ const showId = ctx.getNodeParameter('showId', i);
42
+ const fields = ctx.getNodeParameter('fields', i);
43
+ const body = filterEmpty(fields.values ?? {});
44
+ if (typeof body.published === 'string')
45
+ body.published = parseBoolOption(body.published);
46
+ if (typeof body.allowArchivedPlayback === 'string')
47
+ body.allowArchivedPlayback = parseBoolOption(body.allowArchivedPlayback);
48
+ return {
49
+ method: 'PATCH',
50
+ url: `${baseUrl}/shows/${showId}`,
51
+ headers: { 'Content-Type': 'application/json' },
52
+ body,
53
+ };
54
+ },
55
+ 'show:delete': async (i) => ({
56
+ method: 'DELETE',
57
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}`,
58
+ qs: { removeMedia: true, removeChatlog: true },
59
+ }),
60
+ 'show:getBroadcasts': async (i) => ({
61
+ method: 'GET',
62
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/broadcasts`,
63
+ }),
64
+ 'show:getChatMessages': async (i) => ({
65
+ method: 'GET',
66
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/chat-messages`,
67
+ qs: filterEmpty({
68
+ limit: ctx.getNodeParameter('limit', i, 100),
69
+ after: ctx.getNodeParameter('after', i, ''),
70
+ }),
71
+ }),
72
+ 'show:sendChatMessage': async (i) => {
73
+ const replyToId = ctx.getNodeParameter('replyToId', i, '');
74
+ return {
75
+ method: 'POST',
76
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/chat-messages`,
77
+ headers: { 'Content-Type': 'application/json' },
78
+ body: filterEmpty({
79
+ userId: ctx.getNodeParameter('userId', i),
80
+ message: ctx.getNodeParameter('message', i),
81
+ status: ctx.getNodeParameter('chatStatus', i, ''),
82
+ ...(replyToId ? { replyTo: { id: replyToId } } : {}),
83
+ }),
84
+ };
85
+ },
86
+ 'show:updateChatMessage': async (i) => ({
87
+ method: 'PATCH',
88
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/chat-messages/${ctx.getNodeParameter('chatMessageId', i)}`,
89
+ headers: { 'Content-Type': 'application/json' },
90
+ body: { status: ctx.getNodeParameter('chatStatus', i) },
91
+ }),
92
+ 'show:getChatTranscripts': async (i) => ({
93
+ method: 'GET',
94
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/chat-transcripts`,
95
+ }),
96
+ 'show:getPinnedComments': async (i) => ({
97
+ method: 'GET',
98
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/pinned-comments`,
99
+ qs: filterEmpty({
100
+ limit: ctx.getNodeParameter('limit', i, 100),
101
+ after: ctx.getNodeParameter('after', i, ''),
102
+ filter: ctx.getNodeParameter('filter', i, ''),
103
+ }),
104
+ }),
105
+ 'show:createPinnedComment': async (i) => ({
106
+ method: 'POST',
107
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/pinned-comments`,
108
+ headers: { 'Content-Type': 'application/json' },
109
+ body: { chatMessage: { id: ctx.getNodeParameter('chatMessageId', i) } },
110
+ }),
111
+ 'show:updatePinnedComment': async (i) => ({
112
+ method: 'PATCH',
113
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/pinned-comments/${ctx.getNodeParameter('pinnedCommentId', i)}`,
114
+ headers: { 'Content-Type': 'application/json' },
115
+ body: { chatMessage: { id: ctx.getNodeParameter('chatMessageId', i) } },
116
+ }),
117
+ 'show:deletePinnedComment': async (i) => ({
118
+ method: 'DELETE',
119
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/pinned-comments/${ctx.getNodeParameter('pinnedCommentId', i)}`,
120
+ }),
121
+ 'show:getHighlights': async (i) => ({
122
+ method: 'GET',
123
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/highlights`,
124
+ qs: filterEmpty({
125
+ limit: ctx.getNodeParameter('limit', i, 100),
126
+ after: ctx.getNodeParameter('after', i, ''),
127
+ filter: ctx.getNodeParameter('filter', i, ''),
128
+ }),
129
+ }),
130
+ 'show:addHighlight': async (i) => {
131
+ const startRel = ctx.getNodeParameter('startRel', i, '');
132
+ return {
133
+ method: 'POST',
134
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/highlights`,
135
+ headers: { 'Content-Type': 'application/json' },
136
+ body: filterEmpty({
137
+ products: splitList(ctx.getNodeParameter('products', i, '')),
138
+ startRel: startRel !== '' ? startRel : undefined,
139
+ }),
140
+ };
141
+ },
142
+ 'show:updateHighlight': async (i) => ({
143
+ method: 'PATCH',
144
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/highlights/${ctx.getNodeParameter('highlightId', i)}`,
145
+ headers: { 'Content-Type': 'application/json' },
146
+ body: { products: splitList(ctx.getNodeParameter('products', i, '')) },
147
+ }),
148
+ 'show:deleteHighlight': async (i) => ({
149
+ method: 'DELETE',
150
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/highlights/${ctx.getNodeParameter('highlightId', i)}`,
151
+ }),
152
+ 'show:getProducts': async (i) => ({
153
+ method: 'GET',
154
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/products`,
155
+ }),
156
+ 'show:addProduct': async (i) => ({
157
+ method: 'POST',
158
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/products`,
159
+ headers: { 'Content-Type': 'application/json' },
160
+ body: { publicUrl: ctx.getNodeParameter('publicUrl', i) },
161
+ }),
162
+ 'show:addProductsBatch': async (i) => ({
163
+ method: 'POST',
164
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/products/batch`,
165
+ headers: { 'Content-Type': 'application/json' },
166
+ body: JSON.parse(ctx.getNodeParameter('productsJson', i)),
167
+ }),
168
+ 'show:reorderProducts': async (i) => ({
169
+ method: 'PATCH',
170
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/products`,
171
+ headers: { 'Content-Type': 'application/json' },
172
+ body: { products: splitList(ctx.getNodeParameter('products', i)) },
173
+ }),
174
+ 'show:removeProduct': async (i) => ({
175
+ method: 'DELETE',
176
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/products/${ctx.getNodeParameter('productId', i)}`,
177
+ }),
178
+ 'show:getAssets': async (i) => ({
179
+ method: 'GET',
180
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/assets`,
181
+ }),
182
+ 'show:deleteAsset': async (i) => ({
183
+ method: 'DELETE',
184
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/assets/${ctx.getNodeParameter('assetId', i)}`,
185
+ }),
186
+ 'show:addChannel': async (i) => ({
187
+ method: 'POST',
188
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/channels`,
189
+ headers: { 'Content-Type': 'application/json' },
190
+ body: { id: ctx.getNodeParameter('channelId', i) },
191
+ }),
192
+ 'show:updateChannels': async (i) => ({
193
+ method: 'PUT',
194
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/channels`,
195
+ headers: { 'Content-Type': 'application/json' },
196
+ body: { data: splitList(ctx.getNodeParameter('channelIds', i)).map(id => ({ id })) },
197
+ }),
198
+ 'show:removeChannel': async (i) => ({
199
+ method: 'DELETE',
200
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/channels/${ctx.getNodeParameter('channelId', i)}`,
201
+ }),
202
+ 'show:addTag': async (i) => ({
203
+ method: 'POST',
204
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/tags`,
205
+ headers: { 'Content-Type': 'application/json' },
206
+ body: { id: ctx.getNodeParameter('tagId', i) },
207
+ }),
208
+ 'show:updateTags': async (i) => ({
209
+ method: 'PUT',
210
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/tags`,
211
+ headers: { 'Content-Type': 'application/json' },
212
+ body: { data: splitList(ctx.getNodeParameter('tagIds', i)).map(id => ({ id })) },
213
+ }),
214
+ 'show:removeTag': async (i) => ({
215
+ method: 'DELETE',
216
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/tags/${ctx.getNodeParameter('tagId', i)}`,
217
+ }),
218
+ 'show:getExamples': async (i) => ({
219
+ method: 'GET',
220
+ url: `${baseUrl}/shows/${ctx.getNodeParameter('showId', i)}/examples`,
221
+ }),
222
+ // ─── Product ──────────────────────────────────────────────────────────────
223
+ 'product:get': async (i) => ({
224
+ method: 'GET',
225
+ url: `${baseUrl}/products/${ctx.getNodeParameter('productId', i)}`,
226
+ }),
227
+ 'product:getMany': async (i) => ({
228
+ method: 'GET',
229
+ url: `${baseUrl}/products`,
230
+ qs: filterEmpty({
231
+ limit: ctx.getNodeParameter('limit', i, 100),
232
+ after: ctx.getNodeParameter('after', i, ''),
233
+ }),
234
+ }),
235
+ 'product:update': async (i) => {
236
+ const fields = ctx.getNodeParameter('fields', i);
237
+ return {
238
+ method: 'PATCH',
239
+ url: `${baseUrl}/products/${ctx.getNodeParameter('productId', i)}`,
240
+ headers: { 'Content-Type': 'application/json' },
241
+ body: filterEmpty(fields.values ?? {}),
242
+ };
243
+ },
244
+ 'product:delete': async (i) => ({
245
+ method: 'DELETE',
246
+ url: `${baseUrl}/products/${ctx.getNodeParameter('productId', i)}`,
247
+ }),
248
+ 'product:getHighlighted': async (i) => ({
249
+ method: 'GET',
250
+ url: `${baseUrl}/products/highlighted`,
251
+ qs: filterEmpty({
252
+ limit: ctx.getNodeParameter('limit', i, 100),
253
+ after: ctx.getNodeParameter('after', i, ''),
254
+ showId: ctx.getNodeParameter('filterShowId', i, ''),
255
+ }),
256
+ }),
257
+ 'product:getHighlightedShows': async (i) => ({
258
+ method: 'GET',
259
+ url: `${baseUrl}/products/highlighted/shows`,
260
+ qs: { productReference: ctx.getNodeParameter('productReference', i) },
261
+ }),
262
+ 'product:getHighlightedShowsByRefs': async (i) => ({
263
+ method: 'GET',
264
+ url: `${baseUrl}/products/highlighted/shows/by-references`,
265
+ qs: { productReference: splitList(ctx.getNodeParameter('productReferences', i)) },
266
+ }),
267
+ 'product:getHighlightedShowsById': async (i) => ({
268
+ method: 'GET',
269
+ url: `${baseUrl}/products/${ctx.getNodeParameter('productId', i)}/highlighted/shows`,
270
+ }),
271
+ // ─── Channel ──────────────────────────────────────────────────────────────
272
+ 'channel:create': async (i) => ({
273
+ method: 'POST',
274
+ url: `${baseUrl}/channels`,
275
+ headers: { 'Content-Type': 'application/json' },
276
+ body: { title: ctx.getNodeParameter('title', i) },
277
+ }),
278
+ 'channel:get': async (i) => ({
279
+ method: 'GET',
280
+ url: `${baseUrl}/channels/${ctx.getNodeParameter('channelId', i)}`,
281
+ }),
282
+ // ─── Tag ──────────────────────────────────────────────────────────────────
283
+ 'tag:getMany': async (i) => ({
284
+ method: 'GET',
285
+ url: `${baseUrl}/tags`,
286
+ qs: filterEmpty({
287
+ limit: ctx.getNodeParameter('limit', i, 100),
288
+ after: ctx.getNodeParameter('after', i, ''),
289
+ }),
290
+ }),
291
+ 'tag:create': async (i) => ({
292
+ method: 'POST',
293
+ url: `${baseUrl}/tags`,
294
+ headers: { 'Content-Type': 'application/json' },
295
+ body: { name: ctx.getNodeParameter('name', i) },
296
+ }),
297
+ 'tag:get': async (i) => ({
298
+ method: 'GET',
299
+ url: `${baseUrl}/tags/${ctx.getNodeParameter('tagId', i)}`,
300
+ }),
301
+ 'tag:update': async (i) => ({
302
+ method: 'PATCH',
303
+ url: `${baseUrl}/tags/${ctx.getNodeParameter('tagId', i)}`,
304
+ headers: { 'Content-Type': 'application/json' },
305
+ body: { name: ctx.getNodeParameter('name', i) },
306
+ }),
307
+ // ─── User ─────────────────────────────────────────────────────────────────
308
+ 'user:getMany': async (i) => ({
309
+ method: 'GET',
310
+ url: `${baseUrl}/users`,
311
+ qs: filterEmpty({
312
+ limit: ctx.getNodeParameter('limit', i, 100),
313
+ after: ctx.getNodeParameter('after', i, ''),
314
+ id: ctx.getNodeParameter('filterUserId', i, ''),
315
+ email: ctx.getNodeParameter('email', i, ''),
316
+ externalReferenceId: ctx.getNodeParameter('externalReferenceId', i, ''),
317
+ }),
318
+ }),
319
+ 'user:invite': async (i) => ({
320
+ method: 'POST',
321
+ url: `${baseUrl}/users`,
322
+ headers: { 'Content-Type': 'application/json' },
323
+ body: filterEmpty({
324
+ email: ctx.getNodeParameter('email', i),
325
+ displayName: ctx.getNodeParameter('displayName', i),
326
+ fullName: ctx.getNodeParameter('fullName', i, ''),
327
+ roles: splitList(ctx.getNodeParameter('roles', i)),
328
+ externalReferenceId: ctx.getNodeParameter('externalReferenceId', i, ''),
329
+ omitWelcomeEmail: ctx.getNodeParameter('omitWelcomeEmail', i, false),
330
+ }),
331
+ }),
332
+ 'user:update': async (i) => {
333
+ const fields = ctx.getNodeParameter('fields', i);
334
+ const body = filterEmpty(fields.values ?? {});
335
+ if (typeof body.roles === 'string')
336
+ body.roles = splitList(body.roles);
337
+ return {
338
+ method: 'PATCH',
339
+ url: `${baseUrl}/users/${ctx.getNodeParameter('userId', i)}`,
340
+ headers: { 'Content-Type': 'application/json' },
341
+ body,
342
+ };
343
+ },
344
+ 'user:delete': async (i) => ({
345
+ method: 'DELETE',
346
+ url: `${baseUrl}/users/${ctx.getNodeParameter('userId', i)}`,
347
+ }),
348
+ 'user:getAssets': async (i) => ({
349
+ method: 'GET',
350
+ url: `${baseUrl}/users/${ctx.getNodeParameter('userId', i)}/assets`,
351
+ }),
352
+ 'user:deleteAsset': async (i) => ({
353
+ method: 'DELETE',
354
+ url: `${baseUrl}/users/${ctx.getNodeParameter('userId', i)}/assets/${ctx.getNodeParameter('assetId', i)}`,
355
+ }),
356
+ // ─── Stats ────────────────────────────────────────────────────────────────
357
+ 'stats:getShow': async (i) => ({
358
+ method: 'GET',
359
+ url: `${baseUrl}/stats/show/${ctx.getNodeParameter('showId', i)}`,
360
+ }),
361
+ 'stats:getShows': async (i) => ({
362
+ method: 'GET',
363
+ url: `${baseUrl}/stats/shows`,
364
+ qs: filterEmpty({ from: ctx.getNodeParameter('from', i, ''), to: ctx.getNodeParameter('to', i, '') }),
365
+ }),
366
+ 'stats:getActivity': async (i) => ({
367
+ method: 'GET',
368
+ url: `${baseUrl}/stats/activity`,
369
+ qs: filterEmpty({ from: ctx.getNodeParameter('from', i, ''), to: ctx.getNodeParameter('to', i, '') }),
370
+ }),
371
+ 'stats:getShowOrders': async (i) => ({
372
+ method: 'GET',
373
+ url: `${baseUrl}/stats/show/${ctx.getNodeParameter('showId', i)}/orders`,
374
+ qs: filterEmpty({ limit: ctx.getNodeParameter('limit', i, 10), after: ctx.getNodeParameter('after', i, '') }),
375
+ }),
376
+ 'stats:getShowsOrders': async (i) => ({
377
+ method: 'GET',
378
+ url: `${baseUrl}/stats/shows/orders`,
379
+ qs: filterEmpty({ from: ctx.getNodeParameter('from', i, ''), to: ctx.getNodeParameter('to', i, ''), limit: ctx.getNodeParameter('limit', i, 10), after: ctx.getNodeParameter('after', i, '') }),
380
+ }),
381
+ 'stats:getActivityOrders': async (i) => ({
382
+ method: 'GET',
383
+ url: `${baseUrl}/stats/activity/orders`,
384
+ qs: filterEmpty({ from: ctx.getNodeParameter('from', i, ''), to: ctx.getNodeParameter('to', i, ''), limit: ctx.getNodeParameter('limit', i, 10), after: ctx.getNodeParameter('after', i, '') }),
385
+ }),
386
+ 'stats:getShowTraffic': async (i) => ({
387
+ method: 'GET',
388
+ url: `${baseUrl}/stats/show/${ctx.getNodeParameter('showId', i)}/traffic-acquisition`,
389
+ }),
390
+ 'stats:getShowsTraffic': async (i) => ({
391
+ method: 'GET',
392
+ url: `${baseUrl}/stats/traffic-acquisition`,
393
+ qs: filterEmpty({ from: ctx.getNodeParameter('from', i, ''), to: ctx.getNodeParameter('to', i, '') }),
394
+ }),
395
+ // ─── Webhook ──────────────────────────────────────────────────────────────
396
+ 'webhook:create': async (i) => ({
397
+ method: 'POST',
398
+ url: `${baseUrl}/webhooks`,
399
+ headers: { 'Content-Type': 'application/json' },
400
+ body: {
401
+ name: ctx.getNodeParameter('name', i),
402
+ url: ctx.getNodeParameter('webhookUrl', i),
403
+ topics: splitList(ctx.getNodeParameter('webhookTopics', i)),
404
+ headers: {},
405
+ },
406
+ }),
407
+ 'webhook:getEvent': async (i) => ({
408
+ method: 'GET',
409
+ url: `${baseUrl}/webhooks/${ctx.getNodeParameter('eventId', i)}`,
410
+ }),
411
+ // ─── Broadcast ────────────────────────────────────────────────────────────
412
+ 'broadcast:download': async (i) => ({
413
+ method: 'GET',
414
+ url: `${baseUrl}/broadcasts/${ctx.getNodeParameter('broadcastId', i)}/download`,
415
+ qs: filterEmpty({ format: ctx.getNodeParameter('downloadFormat', i, '') }),
416
+ }),
417
+ 'broadcast:getTranscriptions': async (i) => ({
418
+ method: 'GET',
419
+ url: `${baseUrl}/broadcasts/${ctx.getNodeParameter('broadcastId', i)}/transcriptions`,
420
+ qs: filterEmpty({ cursor: ctx.getNodeParameter('transcriptionCursor', i, '') }),
421
+ }),
422
+ });
423
+ // ─── Shared displayOptions helpers ────────────────────────────────────────────
424
+ // Show operations that require a single showId path param
425
+ const SHOW_ID_OPS = [
426
+ 'get', 'update', 'delete', 'getBroadcasts',
427
+ 'getChatMessages', 'sendChatMessage', 'updateChatMessage', 'getChatTranscripts',
428
+ 'getPinnedComments', 'createPinnedComment', 'updatePinnedComment', 'deletePinnedComment',
429
+ 'getHighlights', 'addHighlight', 'updateHighlight', 'deleteHighlight',
430
+ 'getProducts', 'addProduct', 'addProductsBatch', 'reorderProducts', 'removeProduct',
431
+ 'getAssets', 'deleteAsset',
432
+ 'addChannel', 'updateChannels', 'removeChannel',
433
+ 'addTag', 'updateTags', 'removeTag',
434
+ 'getExamples',
435
+ ];
436
+ const STATS_SHOW_ID_OPS = ['getShow', 'getShowOrders', 'getShowTraffic'];
437
+ class BambuserShows {
438
+ description = {
439
+ // `displayName` is the UI label and may follow public product branding freely.
440
+ // `name` is the persisted node type (`<package>.<name>`) baked into every saved
441
+ // workflow — changing it breaks existing flows, so it is frozen to the internal
442
+ // concept (shows) and must NOT track marketing renames.
443
+ displayName: 'Bambuser Live',
444
+ name: 'bambuserShows',
445
+ icon: 'file:bambuser-live.svg',
446
+ group: ['transform'],
447
+ version: 1,
448
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
449
+ description: 'Interact with the Bambuser Live API',
450
+ defaults: { name: 'Bambuser Live' },
451
+ inputs: ['main'],
452
+ outputs: ['main'],
453
+ credentials: [{ name: 'bambuserApi', required: true }],
454
+ properties: [
455
+ // ── Resource ───────────────────────────────────────────────────────────
456
+ {
457
+ displayName: 'Resource',
458
+ name: 'resource',
459
+ type: 'options',
460
+ noDataExpression: true,
461
+ options: [
462
+ { name: 'Broadcast', value: 'broadcast' },
463
+ { name: 'Channel', value: 'channel' },
464
+ { name: 'Product', value: 'product' },
465
+ { name: 'Show', value: 'show' },
466
+ { name: 'Stat', value: 'stats' },
467
+ { name: 'Tag', value: 'tag' },
468
+ { name: 'User', value: 'user' },
469
+ { name: 'Webhook', value: 'webhook' },
470
+ ],
471
+ default: 'show',
472
+ },
473
+ // ── Operation: Broadcast ───────────────────────────────────────────────
474
+ {
475
+ displayName: 'Operation',
476
+ name: 'operation',
477
+ type: 'options',
478
+ noDataExpression: true,
479
+ displayOptions: { show: { resource: ['broadcast'] } },
480
+ options: [
481
+ { name: 'Download', value: 'download', action: 'Get a download link for a broadcast recording' },
482
+ { name: 'Get Transcriptions', value: 'getTranscriptions', action: 'Get transcriptions for a broadcast' },
483
+ ],
484
+ default: 'download',
485
+ },
486
+ // ── Operation: Show ────────────────────────────────────────────────────
487
+ {
488
+ displayName: 'Operation',
489
+ name: 'operation',
490
+ type: 'options',
491
+ noDataExpression: true,
492
+ displayOptions: { show: { resource: ['show'] } },
493
+ options: [
494
+ { name: 'Add Channel', value: 'addChannel', action: 'Add a channel to a show' },
495
+ { name: 'Add Highlight', value: 'addHighlight', action: 'Add a product highlight to a show' },
496
+ { name: 'Add Product', value: 'addProduct', action: 'Add a product to a show' },
497
+ { name: 'Add Products Batch', value: 'addProductsBatch', action: 'Add up to 100 products to a show' },
498
+ { name: 'Add Tag', value: 'addTag', action: 'Add a tag to a show' },
499
+ { name: 'Create', value: 'create', action: 'Create a show' },
500
+ { name: 'Create Pinned Comment', value: 'createPinnedComment', action: 'Create a pinned comment' },
501
+ { name: 'Delete', value: 'delete', action: 'Delete a show' },
502
+ { name: 'Delete Asset', value: 'deleteAsset', action: 'Delete a show asset' },
503
+ { name: 'Delete Highlight', value: 'deleteHighlight', action: 'Delete a highlight from a show' },
504
+ { name: 'Delete Pinned Comment', value: 'deletePinnedComment', action: 'Delete a pinned comment' },
505
+ { name: 'Get', value: 'get', action: 'Get a show by ID' },
506
+ { name: 'Get Assets', value: 'getAssets', action: 'List show assets' },
507
+ { name: 'Get Broadcasts', value: 'getBroadcasts', action: 'Get broadcasts for a show' },
508
+ { name: 'Get Chat Messages', value: 'getChatMessages', action: 'Get chat messages for a show' },
509
+ { name: 'Get Chat Transcripts', value: 'getChatTranscripts', action: 'Get chat transcripts for a show' },
510
+ { name: 'Get Examples', value: 'getExamples', action: 'Get demo embed URL for a show' },
511
+ { name: 'Get Highlights', value: 'getHighlights', action: 'Get highlights for a show' },
512
+ { name: 'Get Many', value: 'getMany', action: 'List shows' },
513
+ { name: 'Get Pinned Comments', value: 'getPinnedComments', action: 'Get pinned comments for a show' },
514
+ { name: 'Get Products', value: 'getProducts', action: 'Get products in a show' },
515
+ { name: 'Remove Channel', value: 'removeChannel', action: 'Remove a channel from a show' },
516
+ { name: 'Remove Product', value: 'removeProduct', action: 'Remove a product from a show' },
517
+ { name: 'Remove Tag', value: 'removeTag', action: 'Remove a tag from a show' },
518
+ { name: 'Reorder Products', value: 'reorderProducts', action: 'Reorder products in a show' },
519
+ { name: 'Send Chat Message', value: 'sendChatMessage', action: 'Send a chat message to a show' },
520
+ { name: 'Update', value: 'update', action: 'Update a show' },
521
+ { name: 'Update Channels', value: 'updateChannels', action: 'Replace all channels on a show' },
522
+ { name: 'Update Chat Message', value: 'updateChatMessage', action: 'Update a chat message status' },
523
+ { name: 'Update Highlight', value: 'updateHighlight', action: 'Update highlight products' },
524
+ { name: 'Update Pinned Comment', value: 'updatePinnedComment', action: 'Update a pinned comment' },
525
+ { name: 'Update Tags', value: 'updateTags', action: 'Replace all tags on a show' },
526
+ ],
527
+ default: 'getMany',
528
+ },
529
+ // ── Operation: Product ─────────────────────────────────────────────────
530
+ {
531
+ displayName: 'Operation',
532
+ name: 'operation',
533
+ type: 'options',
534
+ noDataExpression: true,
535
+ displayOptions: { show: { resource: ['product'] } },
536
+ options: [
537
+ { name: 'Delete', value: 'delete', action: 'Delete a product' },
538
+ { name: 'Get', value: 'get', action: 'Get a product by ID' },
539
+ { name: 'Get Highlighted', value: 'getHighlighted', action: 'List highlighted products' },
540
+ { name: 'Get Highlighted Shows By ID', value: 'getHighlightedShowsById', action: 'Get show appearances for a product by internal ID' },
541
+ { name: 'Get Highlighted Shows By Ref', value: 'getHighlightedShows', action: 'Get show appearances for a product by reference' },
542
+ { name: 'Get Highlighted Shows By Refs', value: 'getHighlightedShowsByRefs', action: 'Get show appearances for multiple product references' },
543
+ { name: 'Get Many', value: 'getMany', action: 'List all products' },
544
+ { name: 'Update', value: 'update', action: 'Update a product' },
545
+ ],
546
+ default: 'getMany',
547
+ },
548
+ // ── Operation: Channel ─────────────────────────────────────────────────
549
+ {
550
+ displayName: 'Operation',
551
+ name: 'operation',
552
+ type: 'options',
553
+ noDataExpression: true,
554
+ displayOptions: { show: { resource: ['channel'] } },
555
+ options: [
556
+ { name: 'Create', value: 'create', action: 'Create a channel' },
557
+ { name: 'Get', value: 'get', action: 'Get a channel by ID' },
558
+ ],
559
+ default: 'get',
560
+ },
561
+ // ── Operation: Tag ─────────────────────────────────────────────────────
562
+ {
563
+ displayName: 'Operation',
564
+ name: 'operation',
565
+ type: 'options',
566
+ noDataExpression: true,
567
+ displayOptions: { show: { resource: ['tag'] } },
568
+ options: [
569
+ { name: 'Create', value: 'create', action: 'Create a tag' },
570
+ { name: 'Get', value: 'get', action: 'Get a tag by ID' },
571
+ { name: 'Get Many', value: 'getMany', action: 'List tags' },
572
+ { name: 'Update', value: 'update', action: 'Update a tag' },
573
+ ],
574
+ default: 'getMany',
575
+ },
576
+ // ── Operation: User ────────────────────────────────────────────────────
577
+ {
578
+ displayName: 'Operation',
579
+ name: 'operation',
580
+ type: 'options',
581
+ noDataExpression: true,
582
+ displayOptions: { show: { resource: ['user'] } },
583
+ options: [
584
+ { name: 'Delete', value: 'delete', action: 'Remove a user' },
585
+ { name: 'Delete Asset', value: 'deleteAsset', action: 'Delete a user asset' },
586
+ { name: 'Get Assets', value: 'getAssets', action: 'List user assets' },
587
+ { name: 'Get Many', value: 'getMany', action: 'List users' },
588
+ { name: 'Invite', value: 'invite', action: 'Invite a user' },
589
+ { name: 'Update', value: 'update', action: 'Update user data' },
590
+ ],
591
+ default: 'getMany',
592
+ },
593
+ // ── Operation: Stats ───────────────────────────────────────────────────
594
+ {
595
+ displayName: 'Operation',
596
+ name: 'operation',
597
+ type: 'options',
598
+ noDataExpression: true,
599
+ displayOptions: { show: { resource: ['stats'] } },
600
+ options: [
601
+ { name: 'Get Activity', value: 'getActivity', action: 'Get show activity in a time period' },
602
+ { name: 'Get Activity Orders', value: 'getActivityOrders', action: 'Get orders by activity period' },
603
+ { name: 'Get Show', value: 'getShow', action: 'Get statistics for a show' },
604
+ { name: 'Get Show Orders', value: 'getShowOrders', action: 'Get order data for a show' },
605
+ { name: 'Get Show Traffic', value: 'getShowTraffic', action: 'Get traffic acquisition for a show' },
606
+ { name: 'Get Shows', value: 'getShows', action: 'Get statistics for multiple shows' },
607
+ { name: 'Get Shows Orders', value: 'getShowsOrders', action: 'Get order data for multiple shows' },
608
+ { name: 'Get Shows Traffic', value: 'getShowsTraffic', action: 'Get traffic acquisition for multiple shows' },
609
+ ],
610
+ default: 'getShow',
611
+ },
612
+ // ── Operation: Webhook ─────────────────────────────────────────────────
613
+ {
614
+ displayName: 'Operation',
615
+ name: 'operation',
616
+ type: 'options',
617
+ noDataExpression: true,
618
+ displayOptions: { show: { resource: ['webhook'] } },
619
+ options: [
620
+ { name: 'Create', value: 'create', action: 'Create a webhook subscription' },
621
+ { name: 'Get Event', value: 'getEvent', action: 'Get a webhook event by ID' },
622
+ ],
623
+ default: 'create',
624
+ },
625
+ // ── broadcastId ────────────────────────────────────────────────────────
626
+ {
627
+ displayName: 'Broadcast ID',
628
+ name: 'broadcastId',
629
+ type: 'string',
630
+ required: true,
631
+ default: '',
632
+ displayOptions: { show: { resource: ['broadcast'], operation: ['download', 'getTranscriptions'] } },
633
+ },
634
+ {
635
+ displayName: 'Format',
636
+ name: 'downloadFormat',
637
+ type: 'options',
638
+ options: [
639
+ { name: 'MP4 H.264', value: 'MP4H264' },
640
+ { name: 'FLV H.264', value: 'FLVH264' },
641
+ { name: 'Default', value: '' },
642
+ ],
643
+ default: 'MP4H264',
644
+ description: 'Video format for the download link',
645
+ displayOptions: { show: { resource: ['broadcast'], operation: ['download'] } },
646
+ },
647
+ {
648
+ displayName: 'Cursor',
649
+ name: 'transcriptionCursor',
650
+ type: 'string',
651
+ default: '',
652
+ description: 'Pagination cursor from the previous response',
653
+ displayOptions: { show: { resource: ['broadcast'], operation: ['getTranscriptions'] } },
654
+ },
655
+ // ── showId ─────────────────────────────────────────────────────────────
656
+ {
657
+ displayName: 'Show ID',
658
+ name: 'showId',
659
+ type: 'string',
660
+ required: true,
661
+ default: '',
662
+ displayOptions: {
663
+ show: {
664
+ resource: ['show'],
665
+ operation: SHOW_ID_OPS,
666
+ },
667
+ },
668
+ },
669
+ {
670
+ displayName: 'Show ID',
671
+ name: 'showId',
672
+ type: 'string',
673
+ required: true,
674
+ default: '',
675
+ displayOptions: {
676
+ show: {
677
+ resource: ['stats'],
678
+ operation: STATS_SHOW_ID_OPS,
679
+ },
680
+ },
681
+ },
682
+ // ── productId ──────────────────────────────────────────────────────────
683
+ {
684
+ displayName: 'Product ID',
685
+ name: 'productId',
686
+ type: 'string',
687
+ required: true,
688
+ default: '',
689
+ displayOptions: {
690
+ show: {
691
+ resource: ['product'],
692
+ operation: ['get', 'update', 'delete', 'getHighlightedShowsById'],
693
+ },
694
+ },
695
+ },
696
+ {
697
+ displayName: 'Product ID',
698
+ name: 'productId',
699
+ type: 'string',
700
+ required: true,
701
+ default: '',
702
+ displayOptions: {
703
+ show: { resource: ['show'], operation: ['removeProduct'] },
704
+ },
705
+ },
706
+ // ── channelId ──────────────────────────────────────────────────────────
707
+ {
708
+ displayName: 'Channel ID',
709
+ name: 'channelId',
710
+ type: 'string',
711
+ required: true,
712
+ default: '',
713
+ displayOptions: {
714
+ show: {
715
+ resource: ['channel'],
716
+ operation: ['get'],
717
+ },
718
+ },
719
+ },
720
+ {
721
+ displayName: 'Channel ID',
722
+ name: 'channelId',
723
+ type: 'string',
724
+ required: true,
725
+ default: '',
726
+ displayOptions: {
727
+ show: { resource: ['show'], operation: ['addChannel', 'removeChannel'] },
728
+ },
729
+ },
730
+ // ── tagId ──────────────────────────────────────────────────────────────
731
+ {
732
+ displayName: 'Tag ID',
733
+ name: 'tagId',
734
+ type: 'string',
735
+ required: true,
736
+ default: '',
737
+ displayOptions: {
738
+ show: { resource: ['tag'], operation: ['get', 'update'] },
739
+ },
740
+ },
741
+ {
742
+ displayName: 'Tag ID',
743
+ name: 'tagId',
744
+ type: 'string',
745
+ required: true,
746
+ default: '',
747
+ displayOptions: {
748
+ show: { resource: ['show'], operation: ['addTag', 'removeTag'] },
749
+ },
750
+ },
751
+ // ── userId ─────────────────────────────────────────────────────────────
752
+ {
753
+ displayName: 'User ID',
754
+ name: 'userId',
755
+ type: 'string',
756
+ required: true,
757
+ default: '',
758
+ displayOptions: {
759
+ show: { resource: ['user'], operation: ['update', 'delete', 'getAssets', 'deleteAsset'] },
760
+ },
761
+ },
762
+ {
763
+ displayName: 'User ID',
764
+ name: 'userId',
765
+ type: 'string',
766
+ required: true,
767
+ default: '',
768
+ description: 'Bambuser user ID of the message sender',
769
+ displayOptions: {
770
+ show: { resource: ['show'], operation: ['sendChatMessage'] },
771
+ },
772
+ },
773
+ // ── chatMessageId ──────────────────────────────────────────────────────
774
+ {
775
+ displayName: 'Chat Message ID',
776
+ name: 'chatMessageId',
777
+ type: 'string',
778
+ required: true,
779
+ default: '',
780
+ displayOptions: {
781
+ show: { resource: ['show'], operation: ['updateChatMessage', 'createPinnedComment', 'updatePinnedComment'] },
782
+ },
783
+ },
784
+ // ── pinnedCommentId ────────────────────────────────────────────────────
785
+ {
786
+ displayName: 'Pinned Comment ID',
787
+ name: 'pinnedCommentId',
788
+ type: 'string',
789
+ required: true,
790
+ default: '',
791
+ displayOptions: {
792
+ show: { resource: ['show'], operation: ['updatePinnedComment', 'deletePinnedComment'] },
793
+ },
794
+ },
795
+ // ── highlightId ────────────────────────────────────────────────────────
796
+ {
797
+ displayName: 'Highlight ID',
798
+ name: 'highlightId',
799
+ type: 'string',
800
+ required: true,
801
+ default: '',
802
+ displayOptions: {
803
+ show: { resource: ['show'], operation: ['updateHighlight', 'deleteHighlight'] },
804
+ },
805
+ },
806
+ // ── assetId ────────────────────────────────────────────────────────────
807
+ {
808
+ displayName: 'Asset ID',
809
+ name: 'assetId',
810
+ type: 'string',
811
+ required: true,
812
+ default: '',
813
+ displayOptions: {
814
+ show: { resource: ['show'], operation: ['deleteAsset'] },
815
+ },
816
+ },
817
+ {
818
+ displayName: 'Asset ID',
819
+ name: 'assetId',
820
+ type: 'string',
821
+ required: true,
822
+ default: '',
823
+ displayOptions: {
824
+ show: { resource: ['user'], operation: ['deleteAsset'] },
825
+ },
826
+ },
827
+ // ── eventId ────────────────────────────────────────────────────────────
828
+ {
829
+ displayName: 'Event ID',
830
+ name: 'eventId',
831
+ type: 'string',
832
+ required: true,
833
+ default: '',
834
+ displayOptions: { show: { resource: ['webhook'], operation: ['getEvent'] } },
835
+ },
836
+ // ── title ──────────────────────────────────────────────────────────────
837
+ {
838
+ displayName: 'Title',
839
+ name: 'title',
840
+ type: 'string',
841
+ required: true,
842
+ default: '',
843
+ displayOptions: {
844
+ show: { resource: ['show', 'channel'], operation: ['create'] },
845
+ },
846
+ },
847
+ // ── name ───────────────────────────────────────────────────────────────
848
+ {
849
+ displayName: 'Name',
850
+ name: 'name',
851
+ type: 'string',
852
+ required: true,
853
+ default: '',
854
+ displayOptions: {
855
+ show: { resource: ['tag'], operation: ['create', 'update'] },
856
+ },
857
+ },
858
+ // ── limit / after ──────────────────────────────────────────────────────
859
+ {
860
+ displayName: 'Limit',
861
+ name: 'limit',
862
+ type: 'number',
863
+ description: 'Max number of results to return',
864
+ typeOptions: { minValue: 1, maxValue: 100 },
865
+ default: 50,
866
+ displayOptions: {
867
+ show: {
868
+ resource: ['show', 'product', 'tag', 'user', 'stats'],
869
+ operation: ['getMany', 'getChatMessages', 'getPinnedComments', 'getHighlights', 'getHighlighted', 'getShowOrders', 'getShowsOrders', 'getActivityOrders'],
870
+ },
871
+ },
872
+ },
873
+ {
874
+ displayName: 'After Cursor',
875
+ name: 'after',
876
+ type: 'string',
877
+ default: '',
878
+ description: 'Pagination cursor from the previous response "next" field',
879
+ displayOptions: {
880
+ show: {
881
+ resource: ['show', 'product', 'tag', 'user', 'stats'],
882
+ operation: ['getMany', 'getChatMessages', 'getPinnedComments', 'getHighlights', 'getHighlighted', 'getShowOrders', 'getShowsOrders', 'getActivityOrders'],
883
+ },
884
+ },
885
+ },
886
+ // ── from / to ──────────────────────────────────────────────────────────
887
+ {
888
+ displayName: 'From',
889
+ name: 'from',
890
+ type: 'string',
891
+ default: '',
892
+ placeholder: '2024-01-01T00:00:00Z',
893
+ description: 'ISO date string — start of range',
894
+ displayOptions: {
895
+ show: {
896
+ resource: ['stats'],
897
+ operation: ['getShows', 'getActivity', 'getShowsOrders', 'getActivityOrders', 'getShowsTraffic'],
898
+ },
899
+ },
900
+ },
901
+ {
902
+ displayName: 'To',
903
+ name: 'to',
904
+ type: 'string',
905
+ default: '',
906
+ placeholder: '2024-12-31T23:59:59Z',
907
+ description: 'ISO date string — end of range',
908
+ displayOptions: {
909
+ show: {
910
+ resource: ['stats'],
911
+ operation: ['getShows', 'getActivity', 'getShowsOrders', 'getActivityOrders', 'getShowsTraffic'],
912
+ },
913
+ },
914
+ },
915
+ // ── show:getMany filters ───────────────────────────────────────────────
916
+ {
917
+ displayName: 'State',
918
+ name: 'state',
919
+ type: 'options',
920
+ options: [
921
+ { name: 'All', value: '' },
922
+ { name: 'Ended', value: 'ended' },
923
+ { name: 'Live', value: 'live' },
924
+ { name: 'Scheduled', value: 'scheduled' },
925
+ { name: 'Upcoming', value: 'upcoming' },
926
+ ],
927
+ default: '',
928
+ displayOptions: { show: { resource: ['show'], operation: ['getMany'] } },
929
+ },
930
+ {
931
+ displayName: 'Contributor User ID',
932
+ name: 'contributor',
933
+ type: 'string',
934
+ default: '',
935
+ description: 'Filter by contributor user ID',
936
+ displayOptions: { show: { resource: ['show'], operation: ['getMany'] } },
937
+ },
938
+ {
939
+ displayName: 'Tag ID Filter',
940
+ name: 'filterTag',
941
+ type: 'string',
942
+ default: '',
943
+ description: 'Filter shows by tag ID',
944
+ displayOptions: { show: { resource: ['show'], operation: ['getMany'] } },
945
+ },
946
+ {
947
+ displayName: 'Is Published',
948
+ name: 'isPublished',
949
+ type: 'options',
950
+ options: [
951
+ { name: 'Any', value: '' },
952
+ { name: 'Yes', value: 'true' },
953
+ { name: 'No', value: 'false' },
954
+ ],
955
+ default: '',
956
+ displayOptions: { show: { resource: ['show'], operation: ['getMany'] } },
957
+ },
958
+ {
959
+ displayName: 'Is Test Show',
960
+ name: 'isTestShow',
961
+ type: 'options',
962
+ options: [
963
+ { name: 'Any', value: '' },
964
+ { name: 'Yes', value: 'true' },
965
+ { name: 'No', value: 'false' },
966
+ ],
967
+ default: '',
968
+ displayOptions: { show: { resource: ['show'], operation: ['getMany'] } },
969
+ },
970
+ // ── show:create optional fields ────────────────────────────────────────
971
+ {
972
+ displayName: 'Optional Fields',
973
+ name: 'fields',
974
+ type: 'fixedCollection',
975
+ typeOptions: { multipleValues: false },
976
+ default: {},
977
+ displayOptions: { show: { resource: ['show'], operation: ['create'] } },
978
+ options: [
979
+ {
980
+ displayName: 'Values',
981
+ name: 'values',
982
+ values: [
983
+ {
984
+ displayName: 'Allow Archived Playback',
985
+ name: 'allowArchivedPlayback',
986
+ type: 'options',
987
+ options: [
988
+ {
989
+ name: 'True',
990
+ value: 'true',
991
+ },
992
+ {
993
+ name: 'False',
994
+ value: 'false',
995
+ },
996
+ ],
997
+ default: 'true',
998
+ },
999
+ {
1000
+ displayName: 'Description',
1001
+ name: 'description',
1002
+ type: 'string',
1003
+ default: '',
1004
+ },
1005
+ {
1006
+ displayName: 'Is Test Show',
1007
+ name: 'isTestShow',
1008
+ type: 'boolean',
1009
+ default: false,
1010
+ },
1011
+ {
1012
+ displayName: 'Published',
1013
+ name: 'published',
1014
+ type: 'options',
1015
+ options: [
1016
+ {
1017
+ name: 'True',
1018
+ value: 'true',
1019
+ },
1020
+ {
1021
+ name: 'False',
1022
+ value: 'false',
1023
+ },
1024
+ ],
1025
+ default: 'true',
1026
+ },
1027
+ {
1028
+ displayName: 'Scheduled Start At',
1029
+ name: 'scheduledStartAt',
1030
+ type: 'string',
1031
+ default: '',
1032
+ placeholder: '2024-06-01T10:00:00Z',
1033
+ },
1034
+ ],
1035
+ },
1036
+ ],
1037
+ },
1038
+ // ── show:update fields ─────────────────────────────────────────────────
1039
+ {
1040
+ displayName: 'Fields to Update',
1041
+ name: 'fields',
1042
+ type: 'fixedCollection',
1043
+ typeOptions: { multipleValues: false },
1044
+ default: {},
1045
+ displayOptions: { show: { resource: ['show'], operation: ['update'] } },
1046
+ options: [
1047
+ {
1048
+ displayName: 'Values',
1049
+ name: 'values',
1050
+ values: [
1051
+ {
1052
+ displayName: 'Allow Archived Playback',
1053
+ name: 'allowArchivedPlayback',
1054
+ type: 'options',
1055
+ options: [
1056
+ {
1057
+ name: '— No Change —',
1058
+ value: '',
1059
+ },
1060
+ {
1061
+ name: 'True',
1062
+ value: 'true',
1063
+ },
1064
+ {
1065
+ name: 'False',
1066
+ value: 'false',
1067
+ },
1068
+ ],
1069
+ default: '',
1070
+ },
1071
+ {
1072
+ displayName: 'Description',
1073
+ name: 'description',
1074
+ type: 'string',
1075
+ default: '',
1076
+ },
1077
+ {
1078
+ displayName: 'Published',
1079
+ name: 'published',
1080
+ type: 'options',
1081
+ options: [
1082
+ {
1083
+ name: '— No Change —',
1084
+ value: '',
1085
+ },
1086
+ {
1087
+ name: 'True',
1088
+ value: 'true',
1089
+ },
1090
+ {
1091
+ name: 'False',
1092
+ value: 'false',
1093
+ },
1094
+ ],
1095
+ default: '',
1096
+ },
1097
+ {
1098
+ displayName: 'Scheduled Start At',
1099
+ name: 'scheduledStartAt',
1100
+ type: 'string',
1101
+ default: '',
1102
+ placeholder: '2024-06-01T10:00:00Z',
1103
+ },
1104
+ {
1105
+ displayName: 'Title',
1106
+ name: 'title',
1107
+ type: 'string',
1108
+ default: '',
1109
+ },
1110
+ ],
1111
+ },
1112
+ ],
1113
+ },
1114
+ // ── product:update fields ──────────────────────────────────────────────
1115
+ {
1116
+ displayName: 'Fields to Update',
1117
+ name: 'fields',
1118
+ type: 'fixedCollection',
1119
+ typeOptions: { multipleValues: false },
1120
+ default: {},
1121
+ displayOptions: { show: { resource: ['product'], operation: ['update'] } },
1122
+ options: [
1123
+ {
1124
+ displayName: 'Values',
1125
+ name: 'values',
1126
+ values: [
1127
+ { displayName: 'Title', name: 'title', type: 'string', default: '' },
1128
+ { displayName: 'Brand', name: 'brand', type: 'string', default: '' },
1129
+ { displayName: 'Thumbnail URL', name: 'thumbnail', type: 'string', default: '' },
1130
+ { displayName: 'Product Reference', name: 'productReference', type: 'string', default: '' },
1131
+ ],
1132
+ },
1133
+ ],
1134
+ },
1135
+ // ── user:update fields ─────────────────────────────────────────────────
1136
+ {
1137
+ displayName: 'Fields to Update',
1138
+ name: 'fields',
1139
+ type: 'fixedCollection',
1140
+ typeOptions: { multipleValues: false },
1141
+ default: {},
1142
+ displayOptions: { show: { resource: ['user'], operation: ['update'] } },
1143
+ options: [
1144
+ {
1145
+ displayName: 'Values',
1146
+ name: 'values',
1147
+ values: [
1148
+ { displayName: 'Display Name', name: 'displayName', type: 'string', default: '' },
1149
+ { displayName: 'Full Name', name: 'fullName', type: 'string', default: '' },
1150
+ { displayName: 'Roles (Comma-Separated)', name: 'roles', type: 'string', default: '', placeholder: 'admin,host' },
1151
+ { displayName: 'External Reference ID', name: 'externalReferenceId', type: 'string', default: '' },
1152
+ ],
1153
+ },
1154
+ ],
1155
+ },
1156
+ // ── show:sendChatMessage ───────────────────────────────────────────────
1157
+ {
1158
+ displayName: 'Message',
1159
+ name: 'message',
1160
+ type: 'string',
1161
+ required: true,
1162
+ default: '',
1163
+ displayOptions: { show: { resource: ['show'], operation: ['sendChatMessage'] } },
1164
+ },
1165
+ {
1166
+ displayName: 'Status',
1167
+ name: 'chatStatus',
1168
+ type: 'options',
1169
+ options: [
1170
+ { name: 'Published', value: 'published' },
1171
+ { name: 'Unpublished', value: 'unpublished' },
1172
+ ],
1173
+ default: 'published',
1174
+ displayOptions: { show: { resource: ['show'], operation: ['sendChatMessage'] } },
1175
+ },
1176
+ {
1177
+ displayName: 'Reply To Message ID',
1178
+ name: 'replyToId',
1179
+ type: 'string',
1180
+ default: '',
1181
+ description: 'Optional — ID of the message to reply to',
1182
+ displayOptions: { show: { resource: ['show'], operation: ['sendChatMessage'] } },
1183
+ },
1184
+ // ── show:updateChatMessage ─────────────────────────────────────────────
1185
+ {
1186
+ displayName: 'Status',
1187
+ name: 'chatStatus',
1188
+ type: 'options',
1189
+ options: [
1190
+ { name: 'Published', value: 'published' },
1191
+ { name: 'Unpublished', value: 'unpublished' },
1192
+ ],
1193
+ default: 'unpublished',
1194
+ displayOptions: { show: { resource: ['show'], operation: ['updateChatMessage'] } },
1195
+ },
1196
+ // ── getPinnedComments / getHighlights filter ───────────────────────────
1197
+ {
1198
+ displayName: 'Filter',
1199
+ name: 'filter',
1200
+ type: 'options',
1201
+ options: [
1202
+ { name: 'All', value: '' },
1203
+ { name: 'Latest', value: 'latest' },
1204
+ ],
1205
+ default: '',
1206
+ displayOptions: { show: { resource: ['show'], operation: ['getPinnedComments', 'getHighlights'] } },
1207
+ },
1208
+ // ── show:addHighlight / updateHighlight ────────────────────────────────
1209
+ {
1210
+ displayName: 'Product IDs',
1211
+ name: 'products',
1212
+ type: 'string',
1213
+ default: '',
1214
+ placeholder: 'tpl:abc123, tpl:def456',
1215
+ description: 'Comma-separated list of product IDs to highlight',
1216
+ displayOptions: { show: { resource: ['show'], operation: ['addHighlight', 'updateHighlight'] } },
1217
+ },
1218
+ {
1219
+ displayName: 'Start Relative (Seconds)',
1220
+ name: 'startRel',
1221
+ type: 'number',
1222
+ default: '',
1223
+ description: 'Position in archived show (seconds from start). Leave empty for live shows.',
1224
+ displayOptions: { show: { resource: ['show'], operation: ['addHighlight'] } },
1225
+ },
1226
+ // ── show:addProduct ────────────────────────────────────────────────────
1227
+ {
1228
+ displayName: 'Public URL',
1229
+ name: 'publicUrl',
1230
+ type: 'string',
1231
+ required: true,
1232
+ default: '',
1233
+ displayOptions: { show: { resource: ['show'], operation: ['addProduct'] } },
1234
+ },
1235
+ // ── show:addProductsBatch ──────────────────────────────────────────────
1236
+ {
1237
+ displayName: 'Products JSON',
1238
+ name: 'productsJson',
1239
+ type: 'string',
1240
+ required: true,
1241
+ default: '',
1242
+ placeholder: '[{"publicUrl":"https://example.com/product"}]',
1243
+ description: 'JSON array of product objects — each requires at least publicUrl',
1244
+ typeOptions: { rows: 4 },
1245
+ displayOptions: { show: { resource: ['show'], operation: ['addProductsBatch'] } },
1246
+ },
1247
+ // ── show:reorderProducts ───────────────────────────────────────────────
1248
+ {
1249
+ displayName: 'Product IDs',
1250
+ name: 'products',
1251
+ type: 'string',
1252
+ required: true,
1253
+ default: '',
1254
+ placeholder: 'tpl:abc123, tpl:def456',
1255
+ description: 'Comma-separated product IDs in desired order',
1256
+ displayOptions: { show: { resource: ['show'], operation: ['reorderProducts'] } },
1257
+ },
1258
+ // ── show:updateChannels ────────────────────────────────────────────────
1259
+ {
1260
+ displayName: 'Channel IDs',
1261
+ name: 'channelIds',
1262
+ type: 'string',
1263
+ required: true,
1264
+ default: '',
1265
+ placeholder: 'id1, id2',
1266
+ description: 'Comma-separated channel IDs — replaces all current channels',
1267
+ displayOptions: { show: { resource: ['show'], operation: ['updateChannels'] } },
1268
+ },
1269
+ // ── show:updateTags ────────────────────────────────────────────────────
1270
+ {
1271
+ displayName: 'Tag IDs',
1272
+ name: 'tagIds',
1273
+ type: 'string',
1274
+ required: true,
1275
+ default: '',
1276
+ placeholder: 'id1, id2',
1277
+ description: 'Comma-separated tag IDs — replaces all current tags',
1278
+ displayOptions: { show: { resource: ['show'], operation: ['updateTags'] } },
1279
+ },
1280
+ // ── product:getHighlightedShows ────────────────────────────────────────
1281
+ {
1282
+ displayName: 'Product Reference',
1283
+ name: 'productReference',
1284
+ type: 'string',
1285
+ required: true,
1286
+ default: '',
1287
+ description: 'SKU or product reference string',
1288
+ displayOptions: { show: { resource: ['product'], operation: ['getHighlightedShows'] } },
1289
+ },
1290
+ {
1291
+ displayName: 'Product References',
1292
+ name: 'productReferences',
1293
+ type: 'string',
1294
+ required: true,
1295
+ default: '',
1296
+ placeholder: 'sku1, sku2, sku3',
1297
+ description: 'Comma-separated product references (max 20)',
1298
+ displayOptions: { show: { resource: ['product'], operation: ['getHighlightedShowsByRefs'] } },
1299
+ },
1300
+ {
1301
+ displayName: 'Show ID Filter',
1302
+ name: 'filterShowId',
1303
+ type: 'string',
1304
+ default: '',
1305
+ description: 'Optional — filter highlighted products by show ID',
1306
+ displayOptions: { show: { resource: ['product'], operation: ['getHighlighted'] } },
1307
+ },
1308
+ // ── user:getMany filters ───────────────────────────────────────────────
1309
+ {
1310
+ displayName: 'User ID Filter',
1311
+ name: 'filterUserId',
1312
+ type: 'string',
1313
+ default: '',
1314
+ description: 'Filter by exact user ID',
1315
+ displayOptions: { show: { resource: ['user'], operation: ['getMany'] } },
1316
+ },
1317
+ {
1318
+ displayName: 'Email',
1319
+ name: 'email',
1320
+ type: 'string',
1321
+ placeholder: 'name@email.com',
1322
+ default: '',
1323
+ displayOptions: { show: { resource: ['user'], operation: ['getMany'] } },
1324
+ },
1325
+ {
1326
+ displayName: 'External Reference ID',
1327
+ name: 'externalReferenceId',
1328
+ type: 'string',
1329
+ default: '',
1330
+ displayOptions: { show: { resource: ['user'], operation: ['getMany'] } },
1331
+ },
1332
+ // ── user:invite ────────────────────────────────────────────────────────
1333
+ {
1334
+ displayName: 'Email',
1335
+ name: 'email',
1336
+ type: 'string',
1337
+ placeholder: 'name@email.com',
1338
+ required: true,
1339
+ default: '',
1340
+ displayOptions: { show: { resource: ['user'], operation: ['invite'] } },
1341
+ },
1342
+ {
1343
+ displayName: 'Display Name',
1344
+ name: 'displayName',
1345
+ type: 'string',
1346
+ required: true,
1347
+ default: '',
1348
+ displayOptions: { show: { resource: ['user'], operation: ['invite'] } },
1349
+ },
1350
+ {
1351
+ displayName: 'Roles',
1352
+ name: 'roles',
1353
+ type: 'string',
1354
+ required: true,
1355
+ default: 'host',
1356
+ placeholder: 'admin, showCreator, host',
1357
+ description: 'Comma-separated roles',
1358
+ displayOptions: { show: { resource: ['user'], operation: ['invite'] } },
1359
+ },
1360
+ {
1361
+ displayName: 'Full Name',
1362
+ name: 'fullName',
1363
+ type: 'string',
1364
+ default: '',
1365
+ displayOptions: { show: { resource: ['user'], operation: ['invite'] } },
1366
+ },
1367
+ {
1368
+ displayName: 'External Reference ID',
1369
+ name: 'externalReferenceId',
1370
+ type: 'string',
1371
+ default: '',
1372
+ displayOptions: { show: { resource: ['user'], operation: ['invite'] } },
1373
+ },
1374
+ {
1375
+ displayName: 'Omit Welcome Email',
1376
+ name: 'omitWelcomeEmail',
1377
+ type: 'boolean',
1378
+ default: false,
1379
+ displayOptions: { show: { resource: ['user'], operation: ['invite'] } },
1380
+ },
1381
+ // ── webhook:create ─────────────────────────────────────────────────────
1382
+ {
1383
+ displayName: 'Name',
1384
+ name: 'name',
1385
+ type: 'string',
1386
+ required: true,
1387
+ default: '',
1388
+ displayOptions: { show: { resource: ['webhook'], operation: ['create'] } },
1389
+ },
1390
+ {
1391
+ displayName: 'URL',
1392
+ name: 'webhookUrl',
1393
+ type: 'string',
1394
+ required: true,
1395
+ default: '',
1396
+ description: 'HTTPS callback URL for webhook delivery',
1397
+ displayOptions: { show: { resource: ['webhook'], operation: ['create'] } },
1398
+ },
1399
+ {
1400
+ displayName: 'Topics',
1401
+ name: 'webhookTopics',
1402
+ type: 'string',
1403
+ required: true,
1404
+ default: 'show',
1405
+ placeholder: 'show, product, user, product-highlight, broadcast',
1406
+ description: 'Comma-separated list of topics to subscribe to',
1407
+ displayOptions: { show: { resource: ['webhook'], operation: ['create'] } },
1408
+ },
1409
+ ],
1410
+ usableAsTool: true,
1411
+ };
1412
+ async execute() {
1413
+ const items = this.getInputData();
1414
+ const credentials = await this.getCredentials('bambuserApi');
1415
+ const origin = (0, resolveOrigin_1.resolveOrigin)(credentials.baseUrl, credentials.region);
1416
+ const handlers = buildOperationHandlers(this, `${origin}/v1`);
1417
+ const results = await Promise.all(items.map(async (_, i) => {
1418
+ const resource = this.getNodeParameter('resource', i);
1419
+ const operation = this.getNodeParameter('operation', i);
1420
+ const key = `${resource}:${operation}`;
1421
+ const handler = handlers[key];
1422
+ if (!handler) {
1423
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation "${operation}" for resource "${resource}"`, { itemIndex: i });
1424
+ }
1425
+ const requestOptions = await handler(i);
1426
+ const responseData = await this.helpers.httpRequestWithAuthentication.call(this, 'bambuserApi', requestOptions) ?? { success: true };
1427
+ return { json: responseData };
1428
+ }));
1429
+ return [results];
1430
+ }
1431
+ }
1432
+ exports.BambuserShows = BambuserShows;