@arabasta/eslint-plugin-tsoa
Version:
ESLint plugin for tsoa rules
114 lines (113 loc) • 4.27 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const node_fs_1 = __importDefault(require("node:fs"));
const utils_1 = require("../utils");
exports.default = (0, utils_1.createRule)({
name: 'require-tags-metadata',
meta: {
messages: {
tagNotDefinedInConfig: "The following tags are missing from the TSOA config '{{ missingTagNames }}'",
},
type: 'problem',
docs: {
description: 'require tags used by the `@Tags` decorator to be present in the `TSOA` config',
recommended: true,
},
schema: [
{
type: 'object',
additionalProperties: false,
properties: {
tsoaConfigFilePath: {
type: 'string',
description: "Where the TSOA's config file is located.",
},
},
},
],
},
defaultOptions: [
{
tsoaConfigFilePath: './tsoa.json',
},
],
create: (context, [{ tsoaConfigFilePath }]) => {
const decorators = [];
function getDefinedTsoaTagNames(tsoaConfig) {
var _a;
if (Array.isArray((_a = tsoaConfig.spec) === null || _a === void 0 ? void 0 : _a.tags)) {
return tsoaConfig.spec.tags
.filter((tag) => typeof tag.name === 'string')
.map((tag) => tag.name);
}
return [];
}
return {
Decorator(node) {
if (node.expression.type !== 'CallExpression' ||
node.expression.callee.type !== 'Identifier' ||
node.expression.callee.name !== 'Tags') {
return;
}
decorators.push(node);
},
'Program:exit': () => {
if (decorators.length === 0) {
return;
}
let tsoaConfigJson;
try {
tsoaConfigJson = node_fs_1.default.readFileSync(tsoaConfigFilePath, {
encoding: 'utf-8',
});
}
catch (error) {
console.warn(error);
return;
}
let tsoaConfig;
try {
tsoaConfig = JSON.parse(tsoaConfigJson);
}
catch (error) {
console.warn(error);
return;
}
if (typeof tsoaConfig !== 'object') {
console.warn(`Expected tsoa config to be an object but got '${typeof tsoaConfig}' instead.`);
return;
}
const tsoaTagNames = getDefinedTsoaTagNames(tsoaConfig);
for (const decorator of decorators) {
const expression = decorator.expression;
if (!('arguments' in expression) ||
!Array.isArray(expression.arguments)) {
continue;
}
const missingTagNames = [];
for (const tagArg of expression.arguments) {
if (tagArg.type !== 'Literal' || typeof tagArg.value !== 'string') {
continue;
}
const tagName = tagArg.value;
if (!tsoaTagNames.includes(tagName)) {
missingTagNames.push(tagName);
}
}
if (missingTagNames.length > 0) {
context.report({
node: decorator,
messageId: 'tagNotDefinedInConfig',
data: {
missingTagNames: missingTagNames.join(', '),
},
});
}
}
},
};
},
});