89 lines
2.8 KiB
JavaScript
89 lines
2.8 KiB
JavaScript
/**
|
|
* Enforces FSD-style layering for quinn.api.
|
|
*
|
|
* app → anything
|
|
* surfaces → features, entities (via index), shared
|
|
* features → entities (via index), shared
|
|
* entities → shared, other entities (via index only)
|
|
* shared → shared only
|
|
*
|
|
* Same-layer cross-imports between siblings (e.g. surfaces/my → surfaces/admin)
|
|
* are forbidden. Entities must be consumed through their barrel `index.ts` —
|
|
* no reaching into `repo.ts` or `schema.ts` from outside the entity folder.
|
|
*/
|
|
module.exports = {
|
|
forbidden: [
|
|
{
|
|
name: 'no-shared-to-upper',
|
|
severity: 'error',
|
|
comment: 'shared/ is the floor — it may not import from any domain layer.',
|
|
from: { path: '^src/shared' },
|
|
to: { path: '^src/(app|surfaces|features|entities)' },
|
|
},
|
|
{
|
|
name: 'no-entities-to-upper',
|
|
severity: 'error',
|
|
comment: 'entities/ may not depend on features, surfaces, or app.',
|
|
from: { path: '^src/entities' },
|
|
to: { path: '^src/(app|surfaces|features)' },
|
|
},
|
|
{
|
|
name: 'no-features-to-upper',
|
|
severity: 'error',
|
|
comment: 'features/ may not depend on surfaces or app.',
|
|
from: { path: '^src/features' },
|
|
to: { path: '^src/(app|surfaces)' },
|
|
},
|
|
{
|
|
name: 'no-surfaces-to-app',
|
|
severity: 'error',
|
|
from: { path: '^src/surfaces' },
|
|
to: { path: '^src/app' },
|
|
},
|
|
{
|
|
name: 'no-cross-surface',
|
|
severity: 'error',
|
|
comment: 'A surface must not import from a sibling surface.',
|
|
from: { path: '^src/surfaces/([^/]+)/' },
|
|
to: {
|
|
path: '^src/surfaces/([^/]+)/',
|
|
pathNot: '^src/surfaces/$1/',
|
|
},
|
|
},
|
|
{
|
|
name: 'no-cross-feature',
|
|
severity: 'error',
|
|
comment: 'Features are leaves — they compose entities, not each other.',
|
|
from: { path: '^src/features/([^/]+)/' },
|
|
to: {
|
|
path: '^src/features/([^/]+)/',
|
|
pathNot: '^src/features/$1/',
|
|
},
|
|
},
|
|
{
|
|
name: 'entities-consumed-via-barrel',
|
|
severity: 'error',
|
|
comment: 'Outside an entity, only its index.ts is public API.',
|
|
from: { pathNot: '^src/entities/([^/]+)/' },
|
|
to: { path: '^src/entities/[^/]+/(?!index\\.ts$).+' },
|
|
},
|
|
{
|
|
name: 'entity-to-entity-via-barrel',
|
|
severity: 'error',
|
|
comment: 'Entities may reference other entities only through their barrel.',
|
|
from: { path: '^src/entities/([^/]+)/' },
|
|
to: {
|
|
path: '^src/entities/([^/]+)/(?!index\\.ts$).+',
|
|
pathNot: '^src/entities/$1/',
|
|
},
|
|
},
|
|
],
|
|
options: {
|
|
doNotFollow: { path: 'node_modules' },
|
|
tsConfig: { fileName: 'tsconfig.json' },
|
|
enhancedResolveOptions: {
|
|
exportsFields: ['exports'],
|
|
conditionNames: ['import', 'require', 'node', 'default'],
|
|
},
|
|
},
|
|
};
|