Files
n8n-nodes-gwezz-changdunovel/node_modules/@n8n/eslint-plugin-community-nodes/dist/rules/credential-documentation-url.js
2025-10-26 23:10:15 +08:00

100 lines
3.8 KiB
JavaScript

import { isCredentialTypeClass, findClassProperty, getStringLiteralValue, createRule, } from '../utils/index.js';
const DEFAULT_OPTIONS = {
allowUrls: true,
allowSlugs: false,
};
function isValidUrl(value) {
try {
new URL(value);
return true;
}
catch {
return false;
}
}
function isValidSlug(value) {
// TODO: Remove this special case once these slugs are updated
if (['google/service-account', 'google/oauth-single-service', 'google/oauth-generic'].includes(value))
return true;
return value.split('/').every((segment) => /^[a-z][a-z0-9]*$/.test(segment));
}
function hasOnlyCaseIssues(value) {
return value.split('/').every((segment) => /^[a-zA-Z][a-zA-Z0-9]*$/.test(segment));
}
function validateDocumentationUrl(value, options) {
return (!!options.allowUrls && isValidUrl(value)) || (!!options.allowSlugs && isValidSlug(value));
}
function getExpectedFormatsMessage(options) {
const formats = [
...(options.allowUrls ? ['a valid URL'] : []),
...(options.allowSlugs ? ['a lowercase alphanumeric slug (can contain slashes)'] : []),
];
if (formats.length === 0)
return 'a valid format (none configured)';
if (formats.length === 1)
return formats[0];
return formats.slice(0, -1).join(', ') + ' or ' + formats[formats.length - 1];
}
export const CredentialDocumentationUrlRule = createRule({
name: 'credential-documentation-url',
meta: {
type: 'problem',
docs: {
description: 'Enforce valid credential documentationUrl format (URL or lowercase alphanumeric slug)',
},
messages: {
invalidDocumentationUrl: "documentationUrl '{{ value }}' must be {{ expectedFormats }}",
},
fixable: 'code',
schema: [
{
type: 'object',
properties: {
allowUrls: {
type: 'boolean',
description: 'Whether to allow valid URLs',
},
allowSlugs: {
type: 'boolean',
description: 'Whether to allow lowercase alphanumeric slugs with slashes',
},
},
additionalProperties: false,
},
],
},
defaultOptions: [DEFAULT_OPTIONS],
create(context, [options = {}]) {
const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
return {
ClassDeclaration(node) {
if (!isCredentialTypeClass(node)) {
return;
}
const documentationUrlProperty = findClassProperty(node, 'documentationUrl');
if (!documentationUrlProperty?.value) {
return;
}
const documentationUrl = getStringLiteralValue(documentationUrlProperty.value);
if (documentationUrl === null) {
return;
}
if (!validateDocumentationUrl(documentationUrl, mergedOptions)) {
const canAutofix = !!mergedOptions.allowSlugs && hasOnlyCaseIssues(documentationUrl);
context.report({
node: documentationUrlProperty.value,
messageId: 'invalidDocumentationUrl',
data: {
value: documentationUrl,
expectedFormats: getExpectedFormatsMessage(mergedOptions),
},
fix: canAutofix
? (fixer) => fixer.replaceText(documentationUrlProperty.value, `'${documentationUrl.toLowerCase()}'`)
: undefined,
});
}
},
};
},
});
//# sourceMappingURL=credential-documentation-url.js.map