@tadnt2003/n8n-nodes-infisical 0.2.1 → 0.3.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.
@@ -2,29 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Infisical = void 0;
4
4
  const n8n_workflow_1 = require("n8n-workflow");
5
- async function getInfisicalToken(helpers, credentials) {
6
- const apiUrl = credentials.apiUrl.replace(/\/$/, '');
7
- const authType = credentials.authType || 'serviceToken';
8
- if (authType === 'universalAuth') {
9
- const clientId = credentials.clientId;
10
- const clientSecret = credentials.clientSecret;
11
- const parts = [
12
- `clientId=${encodeURIComponent(clientId)}`,
13
- `clientSecret=${encodeURIComponent(clientSecret)}`,
14
- ];
15
- if (credentials.organizationSlug) {
16
- parts.push(`organizationSlug=${encodeURIComponent(credentials.organizationSlug)}`);
17
- }
18
- const tokenResponse = await helpers.httpRequest({
19
- method: 'POST',
20
- url: `${apiUrl}/v1/auth/universal-auth/login`,
21
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
22
- body: parts.join('&'),
23
- });
24
- return { apiUrl, accessToken: tokenResponse.accessToken };
25
- }
26
- return { apiUrl, accessToken: credentials.apiKey };
27
- }
5
+ const secretOperations_1 = require("../../utils/secretOperations");
6
+ const projectOperations_1 = require("../../utils/projectOperations");
7
+ const folderOperations_1 = require("../../utils/folderOperations");
8
+ const auth_1 = require("../../utils/auth");
28
9
  class Infisical {
29
10
  constructor() {
30
11
  this.description = {
@@ -55,8 +36,9 @@ class Infisical {
55
36
  type: 'options',
56
37
  noDataExpression: true,
57
38
  options: [
39
+ { name: 'Folder', value: 'folder' },
40
+ { name: 'Project', value: 'project' },
58
41
  { name: 'Secret', value: 'secret' },
59
- { name: 'Workspace', value: 'workspace' },
60
42
  ],
61
43
  default: 'secret',
62
44
  },
@@ -86,6 +68,12 @@ class Infisical {
86
68
  description: 'Delete a secret',
87
69
  action: 'Delete a secret',
88
70
  },
71
+ {
72
+ name: 'Delete Many',
73
+ value: 'deleteMany',
74
+ description: 'Delete multiple secrets in one request',
75
+ action: 'Delete many secrets',
76
+ },
89
77
  {
90
78
  name: 'Get',
91
79
  value: 'get',
@@ -113,32 +101,375 @@ class Infisical {
113
101
  ],
114
102
  default: 'get',
115
103
  },
116
- // ─── Workspace operations ────────────────────────────────────────────────
104
+ // ─── Project operations ────────────────────────────────────────────────
117
105
  {
118
106
  displayName: 'Operation',
119
107
  name: 'operation',
120
108
  type: 'options',
121
109
  noDataExpression: true,
122
- displayOptions: { show: { resource: ['workspace'] } },
110
+ displayOptions: { show: { resource: ['project'] } },
123
111
  options: [
112
+ {
113
+ name: 'Get',
114
+ value: 'get',
115
+ description: 'Get a project by ID',
116
+ action: 'Get a project',
117
+ },
118
+ {
119
+ name: 'Get By Slug',
120
+ value: 'getBySlug',
121
+ description: 'Get a project by slug',
122
+ action: 'Get a project by slug',
123
+ },
124
124
  {
125
125
  name: 'Get Many',
126
126
  value: 'getAll',
127
- description: 'List all accessible workspaces',
128
- action: 'Get many workspaces',
127
+ description: 'List all accessible projects',
128
+ action: 'Get many projects',
129
+ },
130
+ {
131
+ name: 'Get Secret Snapshots',
132
+ value: 'getSecretSnapshots',
133
+ description: 'List secret snapshots for a project environment',
134
+ action: 'Get secret snapshots',
135
+ },
136
+ {
137
+ name: 'Get User By Username',
138
+ value: 'getUserByUsername',
139
+ description: 'Get a project member by username',
140
+ action: 'Get user by username',
141
+ },
142
+ {
143
+ name: 'Get User Memberships',
144
+ value: 'getUserMemberships',
145
+ description: 'List all user memberships in a project',
146
+ action: 'Get user memberships',
129
147
  },
130
148
  ],
131
149
  default: 'getAll',
132
150
  },
151
+ // ─── Project fields ───────────────────────────────
152
+ {
153
+ displayName: 'Project ID',
154
+ name: 'projectId',
155
+ type: 'string',
156
+ required: true,
157
+ displayOptions: {
158
+ show: {
159
+ resource: ['project'],
160
+ operation: ['get', 'getSecretSnapshots', 'getUserMemberships', 'getUserByUsername'],
161
+ },
162
+ },
163
+ default: '',
164
+ description: 'The ID of the Infisical project',
165
+ },
166
+ {
167
+ displayName: 'Slug',
168
+ name: 'slug',
169
+ type: 'string',
170
+ required: true,
171
+ displayOptions: {
172
+ show: {
173
+ resource: ['project'],
174
+ operation: ['getBySlug'],
175
+ },
176
+ },
177
+ default: '',
178
+ description: 'The slug of the Infisical project',
179
+ },
180
+ {
181
+ displayName: 'Environment',
182
+ name: 'snapshotEnvironment',
183
+ type: 'string',
184
+ required: true,
185
+ displayOptions: {
186
+ show: {
187
+ resource: ['project'],
188
+ operation: ['getSecretSnapshots'],
189
+ },
190
+ },
191
+ default: 'dev',
192
+ description: 'The environment slug to retrieve snapshots for (e.g., dev, staging, prod)',
193
+ },
194
+ {
195
+ displayName: 'Username',
196
+ name: 'username',
197
+ type: 'string',
198
+ required: true,
199
+ displayOptions: {
200
+ show: {
201
+ resource: ['project'],
202
+ operation: ['getUserByUsername'],
203
+ },
204
+ },
205
+ default: '',
206
+ description: 'The username of the project member to retrieve',
207
+ },
208
+ {
209
+ displayName: 'Additional Fields',
210
+ name: 'snapshotOptions',
211
+ type: 'collection',
212
+ placeholder: 'Add Field',
213
+ default: {},
214
+ displayOptions: {
215
+ show: {
216
+ resource: ['project'],
217
+ operation: ['getSecretSnapshots'],
218
+ },
219
+ },
220
+ options: [
221
+ {
222
+ displayName: 'Limit',
223
+ name: 'limit',
224
+ type: 'number',
225
+ default: 20,
226
+ description: 'Maximum number of snapshots to return',
227
+ },
228
+ {
229
+ displayName: 'Offset',
230
+ name: 'offset',
231
+ type: 'number',
232
+ default: 0,
233
+ description: 'Number of snapshots to skip (pagination)',
234
+ },
235
+ {
236
+ displayName: 'Secret Path',
237
+ name: 'secretPath',
238
+ type: 'string',
239
+ default: '/',
240
+ description: 'Folder path to filter snapshots (default: /)',
241
+ },
242
+ ],
243
+ },
244
+ // ─── Folder operations ──────────────────────────────────────────────────
245
+ {
246
+ displayName: 'Operation',
247
+ name: 'operation',
248
+ type: 'options',
249
+ noDataExpression: true,
250
+ displayOptions: { show: { resource: ['folder'] } },
251
+ options: [
252
+ {
253
+ name: 'Create',
254
+ value: 'createFolder',
255
+ description: 'Create a new folder',
256
+ action: 'Create a folder',
257
+ },
258
+ {
259
+ name: 'Delete',
260
+ value: 'deleteFolder',
261
+ description: 'Delete a folder by ID or name',
262
+ action: 'Delete a folder',
263
+ },
264
+ {
265
+ name: 'Get',
266
+ value: 'getFolderById',
267
+ description: 'Get a folder by ID',
268
+ action: 'Get a folder',
269
+ },
270
+ {
271
+ name: 'List',
272
+ value: 'listFolders',
273
+ description: 'List all folders at a path',
274
+ action: 'List folders',
275
+ },
276
+ {
277
+ name: 'Update',
278
+ value: 'updateFolder',
279
+ description: 'Update the name or description of a folder',
280
+ action: 'Update a folder',
281
+ },
282
+ ],
283
+ default: 'listFolders',
284
+ },
285
+ // ─── Folder fields ──────────────────────────────────────────────────────
286
+ {
287
+ displayName: 'Project ID',
288
+ name: 'projectId',
289
+ type: 'string',
290
+ required: true,
291
+ displayOptions: {
292
+ show: {
293
+ resource: ['folder'],
294
+ operation: ['listFolders', 'createFolder', 'updateFolder', 'deleteFolder'],
295
+ },
296
+ },
297
+ default: '',
298
+ description: 'The ID of the Infisical project',
299
+ },
300
+ {
301
+ displayName: 'Environment',
302
+ name: 'environment',
303
+ type: 'string',
304
+ required: true,
305
+ displayOptions: {
306
+ show: {
307
+ resource: ['folder'],
308
+ operation: ['listFolders', 'createFolder', 'updateFolder', 'deleteFolder'],
309
+ },
310
+ },
311
+ default: 'dev',
312
+ description: 'The environment slug (e.g., dev, staging, prod)',
313
+ },
314
+ {
315
+ displayName: 'Folder Path',
316
+ name: 'folderPath',
317
+ type: 'string',
318
+ displayOptions: {
319
+ show: {
320
+ resource: ['folder'],
321
+ operation: ['listFolders', 'createFolder', 'updateFolder', 'deleteFolder'],
322
+ },
323
+ },
324
+ default: '/',
325
+ description: 'The path to list from or the parent path for create/update/delete (default: /)',
326
+ },
327
+ {
328
+ displayName: 'Folder ID',
329
+ name: 'folderId',
330
+ type: 'string',
331
+ required: true,
332
+ displayOptions: {
333
+ show: {
334
+ resource: ['folder'],
335
+ operation: ['getFolderById', 'updateFolder'],
336
+ },
337
+ },
338
+ default: '',
339
+ description: 'The ID of the folder',
340
+ },
341
+ {
342
+ displayName: 'Folder ID or Name',
343
+ name: 'folderIdOrName',
344
+ type: 'string',
345
+ required: true,
346
+ displayOptions: {
347
+ show: {
348
+ resource: ['folder'],
349
+ operation: ['deleteFolder'],
350
+ },
351
+ },
352
+ default: '',
353
+ description: 'The ID or name of the folder to delete',
354
+ },
355
+ {
356
+ displayName: 'Folder Name',
357
+ name: 'folderName',
358
+ type: 'string',
359
+ required: true,
360
+ displayOptions: {
361
+ show: {
362
+ resource: ['folder'],
363
+ operation: ['createFolder', 'updateFolder'],
364
+ },
365
+ },
366
+ default: '',
367
+ description: 'The name of the folder',
368
+ },
369
+ {
370
+ displayName: 'Additional Fields',
371
+ name: 'listFolderOptions',
372
+ type: 'collection',
373
+ placeholder: 'Add Field',
374
+ default: {},
375
+ displayOptions: {
376
+ show: {
377
+ resource: ['folder'],
378
+ operation: ['listFolders'],
379
+ },
380
+ },
381
+ options: [
382
+ {
383
+ displayName: 'Last Secret Modified',
384
+ name: 'lastSecretModified',
385
+ type: 'string',
386
+ default: '',
387
+ description: 'Filter folders modified after this ISO 8601 datetime',
388
+ },
389
+ {
390
+ displayName: 'Recursive',
391
+ name: 'recursive',
392
+ type: 'boolean',
393
+ default: false,
394
+ description: 'Whether to include subdirectories in the listing',
395
+ },
396
+ ],
397
+ },
398
+ {
399
+ displayName: 'Additional Fields',
400
+ name: 'createFolderOptions',
401
+ type: 'collection',
402
+ placeholder: 'Add Field',
403
+ default: {},
404
+ displayOptions: {
405
+ show: {
406
+ resource: ['folder'],
407
+ operation: ['createFolder'],
408
+ },
409
+ },
410
+ options: [
411
+ {
412
+ displayName: 'Description',
413
+ name: 'description',
414
+ type: 'string',
415
+ default: '',
416
+ description: 'An optional label for the folder',
417
+ },
418
+ ],
419
+ },
420
+ {
421
+ displayName: 'Additional Fields',
422
+ name: 'updateFolderOptions',
423
+ type: 'collection',
424
+ placeholder: 'Add Field',
425
+ default: {},
426
+ displayOptions: {
427
+ show: {
428
+ resource: ['folder'],
429
+ operation: ['updateFolder'],
430
+ },
431
+ },
432
+ options: [
433
+ {
434
+ displayName: 'Description',
435
+ name: 'description',
436
+ type: 'string',
437
+ default: '',
438
+ description: 'An updated label for the folder',
439
+ },
440
+ ],
441
+ },
442
+ {
443
+ displayName: 'Additional Fields',
444
+ name: 'deleteFolderOptions',
445
+ type: 'collection',
446
+ placeholder: 'Add Field',
447
+ default: {},
448
+ displayOptions: {
449
+ show: {
450
+ resource: ['folder'],
451
+ operation: ['deleteFolder'],
452
+ },
453
+ },
454
+ options: [
455
+ {
456
+ displayName: 'Force Delete',
457
+ name: 'forceDelete',
458
+ type: 'boolean',
459
+ default: false,
460
+ description: 'Whether to force delete the folder even if it contains secrets or sub-folders',
461
+ },
462
+ ],
463
+ },
133
464
  // ─── Shared secret fields ────────────────────────────────────────────────
134
465
  {
135
466
  displayName: 'Project ID',
136
- name: 'workspaceId',
467
+ name: 'projectId',
137
468
  type: 'string',
138
469
  required: true,
139
470
  displayOptions: { show: { resource: ['secret'] } },
140
471
  default: '',
141
- description: 'The ID of the Infisical project (workspace)',
472
+ description: 'The ID of the Infisical project',
142
473
  },
143
474
  {
144
475
  displayName: 'Environment',
@@ -228,6 +559,44 @@ class Infisical {
228
559
  },
229
560
  ],
230
561
  },
562
+ {
563
+ displayName: 'Secret Metadata',
564
+ name: 'secretMetadata',
565
+ type: 'fixedCollection',
566
+ typeOptions: { multipleValues: true },
567
+ placeholder: 'Add Metadata Entry',
568
+ default: {},
569
+ displayOptions: {
570
+ show: {
571
+ resource: ['secret'],
572
+ operation: ['create'],
573
+ },
574
+ },
575
+ description: 'Key/value metadata tags to attach to the secret',
576
+ options: [
577
+ {
578
+ displayName: 'Metadata Entry',
579
+ name: 'values',
580
+ values: [
581
+ {
582
+ displayName: 'Key',
583
+ name: 'key',
584
+ type: 'string',
585
+ required: true,
586
+ default: '',
587
+ description: 'Metadata key',
588
+ },
589
+ {
590
+ displayName: 'Value',
591
+ name: 'value',
592
+ type: 'string',
593
+ default: '',
594
+ description: 'Metadata value',
595
+ },
596
+ ],
597
+ },
598
+ ],
599
+ },
231
600
  // ─── Update: all fields optional ─────────────────────────────────────────
232
601
  {
233
602
  displayName: 'Additional Fields',
@@ -284,6 +653,44 @@ class Infisical {
284
653
  },
285
654
  ],
286
655
  },
656
+ {
657
+ displayName: 'Secret Metadata',
658
+ name: 'secretMetadata',
659
+ type: 'fixedCollection',
660
+ typeOptions: { multipleValues: true },
661
+ placeholder: 'Add Metadata Entry',
662
+ default: {},
663
+ displayOptions: {
664
+ show: {
665
+ resource: ['secret'],
666
+ operation: ['update'],
667
+ },
668
+ },
669
+ description: 'Key/value metadata tags to attach to the secret',
670
+ options: [
671
+ {
672
+ displayName: 'Metadata Entry',
673
+ name: 'values',
674
+ values: [
675
+ {
676
+ displayName: 'Key',
677
+ name: 'key',
678
+ type: 'string',
679
+ required: true,
680
+ default: '',
681
+ description: 'Metadata key',
682
+ },
683
+ {
684
+ displayName: 'Value',
685
+ name: 'value',
686
+ type: 'string',
687
+ default: '',
688
+ description: 'Metadata value',
689
+ },
690
+ ],
691
+ },
692
+ ],
693
+ },
287
694
  // ─── Create Many: secrets fixedCollection ─────────────────────────────────
288
695
  {
289
696
  displayName: 'Secrets',
@@ -334,6 +741,38 @@ class Infisical {
334
741
  default: false,
335
742
  description: 'Whether to disable multiline encoding for this secret value',
336
743
  },
744
+ {
745
+ displayName: 'Secret Metadata',
746
+ name: 'secretMetadata',
747
+ type: 'fixedCollection',
748
+ typeOptions: { multipleValues: true },
749
+ placeholder: 'Add Metadata Entry',
750
+ default: {},
751
+ description: 'Key/value metadata tags to attach to this secret',
752
+ options: [
753
+ {
754
+ displayName: 'Metadata Entry',
755
+ name: 'values',
756
+ values: [
757
+ {
758
+ displayName: 'Key',
759
+ name: 'key',
760
+ type: 'string',
761
+ required: true,
762
+ default: '',
763
+ description: 'Metadata key',
764
+ },
765
+ {
766
+ displayName: 'Value',
767
+ name: 'value',
768
+ type: 'string',
769
+ default: '',
770
+ description: 'Metadata value',
771
+ },
772
+ ],
773
+ },
774
+ ],
775
+ },
337
776
  ],
338
777
  },
339
778
  ],
@@ -416,6 +855,38 @@ class Infisical {
416
855
  default: false,
417
856
  description: 'Whether to disable multiline encoding for this secret value',
418
857
  },
858
+ {
859
+ displayName: 'Secret Metadata',
860
+ name: 'secretMetadata',
861
+ type: 'fixedCollection',
862
+ typeOptions: { multipleValues: true },
863
+ placeholder: 'Add Metadata Entry',
864
+ default: {},
865
+ description: 'Key/value metadata tags to attach to this secret',
866
+ options: [
867
+ {
868
+ displayName: 'Metadata Entry',
869
+ name: 'values',
870
+ values: [
871
+ {
872
+ displayName: 'Key',
873
+ name: 'key',
874
+ type: 'string',
875
+ required: true,
876
+ default: '',
877
+ description: 'Metadata key',
878
+ },
879
+ {
880
+ displayName: 'Value',
881
+ name: 'value',
882
+ type: 'string',
883
+ default: '',
884
+ description: 'Metadata value',
885
+ },
886
+ ],
887
+ },
888
+ ],
889
+ },
419
890
  ],
420
891
  },
421
892
  ],
@@ -466,6 +937,70 @@ class Infisical {
466
937
  },
467
938
  ],
468
939
  },
940
+ // ─── Delete Many: secrets fixedCollection ─────────────────────────────────
941
+ {
942
+ displayName: 'Secrets',
943
+ name: 'secretsToDelete',
944
+ type: 'fixedCollection',
945
+ typeOptions: { multipleValues: true },
946
+ required: true,
947
+ default: {},
948
+ displayOptions: {
949
+ show: {
950
+ resource: ['secret'],
951
+ operation: ['deleteMany'],
952
+ },
953
+ },
954
+ options: [
955
+ {
956
+ displayName: 'Secret',
957
+ name: 'values',
958
+ values: [
959
+ {
960
+ displayName: 'Secret Key',
961
+ name: 'secretKey',
962
+ type: 'string',
963
+ required: true,
964
+ default: '',
965
+ description: 'The name of the secret to delete',
966
+ },
967
+ {
968
+ displayName: 'Type',
969
+ name: 'type',
970
+ type: 'options',
971
+ options: [
972
+ { name: 'Shared', value: 'shared' },
973
+ { name: 'Personal', value: 'personal' },
974
+ ],
975
+ default: 'shared',
976
+ description: 'Whether to delete the shared or personal variant of the secret',
977
+ },
978
+ ],
979
+ },
980
+ ],
981
+ },
982
+ {
983
+ displayName: 'Additional Fields',
984
+ name: 'deleteManyOptions',
985
+ type: 'collection',
986
+ placeholder: 'Add Field',
987
+ default: {},
988
+ displayOptions: {
989
+ show: {
990
+ resource: ['secret'],
991
+ operation: ['deleteMany'],
992
+ },
993
+ },
994
+ options: [
995
+ {
996
+ displayName: 'Secret Path Override',
997
+ name: 'secretPath',
998
+ type: 'string',
999
+ default: '/',
1000
+ description: 'Override the top-level Secret Path for this batch request',
1001
+ },
1002
+ ],
1003
+ },
469
1004
  ],
470
1005
  };
471
1006
  this.methods = {
@@ -517,13 +1052,12 @@ class Infisical {
517
1052
  };
518
1053
  }
519
1054
  async execute() {
520
- var _a, _b, _c;
521
1055
  const items = this.getInputData();
522
1056
  const returnData = [];
523
1057
  const resource = this.getNodeParameter('resource', 0);
524
1058
  const operation = this.getNodeParameter('operation', 0);
525
1059
  const credentials = await this.getCredentials('infisicalApi');
526
- const { apiUrl, accessToken } = await getInfisicalToken(this.helpers, credentials);
1060
+ const { apiUrl, accessToken } = await (0, auth_1.getInfisicalToken)(this.helpers, credentials);
527
1061
  const baseHeaders = {
528
1062
  Authorization: `Bearer ${accessToken}`,
529
1063
  Accept: 'application/json',
@@ -533,209 +1067,18 @@ class Infisical {
533
1067
  try {
534
1068
  // ── Secret resource ─────────────────────────────────────────────────────
535
1069
  if (resource === 'secret') {
536
- const workspaceId = this.getNodeParameter('workspaceId', i);
537
- const environment = this.getNodeParameter('environment', i);
538
- const secretPath = this.getNodeParameter('secretPath', i);
539
- // ── get ───────────────────────────────────────────────────────────────
540
- if (operation === 'get') {
541
- const secretKey = this.getNodeParameter('secretKey', i);
542
- const response = await this.helpers.httpRequest({
543
- method: 'GET',
544
- url: `${apiUrl}/v4/secrets/${encodeURIComponent(secretKey)}`,
545
- headers: baseHeaders,
546
- qs: { projectId: workspaceId, environment, secretPath },
547
- });
548
- returnData.push({ json: response, pairedItem: { item: i } });
549
- // ── getAll ────────────────────────────────────────────────────────────
550
- }
551
- else if (operation === 'getAll') {
552
- const response = await this.helpers.httpRequest({
553
- method: 'GET',
554
- url: `${apiUrl}/v4/secrets`,
555
- headers: baseHeaders,
556
- qs: { projectId: workspaceId, environment, secretPath },
557
- });
558
- const secrets = response.secrets;
559
- for (const secret of secrets) {
560
- returnData.push({ json: secret, pairedItem: { item: i } });
561
- }
562
- // ── create ────────────────────────────────────────────────────────────
563
- }
564
- else if (operation === 'create') {
565
- const secretKey = this.getNodeParameter('secretKey', i);
566
- const secretValue = this.getNodeParameter('secretValue', i);
567
- const createOptions = this.getNodeParameter('createOptions', i, {});
568
- const body = {
569
- projectId: workspaceId,
570
- environment,
571
- secretValue,
572
- secretPath,
573
- type: (_a = createOptions.type) !== null && _a !== void 0 ? _a : 'shared',
574
- };
575
- if (createOptions.secretComment)
576
- body.secretComment = createOptions.secretComment;
577
- if (createOptions.skipMultilineEncoding) {
578
- body.skipMultilineEncoding = createOptions.skipMultilineEncoding;
579
- }
580
- const response = await this.helpers.httpRequest({
581
- method: 'POST',
582
- url: `${apiUrl}/v4/secrets/${encodeURIComponent(secretKey)}`,
583
- headers: baseHeaders,
584
- body: JSON.stringify(body),
585
- });
586
- returnData.push({ json: response, pairedItem: { item: i } });
587
- // ── update (v4) ───────────────────────────────────────────────────────
588
- }
589
- else if (operation === 'update') {
590
- const secretKey = this.getNodeParameter('secretKey', i);
591
- const updateOptions = this.getNodeParameter('updateOptions', i, {});
592
- const body = {
593
- projectId: workspaceId,
594
- environment,
595
- secretPath,
596
- };
597
- // Spread only non-empty optional fields
598
- if (updateOptions.secretValue !== undefined && updateOptions.secretValue !== '') {
599
- body.secretValue = updateOptions.secretValue;
600
- }
601
- if (updateOptions.newSecretName)
602
- body.newSecretName = updateOptions.newSecretName;
603
- if (updateOptions.secretComment !== undefined)
604
- body.secretComment = updateOptions.secretComment;
605
- if (updateOptions.type)
606
- body.type = updateOptions.type;
607
- if (updateOptions.skipMultilineEncoding) {
608
- body.skipMultilineEncoding = updateOptions.skipMultilineEncoding;
609
- }
610
- const response = await this.helpers.httpRequest({
611
- method: 'PATCH',
612
- url: `${apiUrl}/v4/secrets/${encodeURIComponent(secretKey)}`,
613
- headers: baseHeaders,
614
- body: JSON.stringify(body),
615
- });
616
- returnData.push({ json: response, pairedItem: { item: i } });
617
- // ── delete ────────────────────────────────────────────────────────────
618
- }
619
- else if (operation === 'delete') {
620
- const secretKey = this.getNodeParameter('secretKey', i);
621
- const deleteBody = {
622
- projectId: workspaceId,
623
- environment,
624
- secretPath,
625
- };
626
- const response = await this.helpers.httpRequest({
627
- method: 'DELETE',
628
- url: `${apiUrl}/v4/secrets/${encodeURIComponent(secretKey)}`,
629
- headers: baseHeaders,
630
- body: JSON.stringify(deleteBody),
631
- });
632
- returnData.push({ json: response, pairedItem: { item: i } });
633
- // ── createMany (v3 batch POST) ────────────────────────────────────────
634
- }
635
- else if (operation === 'createMany') {
636
- const secretsParam = this.getNodeParameter('secrets', i, {});
637
- const secretItems = (_b = secretsParam.values) !== null && _b !== void 0 ? _b : [];
638
- if (secretItems.length === 0) {
639
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one secret must be added in the Secrets list', { itemIndex: i });
640
- }
641
- const createManyOptions = this.getNodeParameter('createManyOptions', i, {});
642
- const effectivePath = createManyOptions.secretPath || secretPath;
643
- const secrets = secretItems.map((item) => {
644
- const s = {
645
- secretKey: item.secretKey,
646
- secretValue: item.secretValue,
647
- };
648
- if (item.secretComment)
649
- s.secretComment = item.secretComment;
650
- if (item.skipMultilineEncoding)
651
- s.skipMultilineEncoding = item.skipMultilineEncoding;
652
- return s;
653
- });
654
- const body = {
655
- workspaceId,
656
- environment,
657
- secretPath: effectivePath,
658
- secrets,
659
- };
660
- const response = await this.helpers.httpRequest({
661
- method: 'POST',
662
- url: `${apiUrl}/v3/secrets/batch/raw`,
663
- headers: baseHeaders,
664
- body: JSON.stringify(body),
665
- });
666
- const responseData = response;
667
- if (Array.isArray(responseData.secrets)) {
668
- for (const secret of responseData.secrets) {
669
- returnData.push({ json: secret, pairedItem: { item: i } });
670
- }
671
- }
672
- else {
673
- // Approval / policy-gated response
674
- returnData.push({ json: responseData, pairedItem: { item: i } });
675
- }
676
- // ── updateMany (v3 batch PATCH) ───────────────────────────────────────
677
- }
678
- else if (operation === 'updateMany') {
679
- const secretsToUpdateParam = this.getNodeParameter('secretsToUpdate', i, {});
680
- const secretItems = (_c = secretsToUpdateParam.values) !== null && _c !== void 0 ? _c : [];
681
- if (secretItems.length === 0) {
682
- throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'At least one secret must be added in the Secrets list', { itemIndex: i });
683
- }
684
- const updateManyOptions = this.getNodeParameter('updateManyOptions', i, {});
685
- const effectivePath = updateManyOptions.secretPath || secretPath;
686
- const secrets = secretItems.map((item) => {
687
- const s = { secretKey: item.secretKey };
688
- if (item.secretValue !== undefined && item.secretValue !== '') {
689
- s.secretValue = item.secretValue;
690
- }
691
- if (item.newSecretName)
692
- s.newSecretName = item.newSecretName;
693
- if (item.secretComment !== undefined && item.secretComment !== '') {
694
- s.secretComment = item.secretComment;
695
- }
696
- if (item.skipMultilineEncoding)
697
- s.skipMultilineEncoding = item.skipMultilineEncoding;
698
- return s;
699
- });
700
- const body = {
701
- workspaceId,
702
- environment,
703
- secretPath: effectivePath,
704
- secrets,
705
- };
706
- if (updateManyOptions.mode)
707
- body.mode = updateManyOptions.mode;
708
- const response = await this.helpers.httpRequest({
709
- method: 'PATCH',
710
- url: `${apiUrl}/v3/secrets/batch/raw`,
711
- headers: baseHeaders,
712
- body: JSON.stringify(body),
713
- });
714
- const responseData = response;
715
- if (Array.isArray(responseData.secrets)) {
716
- for (const secret of responseData.secrets) {
717
- returnData.push({ json: secret, pairedItem: { item: i } });
718
- }
719
- }
720
- else {
721
- // Approval / policy-gated response
722
- returnData.push({ json: responseData, pairedItem: { item: i } });
723
- }
724
- }
725
- // ── Workspace resource ──────────────────────────────────────────────────
1070
+ const results = await (0, secretOperations_1.executeSecretOperation)(this, apiUrl, baseHeaders, operation, i);
1071
+ returnData.push(...results);
1072
+ // ── Project resource ──────────────────────────────────────────────────
726
1073
  }
727
- else if (resource === 'workspace') {
728
- if (operation === 'getAll') {
729
- const response = await this.helpers.httpRequest({
730
- method: 'GET',
731
- url: `${apiUrl}/v1/workspace`,
732
- headers: baseHeaders,
733
- });
734
- const workspaces = response.workspaces;
735
- for (const workspace of workspaces) {
736
- returnData.push({ json: workspace, pairedItem: { item: i } });
737
- }
738
- }
1074
+ else if (resource === 'project') {
1075
+ const results = await (0, projectOperations_1.executeProjectOperation)(this, apiUrl, baseHeaders, operation, i);
1076
+ returnData.push(...results);
1077
+ // ── Folder resource ──────────────────────────────────────────────────
1078
+ }
1079
+ else if (resource === 'folder') {
1080
+ const results = await (0, folderOperations_1.executeFolderOperation)(this, apiUrl, baseHeaders, operation, i);
1081
+ returnData.push(...results);
739
1082
  }
740
1083
  }
741
1084
  catch (error) {