@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.
@@ -0,0 +1,1057 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InfisicalSync = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const auth_1 = require("../../utils/auth");
6
+ const syncOperations_1 = require("../../utils/syncOperations");
7
+ class InfisicalSync {
8
+ constructor() {
9
+ this.description = {
10
+ displayName: 'Infisical Sync',
11
+ name: 'infisicalSync',
12
+ icon: 'file:infisical.png',
13
+ group: ['transform'],
14
+ version: 1,
15
+ subtitle: '={{$parameter["operation"]}}',
16
+ description: 'Sync n8n credentials to Infisical secrets management',
17
+ defaults: { name: 'Infisical Sync' },
18
+ inputs: ['main'],
19
+ outputs: ['main'],
20
+ credentials: [
21
+ {
22
+ name: 'infisicalApi',
23
+ displayName: 'Infisical Account',
24
+ required: true,
25
+ testedBy: 'testInfisicalApiCredentials',
26
+ },
27
+ {
28
+ name: 'n8nApi',
29
+ displayName: 'n8n Account',
30
+ required: false,
31
+ },
32
+ ],
33
+ properties: [
34
+ // ── Operation ──────────────────────────────────────────────────────────
35
+ {
36
+ displayName: 'Operation',
37
+ name: 'operation',
38
+ type: 'options',
39
+ noDataExpression: true,
40
+ options: [
41
+ {
42
+ name: 'Sync Credential to Infisical',
43
+ value: 'syncToInfisical',
44
+ description: 'Push an n8n credential as a folder of secrets into Infisical',
45
+ action: 'Sync credential to Infisical',
46
+ },
47
+ {
48
+ name: 'Sync Credential from Infisical',
49
+ value: 'syncFromInfisical',
50
+ description: 'Pull secrets from an Infisical folder and update an n8n credential',
51
+ action: 'Sync credential from Infisical',
52
+ },
53
+ {
54
+ name: 'Auto Sync All from Infisical',
55
+ value: 'autoSyncFromInfisical',
56
+ description: 'Discover all credential folders in Infisical and create or update matching n8n credentials automatically',
57
+ action: 'Auto sync all from Infisical',
58
+ },
59
+ ],
60
+ default: 'syncToInfisical',
61
+ },
62
+ // ── Infisical target (shared) ─────────────────────────────────────────
63
+ {
64
+ displayName: 'Project ID',
65
+ name: 'projectId',
66
+ type: 'string',
67
+ required: true,
68
+ default: '',
69
+ description: 'ID of the Infisical project where all n8n credentials are stored',
70
+ displayOptions: { show: { operation: ['syncToInfisical', 'syncFromInfisical', 'autoSyncFromInfisical'] } },
71
+ },
72
+ {
73
+ displayName: 'Environment',
74
+ name: 'environment',
75
+ type: 'string',
76
+ required: true,
77
+ default: 'dev',
78
+ description: 'Infisical environment slug (e.g. dev, staging, prod)',
79
+ displayOptions: { show: { operation: ['syncToInfisical', 'syncFromInfisical', 'autoSyncFromInfisical'] } },
80
+ },
81
+ {
82
+ displayName: 'Root Path',
83
+ name: 'rootPath',
84
+ type: 'string',
85
+ default: '/',
86
+ description: 'Base folder path in Infisical. Each credential is a subfolder here (e.g. / → /My Google Account).',
87
+ displayOptions: { show: { operation: ['syncToInfisical', 'syncFromInfisical', 'autoSyncFromInfisical'] } },
88
+ },
89
+ // ── Credential identity (shared) ──────────────────────────────────────
90
+ {
91
+ displayName: 'Credential Name',
92
+ name: 'credentialName',
93
+ type: 'string',
94
+ required: true,
95
+ default: '',
96
+ description: 'Name of the credential — maps to the Infisical folder name under Root Path',
97
+ displayOptions: { show: { operation: ['syncToInfisical', 'syncFromInfisical'] } },
98
+ },
99
+ // ── Infisical → n8n: target credential ───────────────────────────────
100
+ {
101
+ displayName: 'n8n Credential ID',
102
+ name: 'n8nCredentialId',
103
+ type: 'string',
104
+ required: true,
105
+ default: '',
106
+ description: 'ID of the n8n credential to update (visible in the credential URL)',
107
+ displayOptions: { show: { operation: ['syncFromInfisical'] } },
108
+ },
109
+ // ── Input mode (syncToInfisical only) ─────────────────────────────────
110
+ {
111
+ displayName: 'Input Mode',
112
+ name: 'inputMode',
113
+ type: 'options',
114
+ noDataExpression: true,
115
+ default: 'form',
116
+ options: [
117
+ {
118
+ name: 'Form',
119
+ value: 'form',
120
+ description: 'Fill in individual fields for the selected credential type',
121
+ },
122
+ {
123
+ name: 'JSON',
124
+ value: 'json',
125
+ description: 'Paste all credential fields as a JSON object',
126
+ },
127
+ ],
128
+ displayOptions: { show: { operation: ['syncToInfisical'] } },
129
+ },
130
+ // ── Credential type: form mode (dropdown of supported types) ──────────
131
+ {
132
+ displayName: 'Credential Type',
133
+ name: 'credentialType',
134
+ type: 'options',
135
+ required: true,
136
+ default: 'openAiApi',
137
+ description: 'The n8n credential type to sync',
138
+ displayOptions: { show: { operation: ['syncToInfisical'], inputMode: ['form'] } },
139
+ options: [
140
+ { name: 'Anthropic', value: 'anthropicApi' },
141
+ { name: 'Basic Auth', value: 'httpBasicAuth' },
142
+ { name: 'Bearer Auth', value: 'httpBearerAuth' },
143
+ { name: 'Cohere', value: 'cohereApi' },
144
+ { name: 'Custom Auth', value: 'httpCustomAuth' },
145
+ { name: 'Digest Auth', value: 'httpDigestAuth' },
146
+ { name: 'Discord Bot', value: 'discordBotApi' },
147
+ { name: 'Discord Webhook', value: 'discordWebhookApi' },
148
+ { name: 'Google Docs (OAuth2)', value: 'googleDocsOAuth2Api' },
149
+ { name: 'Google Drive (OAuth2)', value: 'googleDriveOAuth2Api' },
150
+ { name: 'Google OAuth2', value: 'googleOAuth2Api' },
151
+ { name: 'Google Service Account', value: 'googleApi' },
152
+ { name: 'Google Sheets (OAuth2)', value: 'googleSheetsOAuth2Api' },
153
+ { name: 'Groq', value: 'groqApi' },
154
+ { name: 'Header Auth', value: 'httpHeaderAuth' },
155
+ { name: 'HuggingFace', value: 'huggingFaceApi' },
156
+ { name: 'Infisical', value: 'infisicalApi' },
157
+ { name: 'Jira Software Cloud', value: 'jiraSoftwareCloudApi' },
158
+ { name: 'JWT Auth', value: 'jwtAuth' },
159
+ { name: 'Microsoft SQL Server', value: 'microsoftSql' },
160
+ { name: 'Mistral', value: 'mistralCloudApi' },
161
+ { name: 'MongoDB', value: 'mongoDb' },
162
+ { name: 'MySQL', value: 'mySql' },
163
+ { name: 'n8n', value: 'n8nApi' },
164
+ { name: 'OAuth1 API', value: 'oAuth1Api' },
165
+ { name: 'OAuth2 API', value: 'oAuth2Api' },
166
+ { name: 'OpenAI', value: 'openAiApi' },
167
+ { name: 'PostgreSQL', value: 'postgres' },
168
+ { name: 'Query Auth', value: 'httpQueryAuth' },
169
+ { name: 'Redis', value: 'redis' },
170
+ { name: 'SSL Certificates', value: 'httpSslAuth' },
171
+ ],
172
+ },
173
+ // ── Credential type: json mode (free-text, any type) ──────────────────
174
+ {
175
+ displayName: 'Credential Type',
176
+ name: 'credentialTypeJson',
177
+ type: 'string',
178
+ required: true,
179
+ default: '',
180
+ placeholder: 'e.g. openAiApi, postgresApi',
181
+ description: 'The n8n credential type name — stored as n8n_credential_type metadata on every secret',
182
+ displayOptions: { show: { operation: ['syncToInfisical'], inputMode: ['json'] } },
183
+ },
184
+ // ── Credential fields: json mode ──────────────────────────────────────
185
+ {
186
+ displayName: 'Credential Fields (JSON)',
187
+ name: 'credentialJson',
188
+ type: 'string',
189
+ typeOptions: { rows: 8 },
190
+ required: true,
191
+ default: '{}',
192
+ description: 'JSON object mapping each credential field name to its value',
193
+ displayOptions: { show: { operation: ['syncToInfisical'], inputMode: ['json'] } },
194
+ },
195
+ // ── LLM: shared apiKey ────────────────────────────────────────────────
196
+ {
197
+ displayName: 'API Key',
198
+ name: 'apiKey',
199
+ type: 'string',
200
+ typeOptions: { password: true },
201
+ default: '',
202
+ displayOptions: {
203
+ show: {
204
+ operation: ['syncToInfisical'],
205
+ inputMode: ['form'],
206
+ credentialType: [
207
+ 'openAiApi',
208
+ 'anthropicApi',
209
+ 'groqApi',
210
+ 'cohereApi',
211
+ 'huggingFaceApi',
212
+ 'mistralCloudApi',
213
+ 'n8nApi',
214
+ 'infisicalApi',
215
+ ],
216
+ },
217
+ },
218
+ },
219
+ {
220
+ displayName: 'Organization ID',
221
+ name: 'organizationId',
222
+ type: 'string',
223
+ default: '',
224
+ description: 'Optional OpenAI organization ID',
225
+ displayOptions: {
226
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['openAiApi'] },
227
+ },
228
+ },
229
+ {
230
+ displayName: 'Base URL',
231
+ name: 'url',
232
+ type: 'string',
233
+ default: '',
234
+ description: 'Optional custom API base URL (overrides the default endpoint)',
235
+ displayOptions: {
236
+ show: {
237
+ operation: ['syncToInfisical'],
238
+ inputMode: ['form'],
239
+ credentialType: ['openAiApi', 'anthropicApi'],
240
+ },
241
+ },
242
+ },
243
+ // ── Google Service Account ────────────────────────────────────────────
244
+ {
245
+ displayName: 'Private Key',
246
+ name: 'privateKey',
247
+ type: 'string',
248
+ typeOptions: { password: true },
249
+ default: '',
250
+ description: 'PEM-encoded private key from the service account JSON',
251
+ displayOptions: {
252
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['googleApi', 'jwtAuth'] },
253
+ },
254
+ },
255
+ {
256
+ displayName: 'Delegated Email',
257
+ name: 'delegatedEmail',
258
+ type: 'string',
259
+ default: '',
260
+ description: 'Optional email to impersonate via domain-wide delegation',
261
+ displayOptions: {
262
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['googleApi'] },
263
+ },
264
+ },
265
+ {
266
+ displayName: 'Scopes',
267
+ name: 'scopes',
268
+ type: 'string',
269
+ default: '',
270
+ description: 'Comma-separated list of OAuth scopes',
271
+ displayOptions: {
272
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['googleApi'] },
273
+ },
274
+ },
275
+ // ── Google OAuth2 ─────────────────────────────────────────────────────
276
+ {
277
+ displayName: 'Client ID',
278
+ name: 'clientId',
279
+ type: 'string',
280
+ default: '',
281
+ displayOptions: {
282
+ show: {
283
+ operation: ['syncToInfisical'],
284
+ inputMode: ['form'],
285
+ credentialType: [
286
+ 'googleOAuth2Api',
287
+ 'googleSheetsOAuth2Api',
288
+ 'googleDriveOAuth2Api',
289
+ 'googleDocsOAuth2Api',
290
+ 'infisicalApi',
291
+ 'oAuth2Api',
292
+ ],
293
+ },
294
+ },
295
+ },
296
+ {
297
+ displayName: 'Client Secret',
298
+ name: 'clientSecret',
299
+ type: 'string',
300
+ typeOptions: { password: true },
301
+ default: '',
302
+ displayOptions: {
303
+ show: {
304
+ operation: ['syncToInfisical'],
305
+ inputMode: ['form'],
306
+ credentialType: [
307
+ 'googleOAuth2Api',
308
+ 'googleSheetsOAuth2Api',
309
+ 'googleDriveOAuth2Api',
310
+ 'googleDocsOAuth2Api',
311
+ 'infisicalApi',
312
+ 'oAuth2Api',
313
+ ],
314
+ },
315
+ },
316
+ },
317
+ {
318
+ displayName: 'Scope',
319
+ name: 'scope',
320
+ type: 'string',
321
+ default: '',
322
+ description: 'Space-separated list of OAuth scopes to request',
323
+ displayOptions: {
324
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['googleOAuth2Api', 'oAuth2Api'] },
325
+ },
326
+ },
327
+ // ── Google Service OAuth2 (Sheets / Drive / Docs) + n8n ─────────────
328
+ {
329
+ displayName: 'Allowed HTTP Request Domains',
330
+ name: 'allowedHttpRequestDomains',
331
+ type: 'options',
332
+ default: 'all',
333
+ options: [
334
+ { name: 'All Domains', value: 'all' },
335
+ { name: 'Specific Domains', value: 'domains' },
336
+ { name: 'None', value: 'none' },
337
+ ],
338
+ displayOptions: {
339
+ show: {
340
+ operation: ['syncToInfisical'],
341
+ inputMode: ['form'],
342
+ credentialType: [
343
+ 'googleSheetsOAuth2Api',
344
+ 'googleDriveOAuth2Api',
345
+ 'googleDocsOAuth2Api',
346
+ 'n8nApi',
347
+ 'httpBearerAuth',
348
+ 'httpBasicAuth',
349
+ 'httpDigestAuth',
350
+ 'httpHeaderAuth',
351
+ 'httpQueryAuth',
352
+ 'httpCustomAuth',
353
+ 'oAuth1Api',
354
+ 'oAuth2Api',
355
+ ],
356
+ },
357
+ },
358
+ },
359
+ {
360
+ displayName: 'Allowed Domains',
361
+ name: 'allowedDomains',
362
+ type: 'string',
363
+ default: '',
364
+ placeholder: 'e.g. api.example.com,cdn.example.com',
365
+ description: 'Comma-separated list of domains; only used when Allowed HTTP Request Domains is set to Specific Domains',
366
+ displayOptions: {
367
+ show: {
368
+ operation: ['syncToInfisical'],
369
+ inputMode: ['form'],
370
+ credentialType: [
371
+ 'googleSheetsOAuth2Api',
372
+ 'googleDriveOAuth2Api',
373
+ 'googleDocsOAuth2Api',
374
+ 'n8nApi',
375
+ 'httpBearerAuth',
376
+ 'httpBasicAuth',
377
+ 'httpDigestAuth',
378
+ 'httpHeaderAuth',
379
+ 'httpQueryAuth',
380
+ 'httpCustomAuth',
381
+ 'oAuth1Api',
382
+ 'oAuth2Api',
383
+ ],
384
+ allowedHttpRequestDomains: ['domains'],
385
+ },
386
+ },
387
+ },
388
+ // ── n8n API ───────────────────────────────────────────────────────────
389
+ {
390
+ displayName: 'Base URL',
391
+ name: 'baseUrl',
392
+ type: 'string',
393
+ default: '',
394
+ placeholder: 'http://localhost:5678',
395
+ description: 'Base URL of the n8n instance (without /api/v1)',
396
+ displayOptions: {
397
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['n8nApi'] },
398
+ },
399
+ },
400
+ // ── Infisical ─────────────────────────────────────────────────────────
401
+ {
402
+ displayName: 'API URL',
403
+ name: 'apiUrl',
404
+ type: 'string',
405
+ default: 'https://app.infisical.com/api',
406
+ placeholder: 'https://app.infisical.com/api',
407
+ description: 'Base URL of the Infisical API',
408
+ displayOptions: {
409
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['infisicalApi'] },
410
+ },
411
+ },
412
+ {
413
+ displayName: 'Authentication Type',
414
+ name: 'authType',
415
+ type: 'options',
416
+ default: 'universalAuth',
417
+ options: [
418
+ { name: 'Universal Auth (Machine Identity)', value: 'universalAuth' },
419
+ { name: 'Service Token (Legacy)', value: 'serviceToken' },
420
+ ],
421
+ displayOptions: {
422
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['infisicalApi'] },
423
+ },
424
+ },
425
+ {
426
+ displayName: 'Organization Slug',
427
+ name: 'organizationSlug',
428
+ type: 'string',
429
+ default: '',
430
+ description: 'Optional — scope the access token to a specific organization',
431
+ displayOptions: {
432
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['infisicalApi'] },
433
+ },
434
+ },
435
+ // ── Shared: email (Google SA + Jira) ──────────────────────────────────
436
+ {
437
+ displayName: 'Email',
438
+ name: 'email',
439
+ type: 'string',
440
+ default: '',
441
+ displayOptions: {
442
+ show: {
443
+ operation: ['syncToInfisical'],
444
+ inputMode: ['form'],
445
+ credentialType: ['googleApi', 'jiraSoftwareCloudApi'],
446
+ },
447
+ },
448
+ },
449
+ // ── Jira ──────────────────────────────────────────────────────────────
450
+ {
451
+ displayName: 'API Token',
452
+ name: 'apiToken',
453
+ type: 'string',
454
+ typeOptions: { password: true },
455
+ default: '',
456
+ displayOptions: {
457
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['jiraSoftwareCloudApi'] },
458
+ },
459
+ },
460
+ {
461
+ displayName: 'Jira Domain',
462
+ name: 'jiraDomain',
463
+ type: 'string',
464
+ default: '',
465
+ placeholder: 'yourcompany.atlassian.net',
466
+ displayOptions: {
467
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['jiraSoftwareCloudApi'] },
468
+ },
469
+ },
470
+ // ── Discord ───────────────────────────────────────────────────────────
471
+ {
472
+ displayName: 'Bot Token',
473
+ name: 'botToken',
474
+ type: 'string',
475
+ typeOptions: { password: true },
476
+ default: '',
477
+ displayOptions: {
478
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['discordBotApi'] },
479
+ },
480
+ },
481
+ {
482
+ displayName: 'Webhook URI',
483
+ name: 'webhookUri',
484
+ type: 'string',
485
+ default: '',
486
+ displayOptions: {
487
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['discordWebhookApi'] },
488
+ },
489
+ },
490
+ // ── Database: shared host / user / password / port / database ─────────
491
+ {
492
+ displayName: 'Host',
493
+ name: 'host',
494
+ type: 'string',
495
+ default: 'localhost',
496
+ displayOptions: {
497
+ show: {
498
+ operation: ['syncToInfisical'],
499
+ inputMode: ['form'],
500
+ credentialType: ['mySql', 'postgres', 'mongoDb', 'redis'],
501
+ },
502
+ },
503
+ },
504
+ {
505
+ displayName: 'Server',
506
+ name: 'server',
507
+ type: 'string',
508
+ default: 'localhost',
509
+ displayOptions: {
510
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['microsoftSql'] },
511
+ },
512
+ },
513
+ {
514
+ displayName: 'Database',
515
+ name: 'database',
516
+ type: 'string',
517
+ default: '',
518
+ displayOptions: {
519
+ show: {
520
+ operation: ['syncToInfisical'],
521
+ inputMode: ['form'],
522
+ credentialType: ['mySql', 'postgres', 'mongoDb', 'redis', 'microsoftSql', 'httpBasicAuth', 'httpDigestAuth'],
523
+ },
524
+ },
525
+ },
526
+ {
527
+ displayName: 'User',
528
+ name: 'user',
529
+ type: 'string',
530
+ default: '',
531
+ displayOptions: {
532
+ show: {
533
+ operation: ['syncToInfisical'],
534
+ inputMode: ['form'],
535
+ credentialType: ['mySql', 'postgres', 'mongoDb', 'redis', 'microsoftSql', 'httpBasicAuth', 'httpDigestAuth'],
536
+ },
537
+ },
538
+ },
539
+ {
540
+ displayName: 'Password',
541
+ name: 'password',
542
+ type: 'string',
543
+ typeOptions: { password: true },
544
+ default: '',
545
+ displayOptions: {
546
+ show: {
547
+ operation: ['syncToInfisical'],
548
+ inputMode: ['form'],
549
+ credentialType: ['mySql', 'postgres', 'mongoDb', 'redis', 'microsoftSql'],
550
+ },
551
+ },
552
+ },
553
+ {
554
+ displayName: 'Port',
555
+ name: 'port',
556
+ type: 'number',
557
+ default: 5432,
558
+ description: 'Default by type: MySQL 3306 · PostgreSQL 5432 · MongoDB 27017 · Redis 6379 · MSSQL 1433',
559
+ displayOptions: {
560
+ show: {
561
+ operation: ['syncToInfisical'],
562
+ inputMode: ['form'],
563
+ credentialType: ['mySql', 'postgres', 'mongoDb', 'redis', 'microsoftSql'],
564
+ },
565
+ },
566
+ },
567
+ // ── MongoDB specific ──────────────────────────────────────────────────
568
+ {
569
+ displayName: 'Connection Type',
570
+ name: 'configurationType',
571
+ type: 'options',
572
+ default: 'values',
573
+ options: [
574
+ { name: 'Individual Fields', value: 'values' },
575
+ { name: 'Connection String', value: 'connectionString' },
576
+ ],
577
+ displayOptions: {
578
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['mongoDb'] },
579
+ },
580
+ },
581
+ {
582
+ displayName: 'Connection String',
583
+ name: 'connectionString',
584
+ type: 'string',
585
+ typeOptions: { password: true },
586
+ default: '',
587
+ placeholder: 'mongodb://user:pass@host:27017/db',
588
+ displayOptions: {
589
+ show: {
590
+ operation: ['syncToInfisical'],
591
+ inputMode: ['form'],
592
+ credentialType: ['mongoDb'],
593
+ configurationType: ['connectionString'],
594
+ },
595
+ },
596
+ },
597
+ // ── Microsoft SQL specific ────────────────────────────────────────────
598
+ {
599
+ displayName: 'Windows Domain',
600
+ name: 'mssqlDomain',
601
+ type: 'string',
602
+ default: '',
603
+ description: 'Optional Windows authentication domain',
604
+ displayOptions: {
605
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['microsoftSql'] },
606
+ },
607
+ },
608
+ // ── SSL/TLS ───────────────────────────────────────────────────────────
609
+ {
610
+ displayName: 'SSL/TLS',
611
+ name: 'ssl',
612
+ type: 'boolean',
613
+ default: false,
614
+ displayOptions: {
615
+ show: {
616
+ operation: ['syncToInfisical'],
617
+ inputMode: ['form'],
618
+ credentialType: ['mySql', 'mongoDb', 'redis'],
619
+ },
620
+ },
621
+ },
622
+ {
623
+ displayName: 'SSL Mode',
624
+ name: 'sslMode',
625
+ type: 'options',
626
+ default: 'disable',
627
+ options: [
628
+ { name: 'Disable', value: 'disable' },
629
+ { name: 'Allow', value: 'allow' },
630
+ { name: 'Require', value: 'require' },
631
+ ],
632
+ displayOptions: {
633
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['postgres'] },
634
+ },
635
+ },
636
+ // ── SSH Tunnel (MySQL + PostgreSQL) ───────────────────────────────────
637
+ {
638
+ displayName: 'SSH Tunnel',
639
+ name: 'sshTunnel',
640
+ type: 'boolean',
641
+ default: false,
642
+ displayOptions: {
643
+ show: {
644
+ operation: ['syncToInfisical'],
645
+ inputMode: ['form'],
646
+ credentialType: ['mySql', 'postgres'],
647
+ },
648
+ },
649
+ },
650
+ {
651
+ displayName: 'SSH Host',
652
+ name: 'sshHost',
653
+ type: 'string',
654
+ default: '',
655
+ displayOptions: {
656
+ show: {
657
+ operation: ['syncToInfisical'],
658
+ inputMode: ['form'],
659
+ credentialType: ['mySql', 'postgres'],
660
+ sshTunnel: [true],
661
+ },
662
+ },
663
+ },
664
+ {
665
+ displayName: 'SSH Port',
666
+ name: 'sshPort',
667
+ type: 'number',
668
+ default: 22,
669
+ displayOptions: {
670
+ show: {
671
+ operation: ['syncToInfisical'],
672
+ inputMode: ['form'],
673
+ credentialType: ['mySql', 'postgres'],
674
+ sshTunnel: [true],
675
+ },
676
+ },
677
+ },
678
+ {
679
+ displayName: 'SSH User',
680
+ name: 'sshUser',
681
+ type: 'string',
682
+ default: '',
683
+ displayOptions: {
684
+ show: {
685
+ operation: ['syncToInfisical'],
686
+ inputMode: ['form'],
687
+ credentialType: ['mySql', 'postgres'],
688
+ sshTunnel: [true],
689
+ },
690
+ },
691
+ },
692
+ {
693
+ displayName: 'SSH Password',
694
+ name: 'sshPassword',
695
+ type: 'string',
696
+ typeOptions: { password: true },
697
+ default: '',
698
+ displayOptions: {
699
+ show: {
700
+ operation: ['syncToInfisical'],
701
+ inputMode: ['form'],
702
+ credentialType: ['mySql', 'postgres'],
703
+ sshTunnel: [true],
704
+ },
705
+ },
706
+ },
707
+ // ── Bearer Auth ──────────────────────────────────────────────────────────
708
+ {
709
+ displayName: 'Token',
710
+ name: 'token',
711
+ type: 'string',
712
+ typeOptions: { password: true },
713
+ default: '',
714
+ displayOptions: {
715
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['httpBearerAuth'] },
716
+ },
717
+ },
718
+ // ── Header / Query Auth ──────────────────────────────────────────────────
719
+ {
720
+ displayName: 'Name',
721
+ name: 'name',
722
+ type: 'string',
723
+ default: '',
724
+ description: 'Header name (e.g. Authorization) or query parameter name',
725
+ displayOptions: {
726
+ show: {
727
+ operation: ['syncToInfisical'],
728
+ inputMode: ['form'],
729
+ credentialType: ['httpHeaderAuth', 'httpQueryAuth'],
730
+ },
731
+ },
732
+ },
733
+ {
734
+ displayName: 'Value',
735
+ name: 'value',
736
+ type: 'string',
737
+ typeOptions: { password: true },
738
+ default: '',
739
+ displayOptions: {
740
+ show: {
741
+ operation: ['syncToInfisical'],
742
+ inputMode: ['form'],
743
+ credentialType: ['httpHeaderAuth', 'httpQueryAuth'],
744
+ },
745
+ },
746
+ },
747
+ // ── Custom Auth ───────────────────────────────────────────────────────────
748
+ {
749
+ displayName: 'Auth JSON',
750
+ name: 'json',
751
+ type: 'string',
752
+ typeOptions: { rows: 4 },
753
+ default: '',
754
+ placeholder: '{ "headers": { "Authorization": "Bearer token" } }',
755
+ description: 'JSON object specifying headers, body, and/or query parameters for authentication',
756
+ displayOptions: {
757
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['httpCustomAuth'] },
758
+ },
759
+ },
760
+ // ── SSL Certificates ─────────────────────────────────────────────────────
761
+ {
762
+ displayName: 'CA Certificate',
763
+ name: 'ca',
764
+ type: 'string',
765
+ typeOptions: { password: true },
766
+ default: '',
767
+ description: 'PEM-encoded Certificate Authority certificate',
768
+ displayOptions: {
769
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['httpSslAuth'] },
770
+ },
771
+ },
772
+ {
773
+ displayName: 'Client Certificate',
774
+ name: 'cert',
775
+ type: 'string',
776
+ typeOptions: { password: true },
777
+ default: '',
778
+ displayOptions: {
779
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['httpSslAuth'] },
780
+ },
781
+ },
782
+ {
783
+ displayName: 'Private Key',
784
+ name: 'key',
785
+ type: 'string',
786
+ typeOptions: { password: true },
787
+ default: '',
788
+ displayOptions: {
789
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['httpSslAuth'] },
790
+ },
791
+ },
792
+ {
793
+ displayName: 'Passphrase',
794
+ name: 'passphrase',
795
+ type: 'string',
796
+ typeOptions: { password: true },
797
+ default: '',
798
+ description: 'Optional passphrase for the SSL private key',
799
+ displayOptions: {
800
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['httpSslAuth'] },
801
+ },
802
+ },
803
+ // ── OAuth1 / OAuth2 shared ────────────────────────────────────────────────
804
+ {
805
+ displayName: 'Authorization URL',
806
+ name: 'authUrl',
807
+ type: 'string',
808
+ default: '',
809
+ displayOptions: {
810
+ show: {
811
+ operation: ['syncToInfisical'],
812
+ inputMode: ['form'],
813
+ credentialType: ['oAuth1Api', 'oAuth2Api'],
814
+ },
815
+ },
816
+ },
817
+ {
818
+ displayName: 'Access Token URL',
819
+ name: 'accessTokenUrl',
820
+ type: 'string',
821
+ default: '',
822
+ displayOptions: {
823
+ show: {
824
+ operation: ['syncToInfisical'],
825
+ inputMode: ['form'],
826
+ credentialType: ['oAuth1Api', 'oAuth2Api'],
827
+ },
828
+ },
829
+ },
830
+ // ── OAuth1 ───────────────────────────────────────────────────────────────
831
+ {
832
+ displayName: 'Consumer Key',
833
+ name: 'consumerKey',
834
+ type: 'string',
835
+ default: '',
836
+ displayOptions: {
837
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['oAuth1Api'] },
838
+ },
839
+ },
840
+ {
841
+ displayName: 'Consumer Secret',
842
+ name: 'consumerSecret',
843
+ type: 'string',
844
+ typeOptions: { password: true },
845
+ default: '',
846
+ displayOptions: {
847
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['oAuth1Api'] },
848
+ },
849
+ },
850
+ {
851
+ displayName: 'Request Token URL',
852
+ name: 'requestTokenUrl',
853
+ type: 'string',
854
+ default: '',
855
+ displayOptions: {
856
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['oAuth1Api'] },
857
+ },
858
+ },
859
+ {
860
+ displayName: 'Signature Method',
861
+ name: 'signatureMethod',
862
+ type: 'options',
863
+ default: 'HMAC-SHA1',
864
+ options: [
865
+ { name: 'HMAC-SHA1', value: 'HMAC-SHA1' },
866
+ { name: 'HMAC-SHA256', value: 'HMAC-SHA256' },
867
+ { name: 'HMAC-SHA512', value: 'HMAC-SHA512' },
868
+ ],
869
+ displayOptions: {
870
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['oAuth1Api'] },
871
+ },
872
+ },
873
+ // ── OAuth2 ────────────────────────────────────────────────────────────────
874
+ {
875
+ displayName: 'Grant Type',
876
+ name: 'grantType',
877
+ type: 'options',
878
+ default: 'authorizationCode',
879
+ options: [
880
+ { name: 'Authorization Code', value: 'authorizationCode' },
881
+ { name: 'Client Credentials', value: 'clientCredentials' },
882
+ { name: 'PKCE', value: 'pkce' },
883
+ ],
884
+ displayOptions: {
885
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['oAuth2Api'] },
886
+ },
887
+ },
888
+ {
889
+ displayName: 'Auth URI Query Parameters',
890
+ name: 'authQueryParameters',
891
+ type: 'string',
892
+ default: '',
893
+ placeholder: 'access_type=offline',
894
+ description: 'Additional query parameters appended to the authorization URL (authorization code / PKCE flows only)',
895
+ displayOptions: {
896
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['oAuth2Api'] },
897
+ },
898
+ },
899
+ {
900
+ displayName: 'Authentication',
901
+ name: 'authentication',
902
+ type: 'options',
903
+ default: 'header',
904
+ options: [
905
+ { name: 'Body', value: 'body' },
906
+ { name: 'Header', value: 'header' },
907
+ ],
908
+ displayOptions: {
909
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['oAuth2Api'] },
910
+ },
911
+ },
912
+ // ── JWT Auth ─────────────────────────────────────────────────────────────
913
+ {
914
+ displayName: 'Key Type',
915
+ name: 'keyType',
916
+ type: 'options',
917
+ default: 'passphrase',
918
+ options: [
919
+ { name: 'Passphrase', value: 'passphrase' },
920
+ { name: 'PEM Key', value: 'pemKey' },
921
+ ],
922
+ displayOptions: {
923
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['jwtAuth'] },
924
+ },
925
+ },
926
+ {
927
+ displayName: 'Secret',
928
+ name: 'secret',
929
+ type: 'string',
930
+ typeOptions: { password: true },
931
+ default: '',
932
+ description: 'JWT signing secret (passphrase key type)',
933
+ displayOptions: {
934
+ show: {
935
+ operation: ['syncToInfisical'],
936
+ inputMode: ['form'],
937
+ credentialType: ['jwtAuth'],
938
+ keyType: ['passphrase'],
939
+ },
940
+ },
941
+ },
942
+ {
943
+ displayName: 'Public Key',
944
+ name: 'publicKey',
945
+ type: 'string',
946
+ typeOptions: { password: true },
947
+ default: '',
948
+ description: 'PEM-encoded public key (PEM key type)',
949
+ displayOptions: {
950
+ show: {
951
+ operation: ['syncToInfisical'],
952
+ inputMode: ['form'],
953
+ credentialType: ['jwtAuth'],
954
+ keyType: ['pemKey'],
955
+ },
956
+ },
957
+ },
958
+ {
959
+ displayName: 'Algorithm',
960
+ name: 'algorithm',
961
+ type: 'options',
962
+ default: 'HS256',
963
+ options: [
964
+ { name: 'HS256', value: 'HS256' },
965
+ { name: 'HS384', value: 'HS384' },
966
+ { name: 'HS512', value: 'HS512' },
967
+ { name: 'RS256', value: 'RS256' },
968
+ { name: 'RS384', value: 'RS384' },
969
+ { name: 'RS512', value: 'RS512' },
970
+ { name: 'ES256', value: 'ES256' },
971
+ { name: 'ES384', value: 'ES384' },
972
+ { name: 'ES512', value: 'ES512' },
973
+ { name: 'PS256', value: 'PS256' },
974
+ { name: 'PS384', value: 'PS384' },
975
+ { name: 'PS512', value: 'PS512' },
976
+ { name: 'none', value: 'none' },
977
+ ],
978
+ displayOptions: {
979
+ show: { operation: ['syncToInfisical'], inputMode: ['form'], credentialType: ['jwtAuth'] },
980
+ },
981
+ },
982
+ ],
983
+ };
984
+ this.methods = {
985
+ credentialTest: {
986
+ async testInfisicalApiCredentials(credential) {
987
+ const creds = credential.data;
988
+ const apiUrl = creds.apiUrl.replace(/\/$/, '');
989
+ const authType = creds.authType || 'serviceToken';
990
+ try {
991
+ let accessToken;
992
+ if (authType === 'universalAuth') {
993
+ const loginForm = {
994
+ clientId: creds.clientId,
995
+ clientSecret: creds.clientSecret,
996
+ };
997
+ if (creds.organizationSlug) {
998
+ loginForm.organizationSlug = creds.organizationSlug;
999
+ }
1000
+ const tokenResponse = await this.helpers.request({
1001
+ method: 'POST',
1002
+ uri: `${apiUrl}/v1/auth/universal-auth/login`,
1003
+ form: loginForm,
1004
+ json: true,
1005
+ });
1006
+ accessToken = tokenResponse.accessToken;
1007
+ }
1008
+ else {
1009
+ accessToken = creds.apiKey;
1010
+ }
1011
+ await this.helpers.request({
1012
+ method: 'GET',
1013
+ uri: `${apiUrl}/v1/workspace`,
1014
+ headers: { Authorization: `Bearer ${accessToken}`, Accept: 'application/json' },
1015
+ json: true,
1016
+ });
1017
+ return { status: 'OK', message: 'Authentication successful' };
1018
+ }
1019
+ catch (error) {
1020
+ return { status: 'Error', message: (0, n8n_workflow_1.ensureError)(error).message };
1021
+ }
1022
+ },
1023
+ },
1024
+ };
1025
+ }
1026
+ async execute() {
1027
+ const items = this.getInputData();
1028
+ const returnData = [];
1029
+ const operation = this.getNodeParameter('operation', 0);
1030
+ const credentials = await this.getCredentials('infisicalApi');
1031
+ const { apiUrl, accessToken } = await (0, auth_1.getInfisicalToken)(this.helpers, credentials);
1032
+ const baseHeaders = {
1033
+ Authorization: `Bearer ${accessToken}`,
1034
+ 'Content-Type': 'application/json',
1035
+ };
1036
+ for (let i = 0; i < items.length; i++) {
1037
+ try {
1038
+ const result = await (0, syncOperations_1.executeSyncOperation)(this, apiUrl, baseHeaders, operation, i);
1039
+ returnData.push(...result);
1040
+ }
1041
+ catch (error) {
1042
+ if (this.continueOnFail()) {
1043
+ returnData.push({
1044
+ json: { error: (0, n8n_workflow_1.ensureError)(error).message },
1045
+ pairedItem: { item: i },
1046
+ });
1047
+ continue;
1048
+ }
1049
+ if (error instanceof n8n_workflow_1.NodeOperationError)
1050
+ throw error;
1051
+ throw new n8n_workflow_1.NodeApiError(this.getNode(), error, { itemIndex: i });
1052
+ }
1053
+ }
1054
+ return [returnData];
1055
+ }
1056
+ }
1057
+ exports.InfisicalSync = InfisicalSync;