routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+112
@@ -0,0 +1,112 @@
|
||||
import {getStaticValue} from '@eslint-community/eslint-utils';
|
||||
import {
|
||||
isCallExpression,
|
||||
isNewExpression,
|
||||
isUndefined,
|
||||
isNullLiteral,
|
||||
} from './ast/index.js';
|
||||
|
||||
const MESSAGE_ID_ERROR = 'no-invalid-fetch-options';
|
||||
const messages = {
|
||||
[MESSAGE_ID_ERROR]: '"body" is not allowed when method is "{{method}}".',
|
||||
};
|
||||
|
||||
const isObjectPropertyWithName = (node, name) =>
|
||||
node.type === 'Property'
|
||||
&& !node.computed
|
||||
&& node.key.type === 'Identifier'
|
||||
&& node.key.name === name;
|
||||
|
||||
function checkFetchOptions(context, node) {
|
||||
if (node.type !== 'ObjectExpression') {
|
||||
return;
|
||||
}
|
||||
|
||||
const {properties} = node;
|
||||
|
||||
const bodyProperty = properties.findLast(property => isObjectPropertyWithName(property, 'body'));
|
||||
|
||||
if (!bodyProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bodyValue = bodyProperty.value;
|
||||
if (isUndefined(bodyValue) || isNullLiteral(bodyValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const methodProperty = properties.findLast(property => isObjectPropertyWithName(property, 'method'));
|
||||
// If `method` is omitted but there is a `SpreadElement`, we just ignore the case
|
||||
if (!methodProperty) {
|
||||
if (properties.some(node => node.type === 'SpreadElement')) {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
node: bodyProperty.key,
|
||||
messageId: MESSAGE_ID_ERROR,
|
||||
data: {method: 'GET'},
|
||||
};
|
||||
}
|
||||
|
||||
const methodValue = methodProperty.value;
|
||||
|
||||
const scope = context.sourceCode.getScope(methodValue);
|
||||
let method = getStaticValue(methodValue, scope)?.value;
|
||||
|
||||
if (typeof method !== 'string') {
|
||||
return;
|
||||
}
|
||||
|
||||
method = method.toUpperCase();
|
||||
if (method !== 'GET' && method !== 'HEAD') {
|
||||
return;
|
||||
}
|
||||
|
||||
return {
|
||||
node: bodyProperty.key,
|
||||
messageId: MESSAGE_ID_ERROR,
|
||||
data: {method},
|
||||
};
|
||||
}
|
||||
|
||||
/** @param {import('eslint').Rule.RuleContext} context */
|
||||
const create = context => {
|
||||
context.on('CallExpression', callExpression => {
|
||||
if (!isCallExpression(callExpression, {
|
||||
name: 'fetch',
|
||||
minimumArguments: 2,
|
||||
optional: false,
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
|
||||
return checkFetchOptions(context, callExpression.arguments[1]);
|
||||
});
|
||||
|
||||
context.on('NewExpression', newExpression => {
|
||||
if (!isNewExpression(newExpression, {
|
||||
name: 'Request',
|
||||
minimumArguments: 2,
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
|
||||
return checkFetchOptions(context, newExpression.arguments[1]);
|
||||
});
|
||||
};
|
||||
|
||||
/** @type {import('eslint').Rule.RuleModule} */
|
||||
const config = {
|
||||
create,
|
||||
meta: {
|
||||
type: 'problem',
|
||||
docs: {
|
||||
description: 'Disallow invalid options in `fetch()` and `new Request()`.',
|
||||
recommended: 'unopinionated',
|
||||
},
|
||||
messages,
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
Reference in New Issue
Block a user