mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
[Migration 0-2] Enable ESLint import/no-cycle + boundaries rules (#3349)
Enable ESLint import/no-cycle and architecture boundary rules Add eslint-plugin-boundaries with element-types matching ARCH_REDESIGN §8, enable import/no-cycle (error in client/, warn in lib/ and ui/), extend consistent-default-export-name to client/**/*.tsx, and document §10 types/api.ts enforcement as a follow-up.
This commit is contained in:
+116
-1
@@ -3,6 +3,7 @@ import jsPlugin from '@eslint/js';
|
||||
import nextJsPlugin from '@next/eslint-plugin-next';
|
||||
import stylisticPlugin from '@stylistic/eslint-plugin';
|
||||
import reactQueryPlugin from '@tanstack/eslint-plugin-query';
|
||||
import boundariesPlugin from 'eslint-plugin-boundaries';
|
||||
import consistentDefaultExportNamePlugin from 'eslint-plugin-consistent-default-export-name';
|
||||
import importPlugin from 'eslint-plugin-import';
|
||||
import importHelpersPlugin from 'eslint-plugin-import-helpers';
|
||||
@@ -57,6 +58,20 @@ const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const gitignorePath = path.resolve(__dirname, '.gitignore');
|
||||
|
||||
/** @see client/ARCH_REDESIGN.md §8 — dependency layers for migrated code */
|
||||
const ARCH_BOUNDARY_ELEMENTS = [
|
||||
{ type: 'client-api', pattern: 'client/api/**', mode: 'full' },
|
||||
{ type: 'client-slices', pattern: 'client/slices/**', mode: 'full' },
|
||||
{ type: 'client-features', pattern: 'client/features/**', mode: 'full' },
|
||||
{ type: 'client-shared', pattern: 'client/shared/**', mode: 'full' },
|
||||
{ type: 'client-shell', pattern: 'client/shell/**', mode: 'full' },
|
||||
{ type: 'configs', pattern: 'configs/**', mode: 'full' },
|
||||
{ type: 'toolkit', pattern: 'toolkit/**', mode: 'full' },
|
||||
{ type: 'nextjs', pattern: 'nextjs/**', mode: 'full' },
|
||||
{ type: 'legacy-lib', pattern: 'lib/**', mode: 'full' },
|
||||
{ type: 'legacy-ui', pattern: 'ui/**', mode: 'full' },
|
||||
];
|
||||
|
||||
/** @type {import('eslint').Linter.Config[]} */
|
||||
export default tseslint.config(
|
||||
includeIgnoreFile(gitignorePath),
|
||||
@@ -72,7 +87,12 @@ export default tseslint.config(
|
||||
|
||||
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } },
|
||||
|
||||
{ settings: { react: { version: 'detect' } } },
|
||||
{
|
||||
settings: {
|
||||
react: { version: 'detect' },
|
||||
'boundaries/elements': ARCH_BOUNDARY_ELEMENTS,
|
||||
},
|
||||
},
|
||||
|
||||
jsPlugin.configs.recommended,
|
||||
|
||||
@@ -288,6 +308,100 @@ export default tseslint.config(
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
files: [ 'client/**' ],
|
||||
plugins: {
|
||||
'import': importPlugin,
|
||||
},
|
||||
rules: {
|
||||
'import/no-cycle': [ 'error', { maxDepth: 10 } ],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
files: [ 'lib/**', 'ui/**' ],
|
||||
plugins: {
|
||||
'import': importPlugin,
|
||||
},
|
||||
rules: {
|
||||
'import/no-cycle': 'warn',
|
||||
},
|
||||
},
|
||||
|
||||
/*
|
||||
* ARCH_REDESIGN.md §10 — public type surface: consumers should import slice/feature types only from
|
||||
* `types/api.ts`. eslint-plugin-boundaries can enforce this with `capture` on element patterns and
|
||||
* targeted `disallow` rules; that is left for a follow-up once more slices/features exist under client/.
|
||||
* Type-only cross-layer imports are approximated via per-rule `importKind: 'type'` (v4 has no `allowTypeImports` option).
|
||||
*/
|
||||
{
|
||||
files: [
|
||||
'client/**/*.{ts,tsx}',
|
||||
'configs/**/*.{ts,tsx,mjs}',
|
||||
],
|
||||
plugins: {
|
||||
boundaries: boundariesPlugin,
|
||||
},
|
||||
rules: {
|
||||
'boundaries/element-types': [ 'error', {
|
||||
'default': 'disallow',
|
||||
rules: [
|
||||
{
|
||||
from: 'client-api',
|
||||
allow: [ 'client-shared', 'legacy-lib' ],
|
||||
},
|
||||
{
|
||||
from: 'client-api',
|
||||
allow: [ 'client-slices', 'client-features' ],
|
||||
importKind: 'type',
|
||||
},
|
||||
{
|
||||
from: 'client-slices',
|
||||
allow: [ 'client-api', 'client-shared', 'client-slices', 'legacy-lib', 'legacy-ui', 'toolkit', 'configs' ],
|
||||
},
|
||||
{
|
||||
from: 'client-slices',
|
||||
allow: [ 'client-features' ],
|
||||
importKind: 'type',
|
||||
},
|
||||
{
|
||||
from: 'client-features',
|
||||
allow: [ 'client-api', 'client-shared', 'client-slices', 'client-features', 'legacy-lib', 'legacy-ui', 'toolkit', 'configs' ],
|
||||
},
|
||||
{
|
||||
from: 'client-shared',
|
||||
allow: [ 'client-shared', 'legacy-lib', 'legacy-ui', 'toolkit', 'configs' ],
|
||||
},
|
||||
{
|
||||
from: 'client-shared',
|
||||
allow: [ 'client-slices' ],
|
||||
importKind: 'type',
|
||||
},
|
||||
{
|
||||
from: 'client-shell',
|
||||
allow: [
|
||||
'client-api',
|
||||
'client-slices',
|
||||
'client-features',
|
||||
'client-shared',
|
||||
'client-shell',
|
||||
'legacy-lib',
|
||||
'legacy-ui',
|
||||
'toolkit',
|
||||
'nextjs',
|
||||
'configs',
|
||||
],
|
||||
},
|
||||
{
|
||||
from: 'configs',
|
||||
// `configs` must not import `client/*`; `lib/*` stays allowed until config-owned types move out of legacy paths
|
||||
allow: [ 'configs', 'legacy-lib' ],
|
||||
},
|
||||
],
|
||||
} ],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
plugins: {
|
||||
'import-helpers': importHelpersPlugin,
|
||||
@@ -338,6 +452,7 @@ export default tseslint.config(
|
||||
},
|
||||
files: [
|
||||
'ui/**/[A-Z]*.tsx',
|
||||
'client/**/*.tsx',
|
||||
],
|
||||
ignores: [
|
||||
'**/*.pw.*',
|
||||
|
||||
@@ -179,6 +179,7 @@
|
||||
"dotenv-cli": "^6.0.0",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-next": "16.1.7",
|
||||
"eslint-plugin-boundaries": "^4.2.2",
|
||||
"eslint-plugin-consistent-default-export-name": "^0.0.15",
|
||||
"eslint-plugin-import": "2.31.0",
|
||||
"eslint-plugin-import-helpers": "2.0.1",
|
||||
|
||||
Generated
+62
@@ -417,6 +417,9 @@ importers:
|
||||
eslint-config-next:
|
||||
specifier: 16.1.7
|
||||
version: 16.1.7(@typescript-eslint/[email protected]([email protected])([email protected]))([email protected])([email protected])
|
||||
eslint-plugin-boundaries:
|
||||
specifier: ^4.2.2
|
||||
version: 4.2.2(@typescript-eslint/[email protected]([email protected])([email protected]))([email protected])
|
||||
eslint-plugin-consistent-default-export-name:
|
||||
specifier: ^0.0.15
|
||||
version: 0.0.15
|
||||
@@ -8532,6 +8535,33 @@ packages:
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==}
|
||||
engines: {node: '>=4'}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': '*'
|
||||
eslint: '*'
|
||||
eslint-import-resolver-node: '*'
|
||||
eslint-import-resolver-typescript: '*'
|
||||
eslint-import-resolver-webpack: '*'
|
||||
peerDependenciesMeta:
|
||||
'@typescript-eslint/parser':
|
||||
optional: true
|
||||
eslint:
|
||||
optional: true
|
||||
eslint-import-resolver-node:
|
||||
optional: true
|
||||
eslint-import-resolver-typescript:
|
||||
optional: true
|
||||
eslint-import-resolver-webpack:
|
||||
optional: true
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-cjwpZqkCXgfz953bc74uDetOtGVxwgMgNZ7hAKi6Oxck+x4oY6Z/9DzgPqAYhtQdSNHFVg+vhft/lSL+snPMQg==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
eslint: '>=6.0.0'
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-gqW7dnJbWMxI5H6/Pyz6Sl/vBMwOktePMI2iuuKPb4N82uvemUkfaWhsRZCKndSzpIVaCZ9wdspCVO1tm0wXJQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -10289,6 +10319,10 @@ packages:
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==}
|
||||
engines: {node: '>=8.6'}
|
||||
|
||||
[email protected]:
|
||||
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
|
||||
engines: {node: '>=8.6'}
|
||||
@@ -25836,6 +25870,29 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
[email protected](@typescript-eslint/[email protected]([email protected])([email protected]))([email protected])([email protected]):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.57.1([email protected])([email protected])
|
||||
eslint: 9.39.2
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
[email protected](@typescript-eslint/[email protected]([email protected])([email protected]))([email protected]):
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
eslint: 9.39.2
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.8.1(@typescript-eslint/[email protected]([email protected])([email protected]))([email protected])([email protected])
|
||||
micromatch: 4.0.7
|
||||
transitivePeerDependencies:
|
||||
- '@typescript-eslint/parser'
|
||||
- eslint-import-resolver-typescript
|
||||
- eslint-import-resolver-webpack
|
||||
- supports-color
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
lodash: 4.17.23
|
||||
@@ -28037,6 +28094,11 @@ snapshots:
|
||||
|
||||
[email protected]: {}
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
braces: 3.0.3
|
||||
picomatch: 2.3.1
|
||||
|
||||
[email protected]:
|
||||
dependencies:
|
||||
braces: 3.0.3
|
||||
|
||||
Reference in New Issue
Block a user