Files
ISA-Frontend/eslint.config.js
Lorenz Hilpert c4480ca8d5 feat(architecture): enable enforce-module-boundaries with comprehensive rules
- Enable @nx/enforce-module-boundaries ESLint rule
- Add type-based constraints (feature, data-access, ui, shared, util, core, common)
- Add domain-based constraints (oms, crm, remission, checkout, availability, etc.)
- Prevent feature->feature, data-access->data-access dependencies
- Enforce domain isolation (no cross-domain imports)
- Tag all 80+ libraries with scope and type tags
- Create automated tagging script for new libraries
- Configure isa-app violations to be ignored

Rules enforce:
- Feature can import: data-access, ui, shared, util, core, common, icons
- Data-access can import: util, generated, common, core only
- UI can import: util, core, icons only
- Cross-domain imports forbidden (except shared, core, common, ui, utils, icons)
- Generated APIs only importable by data-access libraries
2025-11-20 17:55:04 +01:00

303 lines
9.1 KiB
JavaScript

const nx = require('@nx/eslint-plugin');
const eslintConfigPrettier = require('eslint-config-prettier/flat');
module.exports = [
...nx.configs['flat/base'],
...nx.configs['flat/typescript'],
...nx.configs['flat/javascript'],
{
ignores: [
'**/dist',
'**/vite.config.*.timestamp*',
'**/vitest.config.*.timestamp*',
'**/generated/**',
],
},
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
rules: {
'@nx/enforce-module-boundaries': [
'error',
{
enforceBuildableLibDependency: true,
allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'],
depConstraints: [
// ========================================
// TYPE-BASED CONSTRAINTS (Layer Rules)
// ========================================
// FEATURE libraries can import: data-access, ui, shared, util, core (within same domain)
{
sourceTag: 'type:feature',
onlyDependOnLibsWithTags: [
'type:data-access',
'type:ui',
'type:shared',
'type:util',
'type:core',
'type:common',
'type:icon',
],
},
// DATA-ACCESS libraries can import: util, generated, common-data-access only
{
sourceTag: 'type:data-access',
onlyDependOnLibsWithTags: [
'type:util',
'type:generated',
'type:common',
'type:core',
],
bannedExternalImports: [],
},
// DATA-ACCESS cannot import other DATA-ACCESS (except common)
{
sourceTag: 'type:data-access',
notDependOnLibsWithTags: ['type:data-access'],
allowedExternalImports: [],
},
// UI libraries can import: util, core only (NOT shared, NOT data-access)
{
sourceTag: 'type:ui',
onlyDependOnLibsWithTags: ['type:util', 'type:core', 'type:icon'],
},
// SHARED libraries can import: ui, util, core within same domain
{
sourceTag: 'type:shared',
onlyDependOnLibsWithTags: [
'type:ui',
'type:util',
'type:core',
'type:common',
'type:icon',
],
},
// UTIL libraries are leaf nodes - cannot import feature/data-access/ui/shared
{
sourceTag: 'type:util',
onlyDependOnLibsWithTags: ['type:util', 'type:core'],
},
// GENERATED (swagger clients) can only be imported by data-access
// This is enforced by the data-access rule above
// CORE libraries can be imported by anyone, but cannot import feature/data-access
{
sourceTag: 'type:core',
onlyDependOnLibsWithTags: ['type:core', 'type:util', 'type:common'],
},
// COMMON libraries can be imported by anyone
{
sourceTag: 'type:common',
onlyDependOnLibsWithTags: [
'type:util',
'type:core',
'type:generated',
],
},
// ICON libraries can be imported by anyone
{
sourceTag: 'type:icon',
onlyDependOnLibsWithTags: [],
},
// ========================================
// DOMAIN-BASED CONSTRAINTS (Scope Rules)
// ========================================
// OMS domain can only import from OMS, shared, core, common, ui, utils, icons
{
sourceTag: 'scope:oms',
onlyDependOnLibsWithTags: [
'scope:oms',
'scope:shared',
'scope:core',
'scope:common',
'scope:ui',
'scope:utils',
'scope:icons',
'scope:generated',
],
},
// CRM domain can only import from CRM, shared, core, common, ui, utils, icons
{
sourceTag: 'scope:crm',
onlyDependOnLibsWithTags: [
'scope:crm',
'scope:shared',
'scope:core',
'scope:common',
'scope:ui',
'scope:utils',
'scope:icons',
'scope:generated',
],
},
// REMISSION domain can only import from REMISSION, shared, core, common, ui, utils, icons
{
sourceTag: 'scope:remission',
onlyDependOnLibsWithTags: [
'scope:remission',
'scope:shared',
'scope:core',
'scope:common',
'scope:ui',
'scope:utils',
'scope:icons',
'scope:generated',
],
},
// CHECKOUT domain can only import from CHECKOUT, shared, core, common, ui, utils, icons
{
sourceTag: 'scope:checkout',
onlyDependOnLibsWithTags: [
'scope:checkout',
'scope:shared',
'scope:core',
'scope:common',
'scope:ui',
'scope:utils',
'scope:icons',
'scope:generated',
],
},
// AVAILABILITY domain can only import from AVAILABILITY, shared, core, common, ui, utils, icons
{
sourceTag: 'scope:availability',
onlyDependOnLibsWithTags: [
'scope:availability',
'scope:shared',
'scope:core',
'scope:common',
'scope:ui',
'scope:utils',
'scope:icons',
'scope:generated',
],
},
// CATALOGUE domain can only import from CATALOGUE, shared, core, common, ui, utils, icons
{
sourceTag: 'scope:catalogue',
onlyDependOnLibsWithTags: [
'scope:catalogue',
'scope:shared',
'scope:core',
'scope:common',
'scope:ui',
'scope:utils',
'scope:icons',
'scope:generated',
],
},
// SHARED libraries can be imported by all domains
{
sourceTag: 'scope:shared',
onlyDependOnLibsWithTags: [
'scope:shared',
'scope:core',
'scope:common',
'scope:ui',
'scope:utils',
'scope:icons',
],
},
// UI libraries can be imported by all domains
{
sourceTag: 'scope:ui',
onlyDependOnLibsWithTags: [
'scope:ui',
'scope:core',
'scope:utils',
'scope:icons',
],
},
// UTILS libraries can be imported by all domains
{
sourceTag: 'scope:utils',
onlyDependOnLibsWithTags: ['scope:utils', 'scope:core'],
},
// CORE libraries can be imported by all domains
{
sourceTag: 'scope:core',
onlyDependOnLibsWithTags: ['scope:core', 'scope:common', 'scope:utils'],
},
// COMMON libraries can be imported by all domains
{
sourceTag: 'scope:common',
onlyDependOnLibsWithTags: [
'scope:common',
'scope:core',
'scope:utils',
'scope:generated',
],
},
// ICONS libraries can be imported by all domains
{
sourceTag: 'scope:icons',
onlyDependOnLibsWithTags: [],
},
// GENERATED (swagger) can only be imported by data-access
{
sourceTag: 'scope:generated',
onlyDependOnLibsWithTags: [],
},
// ========================================
// SPECIAL RULES
// ========================================
// APP scope - violations ignored for now (as per user requirement)
{
sourceTag: 'scope:app',
onlyDependOnLibsWithTags: ['*'],
},
// Disallow relative imports - must use path aliases
{
sourceTag: '*',
bannedExternalImports: ['../*', '../../*', '../../../*'],
},
],
},
],
},
},
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
},
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'],
},
],
},
languageOptions: {
parser: require('jsonc-eslint-parser'),
},
},
eslintConfigPrettier,
];