client/utils/eslint-rules/index.ts
Alois 17db895203
Some checks failed
/ build-web (push) Successful in 7m4s
/ build-desktop (linux) (push) Successful in 11m31s
/ build-mobile (push) Successful in 18m12s
/ release (push) Failing after 3m2s
(feat): add custom lint rules
(qol): update todo
(chore): update licenses
2026-07-24 12:44:08 +02:00

74 lines
1.9 KiB
TypeScript

import type { Rule } from "eslint";
export const noReactNamespaceImport: Rule.RuleModule = {
meta: {
type: "suggestion",
docs: {
description: "Require named imports from React",
},
messages: {
namespaceImport:
"Import only the React exports used by this module instead of using a namespace import.",
},
schema: [],
},
create(context) {
return {
ImportDeclaration(node) {
if (
node.source.value === "react" &&
node.specifiers.some(
(specifier) => specifier.type === "ImportNamespaceSpecifier",
)
) {
context.report({ node, messageId: "namespaceImport" });
}
},
};
},
};
function isPropertyNamed(
member: {
computed: boolean;
property: { type: string; name?: string; value?: unknown };
},
name: string,
): boolean {
return member.computed
? member.property.type === "Literal" && member.property.value === name
: member.property.type === "Identifier" && member.property.name === name;
}
export const noWindowLocationReload: Rule.RuleModule = {
meta: {
type: "problem",
docs: {
description: "Disallow reloads that bypass TanStack Router",
},
messages: {
reload:
"Do not use window.location.reload(); use TanStack Router navigation instead.",
},
schema: [],
},
create(context) {
return {
CallExpression(node) {
const callee = node.callee;
if (
callee.type !== "MemberExpression" ||
!isPropertyNamed(callee, "reload") ||
callee.object.type !== "MemberExpression" ||
!isPropertyNamed(callee.object, "location") ||
callee.object.object.type !== "Identifier" ||
callee.object.object.name !== "window"
) {
return;
}
context.report({ node, messageId: "reload" });
},
};
},
};