From 07856b4bb9abc421b91937ee8211791c8ae2cf29 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Fri, 6 Sep 2024 20:35:55 +0200 Subject: [PATCH] Make linter run by upgrading the ESLint config Signed-off-by: Julius Volz --- web/ui/mantine-ui/.eslintrc.cjs | 21 ---- web/ui/mantine-ui/eslint.config.mjs | 71 +++++++++++ web/ui/mantine-ui/package.json | 7 +- web/ui/mantine-ui/src/App.tsx | 2 +- .../src/pages/query/HistogramHelpers.ts | 2 +- .../mantine-ui/src/pages/query/TreeNode.tsx | 6 +- web/ui/mantine-ui/src/promql/ast.ts | 114 +++++++++--------- .../{cmd => tools}/gen_functions_docs/main.go | 0 .../{cmd => tools}/gen_functions_list/main.go | 0 web/ui/mantine-ui/src/promql/tools/go.mod | 26 ++++ web/ui/mantine-ui/src/promql/tools/go.sum | 107 ++++++++++++++++ web/ui/mantine-ui/src/promql/utils.ts | 113 ++++++++++------- web/ui/package-lock.json | 27 +++++ 13 files changed, 371 insertions(+), 125 deletions(-) delete mode 100644 web/ui/mantine-ui/.eslintrc.cjs create mode 100644 web/ui/mantine-ui/eslint.config.mjs rename web/ui/mantine-ui/src/promql/{cmd => tools}/gen_functions_docs/main.go (100%) rename web/ui/mantine-ui/src/promql/{cmd => tools}/gen_functions_list/main.go (100%) create mode 100644 web/ui/mantine-ui/src/promql/tools/go.mod create mode 100644 web/ui/mantine-ui/src/promql/tools/go.sum diff --git a/web/ui/mantine-ui/.eslintrc.cjs b/web/ui/mantine-ui/.eslintrc.cjs deleted file mode 100644 index cf68b3c90..000000000 --- a/web/ui/mantine-ui/.eslintrc.cjs +++ /dev/null @@ -1,21 +0,0 @@ -module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], - rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - 'no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }], - '@typescript-eslint/no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }], - 'prefer-const': ['error', { destructuring: 'all' }], - }, -} diff --git a/web/ui/mantine-ui/eslint.config.mjs b/web/ui/mantine-ui/eslint.config.mjs new file mode 100644 index 000000000..c3cc58920 --- /dev/null +++ b/web/ui/mantine-ui/eslint.config.mjs @@ -0,0 +1,71 @@ +import { fixupConfigRules } from '@eslint/compat'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default [{ + ignores: ['**/dist', '**/.eslintrc.cjs'], +}, ...fixupConfigRules(compat.extends( + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react-hooks/recommended', +)), { + plugins: { + 'react-refresh': reactRefresh, + }, + + languageOptions: { + globals: { + ...globals.browser, + }, + + parser: tsParser, + }, + + rules: { + 'react-refresh/only-export-components': ['warn', { + allowConstantExport: true, + }], + + // Disable the base rule as it can report incorrect errors + 'no-unused-vars': 'off', + + // Use the TypeScript-specific rule for unused vars + '@typescript-eslint/no-unused-vars': ['warn', { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }], + + 'prefer-const': ['error', { + destructuring: 'all', + }], + }, + }, + // Override for Node.js-based config files + { + files: ['postcss.config.cjs'], // Specify any other config files + languageOptions: { + ecmaVersion: 2021, // Optional, set ECMAScript version + sourceType: 'script', // For CommonJS (non-ESM) modules + globals: { + module: 'readonly', + require: 'readonly', + process: 'readonly', + __dirname: 'readonly', // Include other Node.js globals if needed + }, + }, + }, +]; diff --git a/web/ui/mantine-ui/package.json b/web/ui/mantine-ui/package.json index bb7e5534a..7dfdf80b4 100644 --- a/web/ui/mantine-ui/package.json +++ b/web/ui/mantine-ui/package.json @@ -6,7 +6,8 @@ "scripts": { "start": "vite", "build": "tsc && vite build", - "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "lint": "eslint . --report-unused-disable-directives --max-warnings 0", + "lint:fix": "eslint . --report-unused-disable-directives --max-warnings 0 --fix", "preview": "vite preview", "test": "vitest" }, @@ -49,6 +50,9 @@ "use-query-params": "^2.2.1" }, "devDependencies": { + "@eslint/compat": "^1.1.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.9.1", "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^6.21.0", @@ -57,6 +61,7 @@ "eslint": "^9.9.1", "eslint-plugin-react-hooks": "^5.1.0-rc-e56f4ae3-20240830", "eslint-plugin-react-refresh": "^0.4.11", + "globals": "^15.9.0", "jsdom": "^25.0.0", "postcss": "^8.4.35", "postcss-preset-mantine": "^1.17.0", diff --git a/web/ui/mantine-ui/src/App.tsx b/web/ui/mantine-ui/src/App.tsx index 57701914f..1b15f0180 100644 --- a/web/ui/mantine-ui/src/App.tsx +++ b/web/ui/mantine-ui/src/App.tsx @@ -196,7 +196,7 @@ function App() { useEffect(() => { dispatch(updateSettings({ pathPrefix })); - }, [pathPrefix]); + }, [pathPrefix, dispatch]); const { agentMode, consolesLink } = useSettings(); diff --git a/web/ui/mantine-ui/src/pages/query/HistogramHelpers.ts b/web/ui/mantine-ui/src/pages/query/HistogramHelpers.ts index 0bb76ba42..12dd3e1bd 100644 --- a/web/ui/mantine-ui/src/pages/query/HistogramHelpers.ts +++ b/web/ui/mantine-ui/src/pages/query/HistogramHelpers.ts @@ -137,7 +137,7 @@ export const bucketRangeString = ([ boundaryRule, leftBoundary, rightBoundary, - // eslint-disable-next-line @typescript-eslint/no-unused-vars + _, ]: [number, string, string, string]): string => { return `${leftDelim(boundaryRule)}${leftBoundary} -> ${rightBoundary}${rightDelim(boundaryRule)}`; diff --git a/web/ui/mantine-ui/src/pages/query/TreeNode.tsx b/web/ui/mantine-ui/src/pages/query/TreeNode.tsx index f48bda327..b6a78e9a6 100644 --- a/web/ui/mantine-ui/src/pages/query/TreeNode.tsx +++ b/web/ui/mantine-ui/src/pages/query/TreeNode.tsx @@ -131,13 +131,13 @@ const TreeNode: FC<{ if (error) { reportNodeState && reportNodeState("error"); } - }, [error]); + }, [error, reportNodeState]); useEffect(() => { if (isFetching) { reportNodeState && reportNodeState("running"); } - }, [isFetching]); + }, [isFetching, reportNodeState]); // Update the size and position of tree connector lines based on the node's and its parent's position. useLayoutEffect(() => { @@ -221,7 +221,7 @@ const TreeNode: FC<{ ), labelExamples, }); - }, [data]); + }, [data, reportNodeState]); const innerNode = ( { let cur: ASTNode; - for (cur = n; cur.type === 'parenExpr'; cur = cur.expr) {} + for (cur = n; cur.type === "parenExpr"; cur = cur.expr) { + // Continue traversing until a non-parenthesis expression is found + } return cur.type; }; @@ -34,7 +43,10 @@ const binOpPrecedence = { [binaryOperatorType.atan2]: 2, }; -export const maybeParenthesizeBinopChild = (op: binaryOperatorType, child: ASTNode): ASTNode => { +export const maybeParenthesizeBinopChild = ( + op: binaryOperatorType, + child: ASTNode +): ASTNode => { if (child.type !== nodeType.binaryExpr) { return child; } @@ -73,7 +85,7 @@ export const getNodeChildren = (node: ASTNode): ASTNode[] => { case nodeType.binaryExpr: return [node.lhs, node.rhs]; default: - throw new Error('unsupported node type'); + throw new Error("unsupported node type"); } }; @@ -92,18 +104,19 @@ export const getNodeChild = (node: ASTNode, idx: number) => { case nodeType.binaryExpr: return idx === 0 ? node.lhs : node.rhs; default: - throw new Error('unsupported node type'); + throw new Error("unsupported node type"); } }; export const containsPlaceholders = (node: ASTNode): boolean => - node.type === nodeType.placeholder || getNodeChildren(node).some((n) => containsPlaceholders(n)); + node.type === nodeType.placeholder || + getNodeChildren(node).some((n) => containsPlaceholders(n)); export const nodeValueType = (node: ASTNode): valueType | null => { switch (node.type) { case nodeType.aggregation: return valueType.vector; - case nodeType.binaryExpr: + case nodeType.binaryExpr: { const childTypes = [nodeValueType(node.lhs), nodeValueType(node.rhs)]; if (childTypes.includes(null)) { @@ -116,6 +129,7 @@ export const nodeValueType = (node: ASTNode): valueType | null => { } return valueType.scalar; + } case nodeType.call: return node.func.returnType; case nodeType.matrixSelector: @@ -135,7 +149,7 @@ export const nodeValueType = (node: ASTNode): valueType | null => { case nodeType.vectorSelector: return valueType.vector; default: - throw new Error('invalid node type'); + throw new Error("invalid node type"); } }; @@ -144,50 +158,65 @@ export const childDescription = (node: ASTNode, idx: number): string => { case nodeType.aggregation: if (aggregatorsWithParam.includes(node.op) && idx === 0) { switch (node.op) { - case 'topk': - case 'bottomk': - case 'limitk': - return 'k'; - case 'quantile': - return 'quantile'; - case 'count_values': - return 'target label name'; - case 'limit_ratio': - return 'ratio'; + case "topk": + case "bottomk": + case "limitk": + return "k"; + case "quantile": + return "quantile"; + case "count_values": + return "target label name"; + case "limit_ratio": + return "ratio"; } } - return 'vector to aggregate'; + return "vector to aggregate"; case nodeType.binaryExpr: - return idx === 0 ? 'left-hand side' : 'right-hand side'; + return idx === 0 ? "left-hand side" : "right-hand side"; case nodeType.call: - if (functionArgNames.hasOwnProperty(node.func.name)) { + if (node.func.name in functionArgNames) { const argNames = functionArgNames[node.func.name]; - return argNames[Math.min(functionArgNames[node.func.name].length - 1, idx)]; + return argNames[Math.min(argNames.length - 1, idx)]; } - return 'argument'; + return "argument"; case nodeType.parenExpr: - return 'expression'; + return "expression"; case nodeType.placeholder: - return 'argument'; + return "argument"; case nodeType.subquery: - return 'subquery to execute'; + return "subquery to execute"; case nodeType.unaryExpr: - return 'expression'; + return "expression"; default: - throw new Error('invalid node type'); + throw new Error("invalid node type"); } }; -export const aggregatorsWithParam = ['topk', 'bottomk', 'quantile', 'count_values', 'limitk', 'limit_ratio']; +export const aggregatorsWithParam = [ + "topk", + "bottomk", + "quantile", + "count_values", + "limitk", + "limit_ratio", +]; -export const anyValueType = [valueType.scalar, valueType.string, valueType.matrix, valueType.vector]; +export const anyValueType = [ + valueType.scalar, + valueType.string, + valueType.matrix, + valueType.vector, +]; -export const allowedChildValueTypes = (node: ASTNode, idx: number): valueType[] => { +export const allowedChildValueTypes = ( + node: ASTNode, + idx: number +): valueType[] => { switch (node.type) { case nodeType.aggregation: if (aggregatorsWithParam.includes(node.op) && idx === 0) { - if (node.op === 'count_values') { + if (node.op === "count_values") { return [valueType.string]; } return [valueType.scalar]; @@ -211,7 +240,7 @@ export const allowedChildValueTypes = (node: ASTNode, idx: number): valueType[] case nodeType.unaryExpr: return anyValueType; default: - throw new Error('invalid node type'); + throw new Error("invalid node type"); } }; @@ -225,17 +254,19 @@ export const canAddVarArg = (node: Call): boolean => { }; export const canRemoveVarArg = (node: Call): boolean => { - return node.func.variadic !== 0 && node.args.length >= node.func.argTypes.length; + return ( + node.func.variadic !== 0 && node.args.length >= node.func.argTypes.length + ); }; export const humanizedValueType: Record = { - [valueType.none]: 'none', - [valueType.string]: 'string', - [valueType.scalar]: 'number (scalar)', - [valueType.vector]: 'instant vector', - [valueType.matrix]: 'range vector', + [valueType.none]: "none", + [valueType.string]: "string", + [valueType.scalar]: "number (scalar)", + [valueType.vector]: "instant vector", + [valueType.matrix]: "range vector", }; export const escapeString = (str: string) => { - return str.replace(/([\\"])/g, '\\$1'); + return str.replace(/([\\"])/g, "\\$1"); }; diff --git a/web/ui/package-lock.json b/web/ui/package-lock.json index 00736ad63..56e34e2de 100644 --- a/web/ui/package-lock.json +++ b/web/ui/package-lock.json @@ -62,6 +62,9 @@ "use-query-params": "^2.2.1" }, "devDependencies": { + "@eslint/compat": "^1.1.1", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "^9.9.1", "@types/react": "^18.3.5", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^6.21.0", @@ -70,6 +73,7 @@ "eslint": "^9.9.1", "eslint-plugin-react-hooks": "^5.1.0-rc-e56f4ae3-20240830", "eslint-plugin-react-refresh": "^0.4.11", + "globals": "^15.9.0", "jsdom": "^25.0.0", "postcss": "^8.4.35", "postcss-preset-mantine": "^1.17.0", @@ -169,6 +173,19 @@ } } }, + "mantine-ui/node_modules/globals": { + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.9.0.tgz", + "integrity": "sha512-SmSKyLLKFbSr6rptvP8izbyxJL4ILwqO9Jg23UA0sDlGlu58V59D1//I3vlc0KJphVdUR7vMjHIplYnzBxorQA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "module/codemirror-promql": { "name": "@prometheus-io/codemirror-promql", "version": "0.54.1", @@ -1448,6 +1465,16 @@ "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/compat": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", + "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/config-array": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz",