@unito/integration-sdk
Version:
Integration SDK
67 lines (66 loc) • 2.53 kB
JavaScript
const RAW_ERROR_NAMES = new Set(['Error', 'TypeError', 'RangeError', 'SyntaxError', 'ReferenceError']);
const ALLOWLISTED_FILE_PATTERNS = [/\/cache\.ts$/, /\/scripts?\//, /\/errors\.ts$/, /\/helpers\/stringHelper\.ts$/];
const ALLOWLISTED_MESSAGE_PATTERNS = [/only supported in tests/i, /assertNever/];
function isFileAllowlisted(filename) {
return ALLOWLISTED_FILE_PATTERNS.some(re => re.test(filename));
}
function isMessageAllowlisted(arg, sourceCode) {
if (!arg) {
return false;
}
const text = sourceCode.getText(arg);
return ALLOWLISTED_MESSAGE_PATTERNS.some(re => re.test(text));
}
function getThrownConstructorName(arg) {
if (!arg) {
return null;
}
const isConstructorLike = arg.type === 'NewExpression' || arg.type === 'CallExpression';
if (!isConstructorLike) {
return null;
}
const callExpr = arg;
if (!callExpr.callee || callExpr.callee.type !== 'Identifier') {
return null;
}
return callExpr.callee.name;
}
const rule = {
meta: {
type: 'problem',
docs: {
description: 'Disallow `throw new Error(...)` and related raw builtins; require typed errors from `@unito/integration-sdk`',
recommended: true,
},
schema: [],
messages: {
rawThrow: 'Do not `throw new {{name}}(...)`. Throw a typed error from `@unito/integration-sdk` instead (e.g. `HttpErrors.UnprocessableEntityError`, `HttpErrors.NotFoundError`). Typed errors carry the right HTTP status code, expose structured metadata to the logger, and let callers branch on `instanceof`.',
},
},
create(context) {
const filename = context.filename ?? '';
if (isFileAllowlisted(filename)) {
return {};
}
const sourceCode = context.sourceCode;
return {
ThrowStatement(node) {
const constructorName = getThrownConstructorName(node.argument);
if (!constructorName || !RAW_ERROR_NAMES.has(constructorName)) {
return;
}
const callExpr = node.argument;
const firstArg = callExpr.arguments[0];
if (isMessageAllowlisted(firstArg, sourceCode)) {
return;
}
context.report({
node,
messageId: 'rawThrow',
data: { name: constructorName },
});
},
};
},
};
export default rule;