Skip to content

Commit 227f170

Browse files
DaltheCowmarkurtzCopilot
authored
Migrate eslint config (#214)
Co-authored-by: Mark Kurtz <mark.j.kurtz@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent f1dfdc6 commit 227f170

File tree

36 files changed

+1213
-323
lines changed

36 files changed

+1213
-323
lines changed

README.md

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -159,41 +159,7 @@ GuideLLM UI is a companion frontend for visualizing the results of a GuideLLM be
159159

160160
### 🛠 Running the UI
161161

162-
1. Use the Hosted Build (Recommended for Most Users)
163-
164-
After running a benchmark with GuideLLM, a report.html file will be generated (by default at guidellm_report/report.html). This file references the latest stable version of the UI hosted at:
165-
166-
```
167-
https://neuralmagic.github.io/guidellm/ui/dev/
168-
```
169-
170-
Open the file in your browser and you're done—no setup required.
171-
172-
2. Build and Serve the UI Locally (For Development) This option is useful if:
173-
174-
- You are actively developing the UI
175-
176-
- You want to test changes to the UI before publishing
177-
178-
- You want full control over how the report is displayed
179-
180-
```bash
181-
npm install
182-
npm run build
183-
npx serve out
184-
```
185-
186-
This will start a local server (e.g., at http://localhost:3000). Then, in your GuideLLM config or CLI flags, point to this local server as the asset base for report generation.
187-
188-
### 🧪 Development Notes
189-
190-
During UI development, it can be helpful to view sample data. We include a sample benchmark run wired into the Redux store under:
191-
192-
```
193-
src/lib/store/[runInfo/workloadDetails/benchmarks]WindowData.ts
194-
```
195-
196-
In the future this will be replaced by a configurable untracked file for dev use.
162+
The UI is a WIP, check more recent PRs for the latest updates
197163

198164
## Resources
199165

eslint.config.js

Lines changed: 115 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,72 @@
11
// @ts-check
22

33
import eslint from '@eslint/js';
4-
import typescriptPlugin from '@typescript-eslint/eslint-plugin';
5-
import typescriptParser from '@typescript-eslint/parser';
6-
import { FlatCompat } from '@eslint/eslintrc';
7-
import reactPlugin from 'eslint-plugin-react';
8-
import hooksPlugin from 'eslint-plugin-react-hooks';
4+
import nextPlugin from '@next/eslint-plugin-next';
5+
import prettierConfig from 'eslint-config-prettier';
6+
import cypressPlugin from 'eslint-plugin-cypress';
97
import importPlugin from 'eslint-plugin-import';
108
import jestPlugin from 'eslint-plugin-jest';
11-
import noSecretsPlugin from 'eslint-plugin-no-secrets';
129
import prettierPlugin from 'eslint-plugin-prettier';
13-
import prettierConfig from 'eslint-config-prettier';
10+
import reactPlugin from 'eslint-plugin-react';
11+
import hooksPlugin from 'eslint-plugin-react-hooks';
1412
import globals from 'globals';
1513
import path from 'node:path';
1614
import { fileURLToPath } from 'node:url';
15+
import tseslint from 'typescript-eslint';
1716

17+
// --- SETUP ---
18+
// Recreate __dirname for ES modules
1819
const __filename = fileURLToPath(import.meta.url);
1920
const __dirname = path.dirname(__filename);
2021

21-
const compat = new FlatCompat({
22-
baseDirectory: __dirname,
23-
recommendedConfig: eslint.configs.recommended,
24-
});
22+
// --- EXPORT ESLINT CONFIG ---
23+
export default tseslint.config(
24+
// 1. Global Ignores
25+
{
26+
ignores: ['node_modules/', '.next/', 'dist/', 'coverage/', '.DS_Store'],
27+
},
2528

26-
export default [
27-
// Base configuration
29+
// 2. Base Configurations (Applied to all files)
2830
eslint.configs.recommended,
31+
prettierConfig, // Disables ESLint rules that conflict with Prettier. IMPORTANT: Must be after other configs.
2932

30-
// Next.js configuration using FlatCompat
31-
...compat.extends('next/core-web-vitals'),
32-
33-
// --- Main Configuration ---
33+
// 3. Configuration for App Source Code (Next.js with Type-Aware Linting)
3434
{
35-
files: ['src/**/*.{js,jsx,ts,tsx}', 'tests/**/*.{js,jsx,ts,tsx}'],
35+
files: ['src/ui/**/*.{ts,tsx}'],
3636
languageOptions: {
37-
parser: typescriptParser,
38-
ecmaVersion: 2024,
39-
sourceType: 'module',
37+
parser: tseslint.parser,
38+
parserOptions: {
39+
project: true, // Enable type-aware linting
40+
tsconfigRootDir: __dirname,
41+
},
4042
globals: {
4143
...globals.browser,
42-
...globals.node,
43-
...globals.jest,
44-
},
45-
parserOptions: {
46-
ecmaFeatures: {
47-
jsx: true,
48-
},
49-
project: [
50-
'./src/ui/tsconfig.json',
51-
'./tsconfig.test.json',
52-
'./tsconfig.cypress.json',
53-
],
54-
tsconfigRootDir: import.meta.dirname,
55-
noWarnOnMultipleProjects: true,
44+
...globals.node, // Add Node.js globals for `process` etc.
5645
},
5746
},
5847
plugins: {
59-
'@typescript-eslint': typescriptPlugin,
48+
'@typescript-eslint': tseslint.plugin,
49+
'@next/next': nextPlugin,
50+
import: importPlugin,
6051
react: reactPlugin,
6152
'react-hooks': hooksPlugin,
62-
import: importPlugin,
63-
jest: jestPlugin,
64-
'no-secrets': noSecretsPlugin,
6553
prettier: prettierPlugin,
6654
},
6755
rules: {
68-
// Ccustom rules
69-
complexity: ['warn', { max: 8 }],
70-
curly: ['error', 'all'],
56+
// --- Base rules to disable in favor of TS versions ---
7157
'no-unused-vars': 'off',
7258

73-
// TypeScript rules
59+
// --- Recommended rules from plugins ---
60+
...tseslint.configs.recommendedTypeChecked.rules,
61+
...nextPlugin.configs.recommended.rules,
62+
...nextPlugin.configs['core-web-vitals'].rules,
63+
...reactPlugin.configs.recommended.rules,
64+
...hooksPlugin.configs.recommended.rules,
65+
66+
// --- Prettier ---
67+
'prettier/prettier': 'error',
68+
69+
// --- Custom Rules & Overrides ---
7470
'@typescript-eslint/no-unused-vars': [
7571
'warn',
7672
{
@@ -79,103 +75,103 @@ export default [
7975
caughtErrorsIgnorePattern: '^_',
8076
},
8177
],
78+
'@typescript-eslint/no-floating-promises': 'error',
79+
'@typescript-eslint/no-misused-promises': 'error',
8280
'@typescript-eslint/no-explicit-any': 'warn',
8381

84-
// Next.js overrides
85-
'@next/next/no-img-element': 'off', // Allow img tags if needed
86-
'@next/next/no-page-custom-font': 'warn',
87-
88-
// React rules
89-
'react/react-in-jsx-scope': 'off', // Not needed in Next.js
90-
'react/prop-types': 'off', // Using TypeScript
91-
'react-hooks/rules-of-hooks': 'error',
92-
'react-hooks/exhaustive-deps': 'warn',
93-
94-
// Import rules
95-
'import/no-extraneous-dependencies': [
96-
'error',
97-
{
98-
devDependencies: [
99-
'**/*.test.{js,jsx,ts,tsx}',
100-
'**/*.d.ts',
101-
'**/*.interfaces.ts',
102-
'**/*.setup.{js,ts}',
103-
'**/*.config.{js,mjs,ts}',
104-
'tests/**/*',
105-
'cypress/**/*',
106-
],
107-
optionalDependencies: false,
108-
peerDependencies: false,
109-
},
110-
],
11182
'import/order': [
11283
'error',
11384
{
114-
groups: [
115-
['builtin', 'external'],
116-
['internal', 'parent', 'sibling', 'index'],
117-
],
118-
'newlines-between': 'always-and-inside-groups',
119-
pathGroups: [
120-
{
121-
pattern:
122-
'@{app,assets,classes,components,hooks,lib,pages,store,tests,types,utils}/**',
123-
group: 'internal',
124-
position: 'before',
125-
},
126-
{
127-
pattern: '{.,..}/**',
128-
group: 'internal',
129-
position: 'after',
130-
},
131-
],
132-
pathGroupsExcludedImportTypes: ['builtin'],
85+
groups: [['builtin', 'external'], 'internal', ['parent', 'sibling', 'index']],
86+
'newlines-between': 'always',
13387
alphabetize: { order: 'asc', caseInsensitive: true },
13488
},
13589
],
13690

137-
// Security
138-
'no-secrets/no-secrets': ['error', { additionalRegexes: {}, ignoreContent: [] }],
91+
'react/react-in-jsx-scope': 'off',
92+
'react/prop-types': 'off',
13993

140-
// Prettier
141-
'prettier/prettier': 'error',
94+
'@next/next/no-html-link-for-pages': 'off',
95+
'@next/next/no-img-element': 'off',
96+
97+
complexity: ['warn', { max: 8 }],
14298
},
14399
settings: {
144-
next: {
145-
rootDir: ['src/ui/', 'tests/ui/'],
146-
},
147-
'import/resolver': {
148-
typescript: {
149-
project: [
150-
'./src/ui/tsconfig.json',
151-
'./tsconfig.test.json',
152-
'./tsconfig.cypress.json',
153-
],
154-
noWarnOnMultipleProjects: true,
155-
},
100+
react: { version: 'detect' },
101+
'import/resolver': { typescript: true, node: true },
102+
},
103+
},
104+
105+
// 4. Configuration for Jest Test Files (Type-Aware)
106+
{
107+
files: ['tests/ui/**/*.{test,spec}.{ts,tsx}', 'jest.setup.ts'],
108+
languageOptions: {
109+
parser: tseslint.parser, // Explicitly set parser
110+
parserOptions: {
111+
project: './tsconfig.test.json',
112+
tsconfigRootDir: __dirname,
156113
},
157-
react: {
158-
version: 'detect',
114+
globals: {
115+
...globals.jest,
116+
...globals.node, // FIX: Add Node.js globals for `global`, etc.
159117
},
160118
},
119+
plugins: {
120+
jest: jestPlugin,
121+
},
122+
rules: {
123+
...jestPlugin.configs['flat/recommended'].rules,
124+
'@typescript-eslint/unbound-method': 'off',
125+
},
161126
},
162127

163-
// Jest-specific rules for test files
128+
// 5. Configuration for Cypress E2E Test Files (Type-Aware)
164129
{
165130
files: [
166-
'tests/**/*.{js,jsx,ts,tsx}',
167-
'**/*.test.{js,jsx,ts,tsx}',
168-
'**/*.spec.{js,jsx,ts,tsx}',
131+
'tests/ui/cypress/**/*.{cy,e2e}.{ts,tsx}',
132+
'tests/ui/cypress/support/**/*.ts',
169133
],
134+
languageOptions: {
135+
parser: tseslint.parser, // Explicitly set parser
136+
parserOptions: {
137+
project: './tsconfig.cypress.json',
138+
tsconfigRootDir: __dirname,
139+
},
140+
// FIX: This is the correct way to get globals from the Cypress plugin's recommended config.
141+
globals: cypressPlugin.configs.recommended.languageOptions.globals,
142+
},
143+
plugins: {
144+
cypress: cypressPlugin,
145+
},
146+
// Apply recommended rules and then add our overrides
170147
rules: {
171-
'jest/expect-expect': 'error',
172-
'jest/no-focused-tests': 'error',
173-
'jest/no-identical-title': 'error',
174-
'jest/prefer-to-have-length': 'warn',
175-
'jest/valid-expect': 'error',
148+
...cypressPlugin.configs.recommended.rules,
149+
'jest/expect-expect': 'off',
150+
'jest/no-standalone-expect': 'off',
151+
'@typescript-eslint/no-floating-promises': 'off',
176152
},
177153
},
178154

179-
// Prettier config (disables conflicting rules)
180-
prettierConfig,
181-
];
155+
// 6. Configuration for JS/TS config files
156+
{
157+
files: ['**/*.config.{js,mjs,ts}'],
158+
languageOptions: {
159+
globals: {
160+
...globals.node,
161+
},
162+
},
163+
rules: {
164+
'@typescript-eslint/no-var-requires': 'off',
165+
},
166+
},
167+
168+
// 7. Configuration for JS/TS mock files and test helpers
169+
{
170+
files: ['tests/ui/**/__mocks__/**/*.{js,ts}', 'tests/ui/unit/mocks/**/*.ts'],
171+
languageOptions: {
172+
globals: {
173+
...globals.node,
174+
},
175+
},
176+
}
177+
);

jest.setup.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ jest.mock('next/dynamic', () => ({
1111
const dynamicModule = jest.requireActual('next/dynamic');
1212
const dynamicActualComp = dynamicModule.default;
1313
const RequiredComponent = dynamicActualComp(props[0]);
14-
// eslint-disable-next-line no-unused-expressions, @typescript-eslint/no-unused-expressions
1514
RequiredComponent.preload
1615
? RequiredComponent.preload()
1716
: RequiredComponent.render.preload();

0 commit comments

Comments
 (0)