100 lines
3.8 KiB
JavaScript
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
|