263 lines
6.6 KiB
Markdown
263 lines
6.6 KiB
Markdown
|
|
# ESLint 9 Migration Documentation
|
||
|
|
|
||
|
|
**Date**: 2024-12-28
|
||
|
|
**Status**: ✅ Completed
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This document describes the migration from ESLint 8 to ESLint 9, including the new flat config format and all changes made to the codebase.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## What Changed
|
||
|
|
|
||
|
|
### 1. ESLint Version Upgrade
|
||
|
|
- **Before**: ESLint 8.57.1
|
||
|
|
- **After**: ESLint 9.17.0
|
||
|
|
- **Location**: Root `package.json` and all app/service `package.json` files
|
||
|
|
|
||
|
|
### 2. TypeScript ESLint Upgrade
|
||
|
|
- **Before**: `@typescript-eslint/eslint-plugin@^6.0.0` and `@typescript-eslint/parser@^6.0.0`
|
||
|
|
- **After**: `@typescript-eslint/eslint-plugin@^8.18.0` and `@typescript-eslint/parser@^8.18.0`
|
||
|
|
- **Reason**: ESLint 9 compatibility
|
||
|
|
|
||
|
|
### 3. Configuration Format
|
||
|
|
- **Before**: `.eslintrc.js` (CommonJS, legacy format)
|
||
|
|
- **After**: `eslint.config.js` (ES modules, flat config)
|
||
|
|
|
||
|
|
### 4. New Dependencies
|
||
|
|
- `@eslint/js@^9.17.0` - Core ESLint recommended configs
|
||
|
|
- `typescript-eslint@^8.18.0` - TypeScript ESLint utilities
|
||
|
|
|
||
|
|
### 5. Removed Dependencies
|
||
|
|
- `@types/pino@^7.0.5` - No longer needed (Pino v8 includes built-in types)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## New Configuration Format
|
||
|
|
|
||
|
|
### Flat Config Structure
|
||
|
|
|
||
|
|
The new `eslint.config.js` uses the flat config format:
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
import js from '@eslint/js';
|
||
|
|
import tseslint from 'typescript-eslint';
|
||
|
|
import prettier from 'eslint-config-prettier';
|
||
|
|
import security from 'eslint-plugin-security';
|
||
|
|
import sonarjs from 'eslint-plugin-sonarjs';
|
||
|
|
|
||
|
|
export default tseslint.config(
|
||
|
|
// Base recommended configs
|
||
|
|
js.configs.recommended,
|
||
|
|
...tseslint.configs.recommended,
|
||
|
|
prettier,
|
||
|
|
|
||
|
|
// Custom rules
|
||
|
|
{
|
||
|
|
plugins: { security, sonarjs },
|
||
|
|
languageOptions: {
|
||
|
|
parserOptions: {
|
||
|
|
ecmaVersion: 2022,
|
||
|
|
sourceType: 'module',
|
||
|
|
},
|
||
|
|
},
|
||
|
|
rules: {
|
||
|
|
// Custom rules here
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
// Type-checked config (for packages with tsconfig.json)
|
||
|
|
...tseslint.configs.recommendedTypeChecked,
|
||
|
|
{
|
||
|
|
languageOptions: {
|
||
|
|
parserOptions: {
|
||
|
|
project: true,
|
||
|
|
tsconfigRootDir: import.meta.dirname,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
rules: {
|
||
|
|
'@typescript-eslint/no-floating-promises': 'error',
|
||
|
|
'@typescript-eslint/await-thenable': 'error',
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
// Ignores
|
||
|
|
{
|
||
|
|
ignores: ['node_modules', 'dist', 'build', '.next', 'coverage', '**/*.config.js'],
|
||
|
|
}
|
||
|
|
);
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Key Differences from ESLint 8
|
||
|
|
|
||
|
|
### 1. ES Modules
|
||
|
|
- Uses `import`/`export` instead of `require`/`module.exports`
|
||
|
|
- File must be named `eslint.config.js` (or `eslint.config.mjs`)
|
||
|
|
|
||
|
|
### 2. Flat Config Array
|
||
|
|
- Configuration is an array of config objects
|
||
|
|
- Each object can have different settings
|
||
|
|
- Later configs override earlier ones
|
||
|
|
|
||
|
|
### 3. No `extends` or `plugins` Arrays
|
||
|
|
- Configs are spread directly: `...tseslint.configs.recommended`
|
||
|
|
- Plugins are objects: `plugins: { security, sonarjs }`
|
||
|
|
|
||
|
|
### 4. `ignores` is Separate
|
||
|
|
- `ignores` is a separate config object
|
||
|
|
- Not part of the main rules config
|
||
|
|
|
||
|
|
### 5. Type Checking Rules
|
||
|
|
- Type-checked rules are in a separate config block
|
||
|
|
- Only applied to packages with `tsconfig.json`
|
||
|
|
- Uses `project: true` to auto-detect tsconfig
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Packages Updated
|
||
|
|
|
||
|
|
### Apps
|
||
|
|
- ✅ `apps/mcp-legal` - ESLint 9.17.0
|
||
|
|
- ✅ `apps/mcp-members` - ESLint 9.17.0
|
||
|
|
- ✅ `apps/portal-public` - ESLint 9.17.0
|
||
|
|
- ✅ `apps/portal-internal` - ESLint 9.17.0
|
||
|
|
|
||
|
|
### Services
|
||
|
|
- ✅ `services/identity` - ESLint 9.17.0
|
||
|
|
- ✅ `services/finance` - ESLint 9.17.0
|
||
|
|
- ✅ `services/dataroom` - ESLint 9.17.0
|
||
|
|
- ✅ `services/intake` - ESLint 9.17.0
|
||
|
|
|
||
|
|
### Root
|
||
|
|
- ✅ Root `package.json` - ESLint 9.17.0 + all plugins
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Lint-staged Configuration
|
||
|
|
|
||
|
|
Updated `lint-staged` in root `package.json`:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"lint-staged": {
|
||
|
|
"*.{ts,tsx}": [
|
||
|
|
"eslint --fix --config eslint.config.js",
|
||
|
|
"prettier --write"
|
||
|
|
],
|
||
|
|
"*.{json,md,yaml,yml}": [
|
||
|
|
"prettier --write"
|
||
|
|
]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Note**: ESLint 9 automatically finds `eslint.config.js`, but we specify it explicitly for clarity.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Next.js Compatibility
|
||
|
|
|
||
|
|
Next.js apps use their own ESLint configuration via `next lint`. ESLint 9 is compatible with Next.js 14+.
|
||
|
|
|
||
|
|
### Testing Next.js Apps
|
||
|
|
```bash
|
||
|
|
# Portal Public
|
||
|
|
pnpm --filter @the-order/portal-public lint
|
||
|
|
|
||
|
|
# Portal Internal
|
||
|
|
pnpm --filter @the-order/portal-internal lint
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Migration Checklist
|
||
|
|
|
||
|
|
- [x] Upgrade ESLint to v9
|
||
|
|
- [x] Upgrade TypeScript ESLint to v8
|
||
|
|
- [x] Create `eslint.config.js` (flat config)
|
||
|
|
- [x] Update all app `package.json` files
|
||
|
|
- [x] Update all service `package.json` files
|
||
|
|
- [x] Update `lint-staged` configuration
|
||
|
|
- [x] Test linting across all packages
|
||
|
|
- [x] Test TypeScript compilation
|
||
|
|
- [x] Test builds
|
||
|
|
- [x] Test Next.js apps
|
||
|
|
- [x] Remove old `.eslintrc.js` (optional, can keep for reference)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Breaking Changes
|
||
|
|
|
||
|
|
### 1. Configuration Format
|
||
|
|
- Old `.eslintrc.js` format no longer works
|
||
|
|
- Must use flat config format
|
||
|
|
|
||
|
|
### 2. Plugin Format
|
||
|
|
- Plugins must be compatible with flat config
|
||
|
|
- Some older plugins may not work
|
||
|
|
|
||
|
|
### 3. Type Checking Rules
|
||
|
|
- Type-checked rules require `tsconfig.json`
|
||
|
|
- Packages without `tsconfig.json` won't have type-checking rules
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Issue: "Parsing error: parserOptions.project has been provided"
|
||
|
|
**Solution**: The config now uses conditional type-checking. Packages without `tsconfig.json` use basic rules, packages with `tsconfig.json` get type-checked rules.
|
||
|
|
|
||
|
|
### Issue: "Cannot find module '@eslint/js'"
|
||
|
|
**Solution**: Run `pnpm install` to install new dependencies.
|
||
|
|
|
||
|
|
### Issue: "ESLint config not found"
|
||
|
|
**Solution**: Ensure `eslint.config.js` is in the root directory. ESLint 9 automatically looks for it.
|
||
|
|
|
||
|
|
### Issue: Next.js lint errors
|
||
|
|
**Solution**: Next.js uses its own ESLint config. Ensure `eslint-config-next` is installed and compatible with ESLint 9.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Benefits
|
||
|
|
|
||
|
|
1. **Modern Configuration**: Flat config is the future of ESLint
|
||
|
|
2. **Better Performance**: ESLint 9 is faster than ESLint 8
|
||
|
|
3. **Active Maintenance**: ESLint 8 is deprecated, ESLint 9 is actively maintained
|
||
|
|
4. **Better TypeScript Support**: TypeScript ESLint v8 has improved TypeScript support
|
||
|
|
5. **Security Updates**: ESLint 9 receives security updates
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Rollback Plan
|
||
|
|
|
||
|
|
If issues arise, you can rollback:
|
||
|
|
|
||
|
|
1. Revert `package.json` changes
|
||
|
|
2. Restore `.eslintrc.js`
|
||
|
|
3. Run `pnpm install`
|
||
|
|
4. Test thoroughly
|
||
|
|
|
||
|
|
**Note**: Keep ESLint 8 branch until migration is fully verified.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## References
|
||
|
|
|
||
|
|
- [ESLint 9 Migration Guide](https://eslint.org/docs/latest/use/migrate-to-9.0.0)
|
||
|
|
- [Flat Config Documentation](https://eslint.org/docs/latest/use/configure/configuration-files-new)
|
||
|
|
- [TypeScript ESLint v8 Docs](https://typescript-eslint.io/)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Status
|
||
|
|
|
||
|
|
✅ **Migration Complete**
|
||
|
|
|
||
|
|
All packages have been upgraded to ESLint 9, and the new flat config is working correctly. The old `.eslintrc.js` can be removed after verification.
|
||
|
|
|