n8n-nodes-sudomock 0.3.1 → 0.4.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.
package/README.md CHANGED
@@ -16,12 +16,20 @@ n8n community node for the SudoMock API. Integrate mockup rendering into your n8
16
16
  - **Update Mockup**: Update the name of a mockup template
17
17
  - **Delete Mockup**: Delete a specific mockup template
18
18
 
19
+ ### 2D Mockups
20
+ - **2D: Create Mockup**: Create a reusable 2D mockup from an image
21
+ - **2D: Get Mockup**: Check preparation status and get ready print areas
22
+ - **2D: List Mockups**: List your 2D mockups
23
+ - **2D: Set Print Areas**: Define print areas with four-point quads
24
+ - **2D: Render Mockup**: Render artwork into ready print areas for 5 credits
25
+ - **2D: Delete Mockup**: Delete a 2D mockup
26
+
19
27
  ### Rendering
20
28
  - **Render Mockup**: Generate mockups by combining templates with your designs. Optionally run asynchronously with the **Run Asynchronously** toggle, which returns a `job_id` to track with **Get Job**.
21
29
  - **Render Video**: Turn a mockup (or an existing image URL) into a short product video (always asynchronous). Pick a duration valid for the model, optional audio/motion, an optional one-off webhook, and optionally **Wait for Completion** to return the finished clip.
22
30
 
23
31
  ### Async Jobs
24
- - **Get Job**: Get the status and result of an async render, upload, or video job by its `job_id`. Terminal statuses are `succeeded`, `failed`, and `cancelled` (pending jobs report `queued`). On success it surfaces `result_url` (render/video) or `mockup_uuid` (upload). Optionally **Wait for Completion** to poll until the job finishes.
32
+ - **Get Job**: Get the status and result of an async render, upload, video, or 2D mockup job by its `job_id`. Terminal statuses are `succeeded`, `failed`, and `cancelled` (pending jobs report `queued`). On success it surfaces `result_url` (render/video) or `mockup_uuid` (upload and 2D creation). Optionally **Wait for Completion** to poll until the job finishes.
25
33
  - **List Jobs**: List your async render, upload, and video jobs (keyset paginated, with optional `kind` and Mockup UUID filters).
26
34
 
27
35
  ### Webhooks
@@ -267,6 +275,21 @@ Deletion confirmation
267
275
 
268
276
  ---
269
277
 
278
+ ### 2D Mockup Operations
279
+
280
+ Create, prepare, render, and manage reusable mockups from product images without a PSD.
281
+
282
+ 1. **2D: Create Mockup** accepts a public `source_url` or `source_base64`, plus an optional name. Creation is asynchronous and returns the 202 response with `mockup_uuid`, `status_url`, and job details unchanged. Use the job ID with **Get Job** when needed.
283
+ 2. **2D: Get Mockup** returns `draft`, `ready`, or `failed` status. Poll this operation until the mockup is `ready`; the ready response includes each print area's UUID and points.
284
+ 3. **2D: List Mockups** returns your 2D mockups.
285
+ 4. **2D: Set Print Areas** accepts one or more print areas. Each print area is a quad with four `[x, y]` coordinate pairs.
286
+ 5. **2D: Render Mockup** accepts the mockup UUID and one or more ready print area UUIDs. Each print area includes either an artwork URL or Base64 artwork, with optional color, adjustments, and placement. Export options support PNG or JPG at 1024, 2048, or 4096 pixels, plus quality and DPI. Each render costs 5 credits and returns `print_files`, where `print_files[0]` is the CDN URL.
287
+ 6. **2D: Delete Mockup** deletes the selected 2D mockup.
288
+
289
+ Create must reach `ready` through **2D: Get Mockup** before **2D: Render Mockup**.
290
+
291
+ ---
292
+
270
293
  ### Render Video
271
294
 
272
295
  Turn a mockup (or an existing image URL) into a short product video. Always asynchronous: returns a `job_id` you can track with **Get Job**.
@@ -292,10 +315,10 @@ The 202 acknowledgement (`job_id`, `kind`, `status`, `status_url`, `estimated_cr
292
315
 
293
316
  ### Get Job
294
317
 
295
- Track an asynchronous render, upload, or video job by its `job_id`.
318
+ Track an asynchronous render, upload, video, or 2D mockup job by its `job_id`.
296
319
 
297
320
  **Parameters:**
298
- - **Job ID** (required): the `job_id` from an async render, upload, or video request
321
+ - **Job ID** (required): the `job_id` from an async render, upload, video, or 2D mockup request
299
322
  - **Wait for Completion**: poll until a terminal status (`succeeded`, `failed`, `cancelled`)
300
323
  - **Poll Timeout (Seconds)**: max wait when Wait for Completion is on
301
324
 
@@ -35,7 +35,7 @@ class SudoMock {
35
35
  group: ['transform'],
36
36
  version: 1,
37
37
  subtitle: '={{$parameter["operation"]}}',
38
- description: 'Generate mockups and product videos for Print-on-Demand automation. Upload PSDs, render with your designs, render videos, run renders asynchronously, track jobs, and manage webhooks.',
38
+ description: 'Generate PSD and 2D mockups and product videos for Print-on-Demand automation. Upload PSDs, render with your designs, render videos, run renders asynchronously, track jobs, and manage webhooks.',
39
39
  defaults: {
40
40
  name: 'SudoMock',
41
41
  },
@@ -58,6 +58,42 @@ class SudoMock {
58
58
  type: 'options',
59
59
  noDataExpression: true,
60
60
  options: [
61
+ {
62
+ name: '2D: Create Mockup',
63
+ value: 'create2DMockup',
64
+ description: 'Create a 2D mockup asynchronously. Returns a job immediately; use 2D: Get Mockup until status is ready before rendering.',
65
+ action: 'Create a 2D mockup',
66
+ },
67
+ {
68
+ name: '2D: Get Mockup',
69
+ value: 'get2DMockup',
70
+ description: 'Get the status and print areas of a 2D mockup',
71
+ action: 'Get a 2D mockup',
72
+ },
73
+ {
74
+ name: '2D: List Mockups',
75
+ value: 'list2DMockups',
76
+ description: 'List your 2D mockups',
77
+ action: 'List 2D mockups',
78
+ },
79
+ {
80
+ name: '2D: Set Print Areas',
81
+ value: 'set2DPrintAreas',
82
+ description: 'Define print area quads for a 2D mockup',
83
+ action: 'Set 2D print areas',
84
+ },
85
+ {
86
+ name: '2D: Render Mockup',
87
+ value: 'render2DMockup',
88
+ description: 'Render artwork on a 2D mockup for 5 credits',
89
+ action: 'Render a 2D mockup',
90
+ },
91
+ {
92
+ name: '2D: Delete Mockup',
93
+ value: 'delete2DMockup',
94
+ description: 'Delete a 2D mockup',
95
+ action: 'Delete a 2D mockup',
96
+ },
61
97
  {
62
98
  name: 'Delete Mockup',
63
99
  value: 'deleteMockup',
@@ -188,6 +224,493 @@ class SudoMock {
188
224
  default: 'render',
189
225
  },
190
226
  // ============================================
227
+ // 2D MOCKUP PARAMETERS
228
+ // ============================================
229
+ {
230
+ displayName: 'Source Type',
231
+ name: 'twoDSourceMode',
232
+ type: 'options',
233
+ displayOptions: {
234
+ show: {
235
+ operation: ['create2DMockup'],
236
+ },
237
+ },
238
+ options: [
239
+ {
240
+ name: 'Image URL',
241
+ value: 'url',
242
+ description: 'Public image URL for the new 2D mockup',
243
+ },
244
+ {
245
+ name: 'Base64 Image',
246
+ value: 'base64',
247
+ description: 'Base64 image data for the new 2D mockup',
248
+ },
249
+ ],
250
+ default: 'url',
251
+ description: 'Image source for the new 2D mockup',
252
+ },
253
+ {
254
+ displayName: 'Source URL',
255
+ name: 'twoDSourceUrl',
256
+ type: 'string',
257
+ required: true,
258
+ displayOptions: {
259
+ show: {
260
+ operation: ['create2DMockup'],
261
+ twoDSourceMode: ['url'],
262
+ },
263
+ },
264
+ default: '',
265
+ placeholder: 'https://cdn.example.com/product.png',
266
+ description: 'Public image URL for the new 2D mockup',
267
+ },
268
+ {
269
+ displayName: 'Source Base64',
270
+ name: 'twoDSourceBase64',
271
+ type: 'string',
272
+ required: true,
273
+ displayOptions: {
274
+ show: {
275
+ operation: ['create2DMockup'],
276
+ twoDSourceMode: ['base64'],
277
+ },
278
+ },
279
+ default: '',
280
+ description: 'Base64 image data for the new 2D mockup',
281
+ },
282
+ {
283
+ displayName: 'Name',
284
+ name: 'twoDName',
285
+ type: 'string',
286
+ displayOptions: {
287
+ show: {
288
+ operation: ['create2DMockup'],
289
+ },
290
+ },
291
+ default: '',
292
+ placeholder: 'T-Shirt Front',
293
+ description: 'Optional human-readable name for the new 2D mockup',
294
+ },
295
+ {
296
+ displayName: 'Mockup UUID',
297
+ name: 'twoDMockupUuid',
298
+ type: 'string',
299
+ required: true,
300
+ displayOptions: {
301
+ show: {
302
+ operation: [
303
+ 'get2DMockup',
304
+ 'set2DPrintAreas',
305
+ 'render2DMockup',
306
+ 'delete2DMockup',
307
+ ],
308
+ },
309
+ },
310
+ default: '',
311
+ placeholder: 'c315f78f-d2c7-4541-b240-a9372842de94',
312
+ description: 'UUID of the 2D mockup to get, set print areas for, render, or delete',
313
+ },
314
+ {
315
+ displayName: 'Print Areas',
316
+ name: 'twoDSetPrintAreas',
317
+ type: 'fixedCollection',
318
+ typeOptions: {
319
+ multipleValues: true,
320
+ },
321
+ required: true,
322
+ displayOptions: {
323
+ show: {
324
+ operation: ['set2DPrintAreas'],
325
+ },
326
+ },
327
+ default: {},
328
+ placeholder: 'Add Print Area',
329
+ description: 'Four coordinate pairs that define each print area quad',
330
+ options: [
331
+ {
332
+ name: 'items',
333
+ displayName: 'Print Area',
334
+ values: [
335
+ {
336
+ displayName: 'Point 1 X',
337
+ name: 'point1X',
338
+ type: 'number',
339
+ required: true,
340
+ default: 0,
341
+ description: 'X coordinate of point 1',
342
+ },
343
+ {
344
+ displayName: 'Point 1 Y',
345
+ name: 'point1Y',
346
+ type: 'number',
347
+ required: true,
348
+ default: 0,
349
+ description: 'Y coordinate of point 1',
350
+ },
351
+ {
352
+ displayName: 'Point 2 X',
353
+ name: 'point2X',
354
+ type: 'number',
355
+ required: true,
356
+ default: 0,
357
+ description: 'X coordinate of point 2',
358
+ },
359
+ {
360
+ displayName: 'Point 2 Y',
361
+ name: 'point2Y',
362
+ type: 'number',
363
+ required: true,
364
+ default: 0,
365
+ description: 'Y coordinate of point 2',
366
+ },
367
+ {
368
+ displayName: 'Point 3 X',
369
+ name: 'point3X',
370
+ type: 'number',
371
+ required: true,
372
+ default: 0,
373
+ description: 'X coordinate of point 3',
374
+ },
375
+ {
376
+ displayName: 'Point 3 Y',
377
+ name: 'point3Y',
378
+ type: 'number',
379
+ required: true,
380
+ default: 0,
381
+ description: 'Y coordinate of point 3',
382
+ },
383
+ {
384
+ displayName: 'Point 4 X',
385
+ name: 'point4X',
386
+ type: 'number',
387
+ required: true,
388
+ default: 0,
389
+ description: 'X coordinate of point 4',
390
+ },
391
+ {
392
+ displayName: 'Point 4 Y',
393
+ name: 'point4Y',
394
+ type: 'number',
395
+ required: true,
396
+ default: 0,
397
+ description: 'Y coordinate of point 4',
398
+ },
399
+ ],
400
+ },
401
+ ],
402
+ },
403
+ {
404
+ displayName: 'Print Areas',
405
+ name: 'twoDRenderPrintAreas',
406
+ type: 'fixedCollection',
407
+ typeOptions: {
408
+ multipleValues: true,
409
+ },
410
+ required: true,
411
+ displayOptions: {
412
+ show: {
413
+ operation: ['render2DMockup'],
414
+ },
415
+ },
416
+ default: {},
417
+ placeholder: 'Add Print Area',
418
+ description: 'Artwork and options for each saved print area',
419
+ options: [
420
+ {
421
+ name: 'items',
422
+ displayName: 'Print Area',
423
+ values: [
424
+ {
425
+ displayName: 'Print Area UUID',
426
+ name: 'uuid',
427
+ type: 'string',
428
+ required: true,
429
+ default: '',
430
+ description: 'UUID returned by 2D: Get Mockup when status is ready',
431
+ },
432
+ {
433
+ displayName: 'Artwork Type',
434
+ name: 'artworkSource',
435
+ type: 'options',
436
+ options: [
437
+ {
438
+ name: 'Artwork URL',
439
+ value: 'url',
440
+ description: 'Public artwork URL for this print area',
441
+ },
442
+ {
443
+ name: 'Base64 Artwork',
444
+ value: 'base64',
445
+ description: 'Base64 artwork data for this print area',
446
+ },
447
+ ],
448
+ default: 'url',
449
+ description: 'Artwork source for this print area',
450
+ },
451
+ {
452
+ displayName: 'Artwork URL',
453
+ name: 'artworkUrl',
454
+ type: 'string',
455
+ required: true,
456
+ displayOptions: {
457
+ show: {
458
+ artworkSource: ['url'],
459
+ },
460
+ },
461
+ default: '',
462
+ placeholder: 'https://cdn.example.com/design.png',
463
+ description: 'Public artwork URL for this print area',
464
+ },
465
+ {
466
+ displayName: 'Base64 Artwork',
467
+ name: 'base64',
468
+ type: 'string',
469
+ required: true,
470
+ displayOptions: {
471
+ show: {
472
+ artworkSource: ['base64'],
473
+ },
474
+ },
475
+ default: '',
476
+ description: 'Base64 artwork data for this print area',
477
+ },
478
+ {
479
+ displayName: 'Color',
480
+ name: 'color',
481
+ type: 'string',
482
+ default: '',
483
+ placeholder: '#FF0000',
484
+ description: 'Optional hex color fill or overlay',
485
+ },
486
+ {
487
+ displayName: 'Adjustments',
488
+ name: 'adjustments',
489
+ type: 'collection',
490
+ placeholder: 'Add Adjustment',
491
+ default: {},
492
+ description: 'Artwork appearance settings for this print area',
493
+ options: [
494
+ {
495
+ displayName: 'Brightness',
496
+ name: 'brightness',
497
+ type: 'number',
498
+ typeOptions: { minValue: -150, maxValue: 150 },
499
+ default: 0,
500
+ description: 'Brightness adjustment from -150 to 150',
501
+ },
502
+ {
503
+ displayName: 'Contrast',
504
+ name: 'contrast',
505
+ type: 'number',
506
+ typeOptions: { minValue: -100, maxValue: 100 },
507
+ default: 0,
508
+ description: 'Contrast adjustment from -100 to 100',
509
+ },
510
+ {
511
+ displayName: 'Opacity',
512
+ name: 'opacity',
513
+ type: 'number',
514
+ typeOptions: { minValue: 0, maxValue: 100 },
515
+ default: 100,
516
+ description: 'Artwork opacity from 0 to 100',
517
+ },
518
+ {
519
+ displayName: 'Saturation',
520
+ name: 'saturation',
521
+ type: 'number',
522
+ typeOptions: { minValue: -100, maxValue: 100 },
523
+ default: 0,
524
+ description: 'Saturation adjustment from -100 to 100',
525
+ },
526
+ {
527
+ displayName: 'Vibrance',
528
+ name: 'vibrance',
529
+ type: 'number',
530
+ typeOptions: { minValue: -100, maxValue: 100 },
531
+ default: 0,
532
+ description: 'Vibrance adjustment from -100 to 100',
533
+ },
534
+ {
535
+ displayName: 'Blur',
536
+ name: 'blur',
537
+ type: 'number',
538
+ typeOptions: { minValue: 0, maxValue: 100 },
539
+ default: 0,
540
+ description: 'Gaussian blur amount from 0 to 100',
541
+ },
542
+ {
543
+ displayName: 'Blend Mode',
544
+ name: 'blend_mode',
545
+ type: 'options',
546
+ options: [
547
+ { name: 'Multiply', value: 'multiply' },
548
+ { name: 'Normal', value: 'normal' },
549
+ ],
550
+ default: 'multiply',
551
+ description: 'Artwork blend mode for the product surface',
552
+ },
553
+ {
554
+ displayName: 'Warp Strength',
555
+ name: 'warp_strength',
556
+ type: 'number',
557
+ typeOptions: { minValue: 0, maxValue: 2 },
558
+ default: 1.5,
559
+ description: 'Surface warp strength from 0 to 2',
560
+ },
561
+ {
562
+ displayName: 'Edge Expand',
563
+ name: 'edge_expand',
564
+ type: 'number',
565
+ typeOptions: { minValue: 0, maxValue: 50 },
566
+ default: 0,
567
+ description: 'Artwork edge expansion from 0 to 50',
568
+ },
569
+ {
570
+ displayName: 'Texture Strength',
571
+ name: 'texture_strength',
572
+ type: 'number',
573
+ typeOptions: { minValue: 0, maxValue: 100 },
574
+ default: 0,
575
+ description: 'Product texture strength from 0 to 100',
576
+ },
577
+ ],
578
+ },
579
+ {
580
+ displayName: 'Placement',
581
+ name: 'placement',
582
+ type: 'collection',
583
+ placeholder: 'Add Placement Option',
584
+ default: {},
585
+ description: 'Artwork position and size settings for this print area',
586
+ options: [
587
+ {
588
+ displayName: 'Position',
589
+ name: 'position',
590
+ type: 'options',
591
+ options: [
592
+ { name: 'Top Left', value: 'top_left' },
593
+ { name: 'Top Center', value: 'top_center' },
594
+ { name: 'Top Right', value: 'top_right' },
595
+ { name: 'Center Left', value: 'center_left' },
596
+ { name: 'Center', value: 'center' },
597
+ { name: 'Center Right', value: 'center_right' },
598
+ { name: 'Bottom Left', value: 'bottom_left' },
599
+ { name: 'Bottom Center', value: 'bottom_center' },
600
+ { name: 'Bottom Right', value: 'bottom_right' },
601
+ ],
602
+ default: 'center',
603
+ description: 'Predefined artwork position in the print area',
604
+ },
605
+ {
606
+ displayName: 'Coverage',
607
+ name: 'coverage',
608
+ type: 'number',
609
+ typeOptions: { minValue: 10, maxValue: 100 },
610
+ default: 70,
611
+ description: 'Percentage of the print area covered by the artwork',
612
+ },
613
+ {
614
+ displayName: 'Fit',
615
+ name: 'fit',
616
+ type: 'options',
617
+ options: [
618
+ { name: 'Fill', value: 'fill' },
619
+ { name: 'Contain', value: 'contain' },
620
+ { name: 'Cover', value: 'cover' },
621
+ ],
622
+ default: 'contain',
623
+ description: 'How the artwork fits within the print area',
624
+ },
625
+ {
626
+ displayName: 'Scale',
627
+ name: 'scale',
628
+ type: 'number',
629
+ default: 1,
630
+ description: 'Artwork scale multiplier that overrides coverage',
631
+ },
632
+ {
633
+ displayName: 'Rotation',
634
+ name: 'rotation',
635
+ type: 'number',
636
+ default: 0,
637
+ description: 'Artwork rotation in degrees',
638
+ },
639
+ {
640
+ displayName: 'Offset X',
641
+ name: 'offset_x',
642
+ type: 'number',
643
+ default: 0,
644
+ description: 'Horizontal artwork offset in pixels',
645
+ },
646
+ {
647
+ displayName: 'Offset Y',
648
+ name: 'offset_y',
649
+ type: 'number',
650
+ default: 0,
651
+ description: 'Vertical artwork offset in pixels',
652
+ },
653
+ ],
654
+ },
655
+ ],
656
+ },
657
+ ],
658
+ },
659
+ {
660
+ displayName: 'Export Options',
661
+ name: 'twoDExportOptions',
662
+ type: 'collection',
663
+ placeholder: 'Add Export Option',
664
+ displayOptions: {
665
+ show: {
666
+ operation: ['render2DMockup'],
667
+ },
668
+ },
669
+ default: {},
670
+ description: 'Output image settings for the rendered 2D mockup',
671
+ options: [
672
+ {
673
+ displayName: 'Image Format',
674
+ name: 'image_format',
675
+ type: 'options',
676
+ options: [
677
+ { name: 'PNG', value: 'png' },
678
+ { name: 'JPG', value: 'jpg' },
679
+ ],
680
+ default: 'png',
681
+ description: 'File format of the rendered image',
682
+ },
683
+ {
684
+ displayName: 'Image Size',
685
+ name: 'image_size',
686
+ type: 'options',
687
+ options: [
688
+ { name: '1024', value: 1024 },
689
+ { name: '2048', value: 2048 },
690
+ { name: '4096', value: 4096 },
691
+ ],
692
+ default: 2048,
693
+ description: 'Width of the rendered image in pixels',
694
+ },
695
+ {
696
+ displayName: 'Quality',
697
+ name: 'quality',
698
+ type: 'number',
699
+ typeOptions: { minValue: 1, maxValue: 100 },
700
+ default: 90,
701
+ description: 'JPG compression quality from 1 to 100',
702
+ },
703
+ {
704
+ displayName: 'DPI',
705
+ name: 'dpi',
706
+ type: 'number',
707
+ typeOptions: { minValue: 72, maxValue: 2400 },
708
+ default: 300,
709
+ description: 'Print resolution tag from 72 to 2400 DPI',
710
+ },
711
+ ],
712
+ },
713
+ // ============================================
191
714
  // UPLOAD PSD PARAMETERS
192
715
  // ============================================
193
716
  {
@@ -789,7 +1312,7 @@ class SudoMock {
789
1312
  },
790
1313
  default: '',
791
1314
  placeholder: '9d4e2b51-0c7a-4f8e-bb1c-2a6f9e3d8c10',
792
- description: 'The job_id returned by an async render, upload, or video request',
1315
+ description: 'The job_id returned by an async render, upload, video, or 2D mockup request',
793
1316
  },
794
1317
  {
795
1318
  displayName: 'Wait for Completion',
@@ -1290,6 +1813,137 @@ class SudoMock {
1290
1813
  });
1291
1814
  }
1292
1815
  // ========================================
1816
+ // 2D: CREATE MOCKUP
1817
+ // ========================================
1818
+ else if (operation === 'create2DMockup') {
1819
+ const sourceMode = this.getNodeParameter('twoDSourceMode', i);
1820
+ const name = this.getNodeParameter('twoDName', i, '');
1821
+ const body = {};
1822
+ if (sourceMode === 'base64') {
1823
+ body.source_base64 = this.getNodeParameter('twoDSourceBase64', i);
1824
+ }
1825
+ else {
1826
+ body.source_url = this.getNodeParameter('twoDSourceUrl', i);
1827
+ }
1828
+ if (name) {
1829
+ body.name = name;
1830
+ }
1831
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'sudoMockApi', {
1832
+ method: 'POST',
1833
+ url: 'https://api.sudomock.com/api/v1/sudoai/2d-mockups',
1834
+ body,
1835
+ json: true,
1836
+ });
1837
+ returnData.push({ json: response, pairedItem: { item: i } });
1838
+ }
1839
+ // ========================================
1840
+ // 2D: GET MOCKUP
1841
+ // ========================================
1842
+ else if (operation === 'get2DMockup') {
1843
+ const mockupUuid = this.getNodeParameter('twoDMockupUuid', i);
1844
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'sudoMockApi', {
1845
+ method: 'GET',
1846
+ url: `https://api.sudomock.com/api/v1/sudoai/2d-mockup/${mockupUuid}`,
1847
+ json: true,
1848
+ });
1849
+ returnData.push({ json: response, pairedItem: { item: i } });
1850
+ }
1851
+ // ========================================
1852
+ // 2D: LIST MOCKUPS
1853
+ // ========================================
1854
+ else if (operation === 'list2DMockups') {
1855
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'sudoMockApi', {
1856
+ method: 'GET',
1857
+ url: 'https://api.sudomock.com/api/v1/sudoai/2d-mockups',
1858
+ json: true,
1859
+ });
1860
+ returnData.push({ json: response, pairedItem: { item: i } });
1861
+ }
1862
+ // ========================================
1863
+ // 2D: SET PRINT AREAS
1864
+ // ========================================
1865
+ else if (operation === 'set2DPrintAreas') {
1866
+ const mockupUuid = this.getNodeParameter('twoDMockupUuid', i);
1867
+ const printAreas = this.getNodeParameter('twoDSetPrintAreas.items', i, []);
1868
+ const body = {
1869
+ print_areas: printAreas.map((area) => ({
1870
+ points: [
1871
+ [area.point1X, area.point1Y],
1872
+ [area.point2X, area.point2Y],
1873
+ [area.point3X, area.point3Y],
1874
+ [area.point4X, area.point4Y],
1875
+ ],
1876
+ })),
1877
+ };
1878
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'sudoMockApi', {
1879
+ method: 'PUT',
1880
+ url: `https://api.sudomock.com/api/v1/sudoai/2d-mockup/${mockupUuid}/print-areas`,
1881
+ body,
1882
+ json: true,
1883
+ });
1884
+ returnData.push({ json: response, pairedItem: { item: i } });
1885
+ }
1886
+ // ========================================
1887
+ // 2D: RENDER MOCKUP
1888
+ // ========================================
1889
+ else if (operation === 'render2DMockup') {
1890
+ const mockupUuid = this.getNodeParameter('twoDMockupUuid', i);
1891
+ const printAreasData = this.getNodeParameter('twoDRenderPrintAreas.items', i, []);
1892
+ const printAreas = printAreasData.map((area) => {
1893
+ const printArea = { uuid: area.uuid };
1894
+ if (area.artworkSource === 'base64') {
1895
+ printArea.base64 = area.base64;
1896
+ }
1897
+ else {
1898
+ printArea.artwork_url = area.artworkUrl;
1899
+ }
1900
+ if (area.color) {
1901
+ printArea.color = area.color;
1902
+ }
1903
+ if (area.adjustments && Object.keys(area.adjustments).length > 0) {
1904
+ printArea.adjustments = area.adjustments;
1905
+ }
1906
+ if (area.placement && Object.keys(area.placement).length > 0) {
1907
+ printArea.placement = area.placement;
1908
+ }
1909
+ return printArea;
1910
+ });
1911
+ const exportOptions = this.getNodeParameter('twoDExportOptions', i, {});
1912
+ const body = {
1913
+ mockup_uuid: mockupUuid,
1914
+ print_areas: printAreas,
1915
+ };
1916
+ if (Object.keys(exportOptions).length > 0) {
1917
+ body.export_options = exportOptions;
1918
+ }
1919
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'sudoMockApi', {
1920
+ method: 'POST',
1921
+ url: 'https://api.sudomock.com/api/v1/sudoai/2d-mockup/render',
1922
+ body,
1923
+ json: true,
1924
+ });
1925
+ returnData.push({ json: response, pairedItem: { item: i } });
1926
+ }
1927
+ // ========================================
1928
+ // 2D: DELETE MOCKUP
1929
+ // ========================================
1930
+ else if (operation === 'delete2DMockup') {
1931
+ const mockupUuid = this.getNodeParameter('twoDMockupUuid', i);
1932
+ await this.helpers.httpRequestWithAuthentication.call(this, 'sudoMockApi', {
1933
+ method: 'DELETE',
1934
+ url: `https://api.sudomock.com/api/v1/sudoai/2d-mockup/${mockupUuid}`,
1935
+ });
1936
+ returnData.push({
1937
+ json: {
1938
+ success: true,
1939
+ message: '2D mockup deleted successfully',
1940
+ mockupUuid,
1941
+ statusCode: 204,
1942
+ },
1943
+ pairedItem: { item: i },
1944
+ });
1945
+ }
1946
+ // ========================================
1293
1947
  // RENDER MOCKUP
1294
1948
  // ========================================
1295
1949
  else if (operation === 'render') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-sudomock",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "n8n community node for SudoMock mockup rendering API - POD automation",
5
5
  "license": "MIT",
6
6
  "homepage": "https://sudomock.com",
@@ -49,6 +49,7 @@
49
49
  "format": "prettier nodes credentials --write",
50
50
  "lint": "eslint nodes credentials",
51
51
  "lintfix": "eslint nodes credentials --fix",
52
+ "test": "npm run build && node --test",
52
53
  "prepublishOnly": "npm run build"
53
54
  },
54
55
  "devDependencies": {