Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,15 @@ This plugin provides rules to enforce modular architecture boundaries in Vue.js

### Dependency Rules

| Rule | Description |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| [feature-imports](./docs/rules/feature-imports.md) | Features should only import from the `shared/` layer or their own internal files. |
| [shared-imports](./docs/rules/shared-imports.md) | `shared/` folder cannot import from `features/` or `views/`. |
| [app-imports](./docs/rules/app-imports.md) | `app/` folder can import from `shared/` and `features/` (exception: `app/router.ts` may import feature route files). |
| app-imports | `app/` folder can import from `shared/` and `features/` (exception: `app/router.ts` may import feature route files to compose the global router). |
| imports-absolute-alias | Use absolute imports with `@/` alias for cross-layer imports and shared resources. |
| imports-no-deep-relative | Avoid relative imports with more than 2 levels (`../../../`) - use absolute instead. |
| imports-from-index | Import from `index.ts` files when available. |
| imports-grouping | Group imports: Vue imports, third-party imports, internal imports. |
| Rule | Description |
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| [feature-imports](./docs/rules/feature-imports.md) | Features should only import from the `shared/` layer or their own internal files. |
| [shared-imports](./docs/rules/shared-imports.md) | `shared/` folder cannot import from `features/` or `views/`. |
| [app-imports](./docs/rules/app-imports.md) | `app/` folder can import from `shared/` and `features/` (exception: `app/router.ts` may import feature route files). |
| imports-absolute-alias | Use absolute imports with `@/` alias for cross-layer imports and shared resources. |
| imports-no-deep-relative | Avoid relative imports with more than 2 levels (`../../../`) - use absolute instead. |
| imports-from-index | Import from `index.ts` files when available. |
| imports-grouping | Group imports: Vue imports, third-party imports, internal imports. |

### Component Rules

Expand Down
13 changes: 7 additions & 6 deletions docs/rules/app-imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ relative paths and reports when an import targets a non-shared, non-public
feature path.

The rule skips checks when the current filename cannot be resolved to a
project-relative path or when the filename matches an `ignores` pattern. The
router special-case is respected: `app/router.ts` may import feature route files
so the global router can be composed from feature routes.
project-relative path or when the filename matches an `ignores` pattern.
The router special-case is respected: `app/router.ts` may import feature route
files so the global router can be composed from feature routes.

How it works

Expand All @@ -35,9 +35,10 @@ How it works

The rule accepts an optional options object with the following properties:

- `ignores` (string[], default: `['**/*.spec.*', '**/*.test.*', '**/*.stories.*']`) —
minimatch patterns that skip files from rule checks when they match the
resolved project-relative filename.
- `ignores` (string[], default: `[]`) — minimatch patterns that skip files from
rule checks when they match the resolved project-relative filename. Typical
projects add patterns for test files, storybook files, or temporary folders
(for example `['**/*.spec.*', '**/*.test.*', '**/*.stories.*']`).

Note: project-level settings control `rootPath`, `rootAlias`, `appPath`,
`sharedPath`, and `featuresPath`. Configure these via `settings['vue-modular']`.
Expand Down
3 changes: 3 additions & 0 deletions src/rules/app-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export const appImports = createRule<VueModularRuleModule>({
const resolvedPath = resolveImportPath(filename, importPath, projectOptions.rootPath, projectOptions.rootAlias)
if (!resolvedPath) return

// Allow relative imports within app/
if (resolvedPath.startsWith(projectOptions.appPath)) return

// Special case: allow app/router.ts to import feature route files
const isRouterFile = filename === `${projectOptions.appPath}/router.ts`
if (isRouterFile) {
Expand Down
4 changes: 4 additions & 0 deletions tests/rules/app-imports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ describe('app-imports', () => {
{ code: "import fm from '@/features/auth/index'", filename: 'src/app/main.ts' },
{ code: "import fm from '@/features/auth/index.ts'", filename: 'src/app/main.ts' },
{ code: "import x from '@/utils/local'", filename: 'src/app/main.ts', options: [{ ignores: ['**/app/main.ts'] }] },
// allow relative imports within app/
{ code: "import x from './local'", filename: 'src/app/main.ts' },
{ code: "import x from '../app/local'", filename: 'src/app/main.ts' },
{ code: "import x from '@/app/local'", filename: 'src/app/main.ts' },
],
invalid: [
{
Expand Down