@tadnt2003/n8n-nodes-infisical 0.3.6 → 0.3.8
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/dist/utils/syncOperations.js +30 -16
- package/package.json +1 -1
|
@@ -211,13 +211,25 @@ const CREDENTIAL_FIELD_MAPS = {
|
|
|
211
211
|
{ param: 'algorithm', secretKey: 'algorithm' },
|
|
212
212
|
],
|
|
213
213
|
};
|
|
214
|
-
|
|
215
|
-
|
|
214
|
+
// Lossless encoding: [A-Za-z0-9-] pass through, _ → __, everything else → _XX hex sequences.
|
|
215
|
+
// Infisical folder names only allow [a-zA-Z0-9_-], so % cannot be used as an escape character.
|
|
216
|
+
function toFolderName(name) {
|
|
217
|
+
return [...name].map(c => {
|
|
218
|
+
if (/[A-Za-z0-9-]/.test(c))
|
|
219
|
+
return c;
|
|
220
|
+
if (c === '_')
|
|
221
|
+
return '__';
|
|
222
|
+
return encodeURIComponent(c).replace(/%/g, '_');
|
|
223
|
+
}).join('');
|
|
224
|
+
}
|
|
225
|
+
function fromFolderName(slug) {
|
|
226
|
+
const restored = slug.replace(/_([0-9A-Fa-f]{2}|_)/g, (_, p1) => p1 === '_' ? '_' : '%' + p1);
|
|
227
|
+
return decodeURIComponent(restored);
|
|
216
228
|
}
|
|
217
229
|
function buildSecretPath(rootPath, credentialName) {
|
|
218
230
|
const root = rootPath.replace(/\/+$/, '') || '/';
|
|
219
|
-
const
|
|
220
|
-
return root === '/' ? `/${
|
|
231
|
+
const folder = toFolderName(credentialName);
|
|
232
|
+
return root === '/' ? `/${folder}` : `${root}/${folder}`;
|
|
221
233
|
}
|
|
222
234
|
// Fix 7.4: handles `number` type (port, connectTimeout, maxConnections, etc.)
|
|
223
235
|
// Fix 7.7: reads schema's own `default` before falling back to enum heuristic
|
|
@@ -257,18 +269,19 @@ function coerceValue(raw, def) {
|
|
|
257
269
|
//
|
|
258
270
|
// When condKey IS in schema properties, fire only when the current value matches condValues.
|
|
259
271
|
//
|
|
260
|
-
// When condKey is NOT in schema properties (e.g. useDynamicClientRegistration on
|
|
261
|
-
// googleOAuth2Api), JSON Schema evaluates the if-clause vacuously
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
//
|
|
272
|
+
// When condKey is NOT in schema properties (e.g. useDynamicClientRegistration or grantType on
|
|
273
|
+
// googleOAuth2Api / googleSheetsOAuth2Api), JSON Schema evaluates the if-clause vacuously:
|
|
274
|
+
// the `properties` keyword only constrains keys that ARE present, so an absent key always
|
|
275
|
+
// satisfies the constraint. The if-clause passes → then fires (else never fires) for every
|
|
276
|
+
// such branch, regardless of condValues. n8n's own schema validator follows this standard
|
|
277
|
+
// JSON Schema behaviour — when useDynamicClientRegistration is absent, BOTH the [true] and
|
|
278
|
+
// [false] allOf branches fire, requiring serverUrl AND clientId/clientSecret simultaneously.
|
|
279
|
+
// We mirror that by always returning true for vacuous-truth branches.
|
|
268
280
|
function conditionFires(condKeyInSchema, condValues, condVal) {
|
|
269
281
|
if (condKeyInSchema)
|
|
270
282
|
return condValues.includes(condVal);
|
|
271
|
-
|
|
283
|
+
// Vacuous truth: absent key → if always passes → then always fires.
|
|
284
|
+
return true;
|
|
272
285
|
}
|
|
273
286
|
// Validate credential data against the n8n schema's required fields and conditional requirements.
|
|
274
287
|
// For form mode, pass availableFormFields to skip checks for fields the form cannot provide.
|
|
@@ -580,7 +593,8 @@ async function autoSyncFromInfisical(ctx, apiUrl, baseHeaders, i) {
|
|
|
580
593
|
credentialData[key] = coerceValue(raw, schemaInfo === null || schemaInfo === void 0 ? void 0 : schemaInfo.props[key]);
|
|
581
594
|
}
|
|
582
595
|
}
|
|
583
|
-
const
|
|
596
|
+
const credentialName = fromFolderName(folderName);
|
|
597
|
+
const existing = credByName.get(credentialName);
|
|
584
598
|
if (existing) {
|
|
585
599
|
// Fix 7.2: apply the same fullData build logic as the create path so that condition-key
|
|
586
600
|
// changes (e.g. ssl:false→true) get their required fields filled and their prohibited
|
|
@@ -618,7 +632,7 @@ async function autoSyncFromInfisical(ctx, apiUrl, baseHeaders, i) {
|
|
|
618
632
|
method: 'POST',
|
|
619
633
|
url: `${n8nApiUrl}/api/v1/credentials`,
|
|
620
634
|
headers: n8nHeaders,
|
|
621
|
-
body: { name:
|
|
635
|
+
body: { name: credentialName, type: credentialType, data: fullData },
|
|
622
636
|
});
|
|
623
637
|
results.push({
|
|
624
638
|
json: Object.assign(Object.assign({}, created), { action: 'created', secretPath, secretCount: secrets.length }),
|
|
@@ -702,7 +716,7 @@ async function executeSyncOperation(ctx, apiUrl, baseHeaders, operation, i) {
|
|
|
702
716
|
method: 'POST',
|
|
703
717
|
url: `${apiUrl}/v2/folders`,
|
|
704
718
|
headers: baseHeaders,
|
|
705
|
-
body: { projectId, environment, name:
|
|
719
|
+
body: { projectId, environment, name: toFolderName(credentialName), path: folderPath },
|
|
706
720
|
});
|
|
707
721
|
}
|
|
708
722
|
catch (err) {
|