chore(tooling): enable eslint-plugin-boundaries in apps/app
Adds 'boundaries' to plugins, the layered-architecture matrix to
rules, and the boundaries/elements + boundaries/ignore + boundaries/
include settings per the WS-3 1c audit (Phase A:
dev-docs/WS-3-SESSION-1C-AUDIT.md). Phase B sign-off (Bert):
- Q1=B — `lib → stores` is DISALLOWED in the matrix; lib/axios.ts is
refactored in the next commit.
- Q2 — src/views/** added to boundaries/ignore (dead Vuexy file;
TECH-DELETE-DEAD-VIEWS backlog item lands with the docs commit).
- Q3 — `navigation` allowed to import `types`, `utils` (forward
headroom).
- Q4 — sub-zone enforcement deferred to TECH-WS3-BOUNDARIES-SUBZONES
(lands when WS-3 PR-B brings the §4.2 components/{organizer,portal,
shared} + pages/{(auth),portal,…} structure).
Forward-flag carried into the inline comment: when src/plugins/1.router/
migrates to a top-level src/router/ in a later WS-3 PR, add a
{ type: 'router', pattern: 'src/router/**' } element and a
{ from: 'router', allow: ['types','utils','lib','plugins','stores'] }
rule. Doc-side flag also lands in the ARCH-CONSOLIDATION 1c entry.
Boundaries plugin v6 emits a deprecation warning that the
'element-types' selector format is legacy (v5 syntax); the rule
still works on v5-compatible config and migrating to v6 object-
selector syntax is out of scope per the prompt's "only the two
.eslintrc.cjs changes listed are permitted" constraint. Filing a
TECH-BOUNDARIES-V6-SELECTOR-MIGRATION backlog item (in the docs
commit) so the migration happens deliberately.
Lint count after this commit: 4 errors, all in lib/axios.ts (lines
3, 4, 61, 72 — the 2 static + 2 dynamic store imports). The plugin
treats both static AND dynamic `await import('@/stores/...')` as
boundary edges; this is a deliberate intermediate state. The next
commit (refactor) resolves all 4 to land at lint = 0.
Tests + typecheck verified green (boundary errors are lint-only).
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -32,6 +32,7 @@ module.exports = {
|
||||
'@typescript-eslint',
|
||||
'regex',
|
||||
'regexp',
|
||||
'boundaries',
|
||||
],
|
||||
ignorePatterns: [
|
||||
'src/plugins/iconify/*.js',
|
||||
@@ -200,12 +201,68 @@ module.exports = {
|
||||
],
|
||||
'\\.eslintrc\\.cjs',
|
||||
],
|
||||
|
||||
// Architectural import boundaries (WS-3 1c, audit:
|
||||
// dev-docs/WS-3-SESSION-1C-AUDIT.md). The matrix is layered:
|
||||
// types → utils → lib → composables → stores → components → layouts → pages.
|
||||
// The `lib → stores` edge is intentionally disallowed; lib/axios.ts
|
||||
// uses dynamic `await import('@/stores/...')` for its 4 store reads
|
||||
// so the static-import surface stays clean.
|
||||
// Sub-zone enforcement (components/{organizer,portal,shared}) is a
|
||||
// backlog item (TECH-WS3-BOUNDARIES-SUBZONES); it lands after the
|
||||
// §4.2 consolidation directory layout.
|
||||
// FORWARD-FLAG: when src/plugins/1.router/ migrates to src/router/
|
||||
// in a later WS-3 PR, add `{ type: 'router', pattern: 'src/router/**' }`
|
||||
// to boundaries/elements and `{ from: 'router', allow: ['types',
|
||||
// 'utils', 'lib', 'plugins', 'stores'] }` to the rules.
|
||||
'boundaries/element-types': ['error', {
|
||||
default: 'disallow',
|
||||
rules: [
|
||||
{ from: 'types', allow: ['types'] },
|
||||
{ from: 'utils', allow: ['types', 'utils'] },
|
||||
{ from: 'lib', allow: ['types', 'utils', 'lib'] },
|
||||
{ from: 'plugins', allow: ['types', 'utils', 'lib', 'plugins', 'stores'] },
|
||||
{ from: 'composables', allow: ['types', 'utils', 'lib', 'composables', 'stores'] },
|
||||
{ from: 'stores', allow: ['types', 'utils', 'lib', 'composables', 'stores'] },
|
||||
{ from: 'navigation', allow: ['types', 'utils', 'navigation'] },
|
||||
{ from: 'components', allow: ['types', 'utils', 'lib', 'composables', 'stores', 'components'] },
|
||||
{ from: 'layouts', allow: ['types', 'utils', 'lib', 'composables', 'stores', 'navigation', 'components', 'layouts'] },
|
||||
{ from: 'pages', allow: ['types', 'utils', 'lib', 'composables', 'stores', 'navigation', 'components', 'layouts'] },
|
||||
],
|
||||
}],
|
||||
'boundaries/no-unknown': 'off', // External packages are fine.
|
||||
'boundaries/no-unknown-files': 'off', // The ignore list handles vendor/generated.
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: true,
|
||||
typescript: {},
|
||||
},
|
||||
|
||||
// Element-type assignment: first-match-wins. Order matters.
|
||||
'boundaries/elements': [
|
||||
{ type: 'types', pattern: 'src/types/**' },
|
||||
{ type: 'utils', pattern: 'src/utils/**' },
|
||||
{ type: 'lib', pattern: 'src/lib/**' },
|
||||
{ type: 'plugins', pattern: 'src/plugins/**' },
|
||||
{ type: 'composables', pattern: 'src/composables/**' },
|
||||
{ type: 'stores', pattern: 'src/stores/**' },
|
||||
{ type: 'navigation', pattern: 'src/navigation/**' },
|
||||
{ type: 'components', pattern: 'src/components/**' },
|
||||
{ type: 'layouts', pattern: 'src/layouts/**' },
|
||||
{ type: 'pages', pattern: 'src/pages/**' },
|
||||
],
|
||||
'boundaries/ignore': [
|
||||
'src/@core/**', // vendored Vuexy
|
||||
'src/@layouts/**', // vendored Vuexy
|
||||
'src/views/**', // single dead Vuexy file (zero importers); see TECH-DELETE-DEAD-VIEWS
|
||||
'src/App.vue', // orchestration root
|
||||
'src/main.ts', // orchestration root
|
||||
'src/assets/**', // static media
|
||||
'src/styles/**', // SCSS
|
||||
'**/*.d.ts', // generated declarations
|
||||
],
|
||||
'boundaries/include': ['src/**/*.{ts,vue,tsx}'],
|
||||
},
|
||||
overrides: [
|
||||
// Vue SFCs: the base lines-around-comment rule conflicts with
|
||||
|
||||
Reference in New Issue
Block a user