website refactor
This commit is contained in:
482
.eslintrc.json
482
.eslintrc.json
@@ -3,225 +3,245 @@
|
||||
"es2022": true,
|
||||
"node": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2022
|
||||
},
|
||||
"ignorePatterns": ["**/dist/**", "**/*.d.ts"],
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"typescript": {}
|
||||
},
|
||||
"boundaries/elements": [
|
||||
{
|
||||
"type": "website",
|
||||
"pattern": "apps/website/**/*"
|
||||
},
|
||||
{
|
||||
"type": "api",
|
||||
"pattern": "apps/api/**/*"
|
||||
},
|
||||
{
|
||||
"type": "adapters",
|
||||
"pattern": ["adapters/**/*", "@adapters/**/*"]
|
||||
},
|
||||
{
|
||||
"type": "core",
|
||||
"pattern": ["core/**/*", "@core/**/*"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"ignorePatterns": [
|
||||
"**/dist/**",
|
||||
"**/*.d.ts"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["**/index.ts", "**/index.tsx"],
|
||||
"files": [
|
||||
"**/index.ts",
|
||||
"**/index.tsx"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "Program",
|
||||
"message": "index.ts files are forbidden. Use explicit file names instead (e.g., UserService.ts, not index.ts)."
|
||||
"message": "index.ts files are forbidden. Use explicit file names instead (e.g., UserService.ts, not index.ts).",
|
||||
"selector": "Program"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/*/application/ports/*/*.ts"],
|
||||
"files": [
|
||||
"core/*/application/ports/*/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSInterfaceDeclaration[id.name=/^Get.*Port$/]",
|
||||
"message": "Port interface names should not start with 'Get'. Use descriptive names without the 'Get' prefix."
|
||||
"message": "Port interface names should not start with 'Get'. Use descriptive names without the 'Get' prefix.",
|
||||
"selector": "TSInterfaceDeclaration[id.name=/^Get.*Port$/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/**/*.ts"],
|
||||
"files": [
|
||||
"core/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/Blocker$/], TSInterfaceDeclaration[id.name=/Blocker$/]",
|
||||
"message": "Blocker classes/interfaces are not allowed in core. Use Guards in backend."
|
||||
"message": "Blocker classes/interfaces are not allowed in core. Use Guards in backend.",
|
||||
"selector": "TSClassDeclaration[id.name=/Blocker$/], TSInterfaceDeclaration[id.name=/Blocker$/]"
|
||||
},
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/Presenter$/], TSInterfaceDeclaration[id.name=/Presenter$/]",
|
||||
"message": "Presenter classes/interfaces are not allowed in core. Presenters belong in API or frontend layers."
|
||||
"message": "Presenter classes/interfaces are not allowed in core. Presenters belong in API or frontend layers.",
|
||||
"selector": "TSClassDeclaration[id.name=/Presenter$/], TSInterfaceDeclaration[id.name=/Presenter$/]"
|
||||
},
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/Dto$/], TSInterfaceDeclaration[id.name=/Dto$/]",
|
||||
"message": "DTO classes/interfaces are not allowed in core. DTOs belong in API or frontend layers."
|
||||
"message": "DTO classes/interfaces are not allowed in core. DTOs belong in API or frontend layers.",
|
||||
"selector": "TSClassDeclaration[id.name=/Dto$/], TSInterfaceDeclaration[id.name=/Dto$/]"
|
||||
},
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/ViewModel$/], TSInterfaceDeclaration[id.name=/ViewModel$/]",
|
||||
"message": "ViewModel classes/interfaces are not allowed in core. View Models belong in frontend."
|
||||
"message": "ViewModel classes/interfaces are not allowed in core. View Models belong in frontend.",
|
||||
"selector": "TSClassDeclaration[id.name=/ViewModel$/], TSInterfaceDeclaration[id.name=/ViewModel$/]"
|
||||
},
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/CommandModel$/], TSInterfaceDeclaration[id.name=/CommandModel$/]",
|
||||
"message": "CommandModel classes/interfaces are not allowed in core. Command Models belong in frontend."
|
||||
"message": "CommandModel classes/interfaces are not allowed in core. Command Models belong in frontend.",
|
||||
"selector": "TSClassDeclaration[id.name=/CommandModel$/], TSInterfaceDeclaration[id.name=/CommandModel$/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/**/application/dto/**/*.ts", "core/**/application/dtos/**/*.ts"],
|
||||
"files": [
|
||||
"core/**/application/dto/**/*.ts",
|
||||
"core/**/application/dtos/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "Program",
|
||||
"message": "core/*/application/dto is forbidden. Use application result models + output ports; DTOs belong in API/website layers."
|
||||
"message": "core/*/application/dto is forbidden. Use application result models + output ports; DTOs belong in API/website layers.",
|
||||
"selector": "Program"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/**/infrastructure/**/*.ts"],
|
||||
"files": [
|
||||
"core/**/infrastructure/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "Program",
|
||||
"message": "core/*/infrastructure is forbidden. Implementations must live in adapters/ and be wired in apps/."
|
||||
"message": "core/*/infrastructure is forbidden. Implementations must live in adapters/ and be wired in apps/.",
|
||||
"selector": "Program"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/**/domain/ports/**/*.ts"],
|
||||
"files": [
|
||||
"core/**/domain/ports/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "Program",
|
||||
"message": "core/*/domain/ports is forbidden. Ports belong in application/ports (or shared application layer), not domain."
|
||||
"message": "core/*/domain/ports is forbidden. Ports belong in application/ports (or shared application layer), not domain.",
|
||||
"selector": "Program"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/**/shared/presentation/**/*.ts"],
|
||||
"files": [
|
||||
"core/**/shared/presentation/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "Program",
|
||||
"message": "core/shared/presentation is forbidden. Presentation belongs in API or website layers."
|
||||
"message": "core/shared/presentation is forbidden. Presentation belongs in API or website layers.",
|
||||
"selector": "Program"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["apps/website/**/*.ts"],
|
||||
"files": [
|
||||
"apps/website/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/Guard$/], TSInterfaceDeclaration[id.name=/Guard$/]",
|
||||
"message": "Guard classes/interfaces are not allowed in frontend. Use Blockers in frontend."
|
||||
"message": "Guard classes/interfaces are not allowed in frontend. Use Blockers in frontend.",
|
||||
"selector": "TSClassDeclaration[id.name=/Guard$/], TSInterfaceDeclaration[id.name=/Guard$/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["apps/api/**/*.ts", "apps/website/lib/dtos/**/*.ts"],
|
||||
"files": [
|
||||
"apps/api/**/*.ts",
|
||||
"apps/website/lib/dtos/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSEnumDeclaration[id.name=/^(?!.*Enum$).+/]",
|
||||
"message": "Transport enums must end with 'Enum'."
|
||||
"message": "Transport enums must end with 'Enum'.",
|
||||
"selector": "TSEnumDeclaration[id.name=/^(?!.*Enum$).+/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/*/application/use-cases/*.ts"],
|
||||
"files": [
|
||||
"core/*/application/use-cases/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/^(?!.*UseCase$).+/]",
|
||||
"message": "Use Case classes must end with 'UseCase'."
|
||||
"message": "Use Case classes must end with 'UseCase'.",
|
||||
"selector": "TSClassDeclaration[id.name=/^(?!.*UseCase$).+/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/*/application/services/*.ts"],
|
||||
"files": [
|
||||
"core/*/application/services/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/^(?!.*Service$).+/]",
|
||||
"message": "Application Service classes must end with 'Service'."
|
||||
"message": "Application Service classes must end with 'Service'.",
|
||||
"selector": "TSClassDeclaration[id.name=/^(?!.*Service$).+/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["apps/website/lib/view-models/*.ts"],
|
||||
"files": [
|
||||
"apps/website/lib/view-models/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/^(?!.*ViewModel$).+/]",
|
||||
"message": "View Model classes must end with 'ViewModel'."
|
||||
"message": "View Model classes must end with 'ViewModel'.",
|
||||
"selector": "TSClassDeclaration[id.name=/^(?!.*ViewModel$).+/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["apps/website/lib/commands/*.ts"],
|
||||
"files": [
|
||||
"apps/website/lib/commands/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSClassDeclaration[id.name=/^(?!.*CommandModel$).+/]",
|
||||
"message": "Command Model classes must end with 'CommandModel'."
|
||||
"message": "Command Model classes must end with 'CommandModel'.",
|
||||
"selector": "TSClassDeclaration[id.name=/^(?!.*CommandModel$).+/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["apps/website/app/**/page.tsx", "apps/website/app/**/page.ts", "apps/website/app/**/layout.tsx", "apps/website/app/**/layout.ts"],
|
||||
"files": [
|
||||
"apps/website/app/**/page.tsx",
|
||||
"apps/website/app/**/page.ts",
|
||||
"apps/website/app/**/layout.tsx",
|
||||
"apps/website/app/**/layout.ts"
|
||||
],
|
||||
"rules": {
|
||||
"import/no-default-export": "off",
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSInterfaceDeclaration[id.name=/^I[A-Z]/]",
|
||||
"message": "Interface names should not start with 'I'. Use descriptive names without the 'I' prefix (e.g., 'LiverCompositor' instead of 'ILiveryCompositor')."
|
||||
"message": "Interface names should not start with 'I'. Use descriptive names without the 'I' prefix (e.g., 'LiverCompositor' instead of 'ILiveryCompositor').",
|
||||
"selector": "TSInterfaceDeclaration[id.name=/^I[A-Z]/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.ts", "**/*.tsx"],
|
||||
"extends": [
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript"
|
||||
],
|
||||
"files": [
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint", "boundaries", "import"],
|
||||
"extends": ["plugin:import/recommended", "plugin:import/typescript"],
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"boundaries",
|
||||
"import"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
@@ -231,20 +251,39 @@
|
||||
"default": "disallow",
|
||||
"rules": [
|
||||
{
|
||||
"from": ["website"],
|
||||
"allow": ["website"]
|
||||
"allow": [
|
||||
"website"
|
||||
],
|
||||
"from": [
|
||||
"website"
|
||||
]
|
||||
},
|
||||
{
|
||||
"from": ["api"],
|
||||
"allow": ["api", "adapters", "core"]
|
||||
"allow": [
|
||||
"api",
|
||||
"adapters",
|
||||
"core"
|
||||
],
|
||||
"from": [
|
||||
"api"
|
||||
]
|
||||
},
|
||||
{
|
||||
"from": ["adapters"],
|
||||
"allow": ["adapters", "core"]
|
||||
"allow": [
|
||||
"adapters",
|
||||
"core"
|
||||
],
|
||||
"from": [
|
||||
"adapters"
|
||||
]
|
||||
},
|
||||
{
|
||||
"from": ["core"],
|
||||
"allow": ["core"]
|
||||
"allow": [
|
||||
"core"
|
||||
],
|
||||
"from": [
|
||||
"core"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -254,171 +293,240 @@
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "ExportDefaultDeclaration",
|
||||
"message": "Default exports are forbidden. Use named exports instead."
|
||||
"message": "Default exports are forbidden. Use named exports instead.",
|
||||
"selector": "ExportDefaultDeclaration"
|
||||
},
|
||||
{
|
||||
"selector": "TSInterfaceDeclaration[id.name=/^I[A-Z]/]",
|
||||
"message": "Interface names should not start with 'I'. Use descriptive names without the 'I' prefix (e.g., 'LiverCompositor' instead of 'ILiveryCompositor')."
|
||||
"message": "Interface names should not start with 'I'. Use descriptive names without the 'I' prefix (e.g., 'LiverCompositor' instead of 'ILiveryCompositor').",
|
||||
"selector": "TSInterfaceDeclaration[id.name=/^I[A-Z]/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/**/*.ts"],
|
||||
"files": [
|
||||
"core/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "ExportDefaultDeclaration",
|
||||
"message": "Default exports are forbidden. Use named exports instead."
|
||||
"message": "Default exports are forbidden. Use named exports instead.",
|
||||
"selector": "ExportDefaultDeclaration"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["apps/website/**/*.tsx", "apps/website/**/*.ts"],
|
||||
"files": [
|
||||
"apps/website/**/*.tsx",
|
||||
"apps/website/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"selector": "TSInterfaceDeclaration[id.name=/ViewModel$/], TSTypeAliasDeclaration[id.name=/ViewModel$/], TSClassDeclaration[id.name=/ViewModel$/]",
|
||||
"message": "ViewModel types must be defined in apps/website/lib/view-models, not in components."
|
||||
},
|
||||
{
|
||||
"selector": "TSInterfaceDeclaration[id.name=/DTO$/], TSTypeAliasDeclaration[id.name=/DTO$/], TSClassDeclaration[id.name=/DTO$/]",
|
||||
"message": "DTO types are forbidden in website components. Use ViewModels instead."
|
||||
}
|
||||
],
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"name": "@core/racing",
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
"message": "Imports from @core are forbidden in website components",
|
||||
"name": "@core/racing"
|
||||
},
|
||||
{
|
||||
"name": "@core/analytics",
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
"message": "Imports from @core are forbidden in website components",
|
||||
"name": "@core/analytics"
|
||||
},
|
||||
{
|
||||
"name": "@core/identity",
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
"message": "Imports from @core are forbidden in website components",
|
||||
"name": "@core/identity"
|
||||
},
|
||||
{
|
||||
"name": "@core/media",
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
"message": "Imports from @core are forbidden in website components",
|
||||
"name": "@core/media"
|
||||
},
|
||||
{
|
||||
"name": "@core/notifications",
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
"message": "Imports from @core are forbidden in website components",
|
||||
"name": "@core/notifications"
|
||||
},
|
||||
{
|
||||
"name": "@core/payments",
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
"message": "Imports from @core are forbidden in website components",
|
||||
"name": "@core/payments"
|
||||
},
|
||||
{
|
||||
"name": "@core/shared",
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
"message": "Imports from @core are forbidden in website components",
|
||||
"name": "@core/shared"
|
||||
},
|
||||
{
|
||||
"name": "@core/social",
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
"message": "Imports from @core are forbidden in website components",
|
||||
"name": "@core/social"
|
||||
},
|
||||
{
|
||||
"name": "@adapters",
|
||||
"message": "Imports from @adapters are forbidden in website components"
|
||||
"message": "Imports from @adapters are forbidden in website components",
|
||||
"name": "@adapters"
|
||||
},
|
||||
{
|
||||
"name": "@api",
|
||||
"message": "Imports from @api are forbidden in website components"
|
||||
"message": "Imports from @api are forbidden in website components",
|
||||
"name": "@api"
|
||||
}
|
||||
],
|
||||
"patterns": [
|
||||
{
|
||||
"group": ["@core/*"],
|
||||
"group": [
|
||||
"@core/*"
|
||||
],
|
||||
"message": "Imports from @core are forbidden in website components"
|
||||
},
|
||||
{
|
||||
"group": ["@adapters/*"],
|
||||
"group": [
|
||||
"@adapters/*"
|
||||
],
|
||||
"message": "Imports from @adapters are forbidden in website components"
|
||||
},
|
||||
{
|
||||
"group": ["@api/*"],
|
||||
"group": [
|
||||
"@api/*"
|
||||
],
|
||||
"message": "Imports from @api are forbidden in website components"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"no-restricted-syntax": [
|
||||
"error",
|
||||
{
|
||||
"message": "ViewModel types must be defined in apps/website/lib/view-models, not in components.",
|
||||
"selector": "TSInterfaceDeclaration[id.name=/ViewModel$/], TSTypeAliasDeclaration[id.name=/ViewModel$/], TSClassDeclaration[id.name=/ViewModel$/]"
|
||||
},
|
||||
{
|
||||
"message": "DTO types are forbidden in website components. Use ViewModels instead.",
|
||||
"selector": "TSInterfaceDeclaration[id.name=/DTO$/], TSTypeAliasDeclaration[id.name=/DTO$/], TSClassDeclaration[id.name=/DTO$/]"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"apps/api/**/*.test.ts",
|
||||
"apps/api/**/*.test.tsx"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"no-restricted-syntax": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"tests/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"message": "Integration tests must use in-memory adapters, not core directly",
|
||||
"name": "@core/*"
|
||||
},
|
||||
{
|
||||
"message": "Integration tests must use in-memory adapters only",
|
||||
"name": "@adapters/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["apps/api/**/*.test.ts", "apps/api/**/*.test.tsx"],
|
||||
"files": [
|
||||
"tests/e2e/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"no-restricted-syntax": "off"
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"patterns": [
|
||||
{
|
||||
"group": [
|
||||
"**/inmemory/**"
|
||||
],
|
||||
"message": "E2E tests must use TypeORM/PostgreSQL, not in-memory adapters"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["tests/**/*.ts"],
|
||||
"files": [
|
||||
"core/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-imports": ["error", {
|
||||
"paths": [
|
||||
{
|
||||
"name": "@core/*",
|
||||
"message": "Integration tests must use in-memory adapters, not core directly"
|
||||
},
|
||||
{
|
||||
"name": "@adapters/*",
|
||||
"message": "Integration tests must use in-memory adapters only"
|
||||
}
|
||||
]
|
||||
}]
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"message": "Use @testing/* from adapters/testing",
|
||||
"name": "testing"
|
||||
},
|
||||
{
|
||||
"message": "Core layer should not depend on testing utilities",
|
||||
"name": "@testing/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["tests/e2e/**/*.ts"],
|
||||
"files": [
|
||||
"adapters/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-imports": ["error", {
|
||||
"patterns": [
|
||||
{
|
||||
"group": ["**/inmemory/**"],
|
||||
"message": "E2E tests must use TypeORM/PostgreSQL, not in-memory adapters"
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["core/**/*.ts"],
|
||||
"rules": {
|
||||
"no-restricted-imports": ["error", {
|
||||
"paths": [
|
||||
{
|
||||
"name": "testing",
|
||||
"message": "Use @testing/* from adapters/testing"
|
||||
},
|
||||
{
|
||||
"name": "@testing/*",
|
||||
"message": "Core layer should not depend on testing utilities"
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["adapters/**/*.ts"],
|
||||
"rules": {
|
||||
"no-restricted-imports": ["error", {
|
||||
"paths": [
|
||||
{
|
||||
"name": "testing",
|
||||
"message": "Use @testing/* from adapters/testing"
|
||||
}
|
||||
]
|
||||
}]
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
{
|
||||
"message": "Use @testing/* from adapters/testing",
|
||||
"name": "testing"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2022,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"settings": {
|
||||
"boundaries/elements": [
|
||||
{
|
||||
"pattern": "apps/website/**/*",
|
||||
"type": "website"
|
||||
},
|
||||
{
|
||||
"pattern": "apps/api/**/*",
|
||||
"type": "api"
|
||||
},
|
||||
{
|
||||
"pattern": [
|
||||
"adapters/**/*",
|
||||
"@adapters/**/*"
|
||||
],
|
||||
"type": "adapters"
|
||||
},
|
||||
{
|
||||
"pattern": [
|
||||
"core/**/*",
|
||||
"@core/**/*"
|
||||
],
|
||||
"type": "core"
|
||||
}
|
||||
],
|
||||
"import/resolver": {
|
||||
"typescript": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user