Dependency Architecture Linter
This document explains the dependency validation system that enforces clean architecture rules.
Overview
Section titled “Overview”The project uses a custom validation script (scripts/validate-dependencies.ts) that runs as part of the linting process to ensure all packages follow the dependency architecture rules.
Architecture Rules
Section titled “Architecture Rules”The linter enforces these strict dependency rules:
| Package Type | Can Depend On |
|---|---|
| Common plugins | Common plugins ONLY |
| Frontend plugins | Frontend plugins OR common plugins |
| Backend plugins | Backend plugins OR common plugins |
| Core packages | Common packages (minimal dependencies) |
How It Works
Section titled “How It Works”Package Type Detection
Section titled “Package Type Detection”The script automatically detects package types based on naming conventions:
- Common: Packages ending with
-commonor named@checkstack/common - Frontend: Packages ending with
-frontend,-frontend-plugin, or starting with@checkstack/frontendor@checkstack/ui - Backend: Packages ending with
-backend,-backend-plugin, or starting with@checkstack/backend - Core: The
@checkstack/commonpackage - External: Non-
@checkstack/*packages (always allowed)
Validation Process
Section titled “Validation Process”- Scans all packages in
core/*andplugins/*directories - Reads each
package.jsonfile - Checks
dependenciesandpeerDependencies - Validates each internal dependency against the architecture rules
- Reports violations and exits with error code 1 if any are found
Running the Linter
Section titled “Running the Linter”As Part of Lint
Section titled “As Part of Lint”The dependency validation runs automatically with the regular linting:
bun run lintThis command runs:
bun run lint:code- ESLint for code qualitybun run lint:deps- Dependency architecture validation
Standalone
Section titled “Standalone”You can run just the dependency validation:
bun run lint:depsOr directly:
bun run scripts/validate-dependencies.tsExample Violations
Section titled “Example Violations”Violation: Common Depending on Backend
Section titled “Violation: Common Depending on Backend”{ "name": "@checkstack/catalog-common", "dependencies": { "@checkstack/backend-api": "workspace:*" // ❌ VIOLATION }}Error:
❌ Dependency Architecture Violations Found:
@checkstack/catalog-common → depends on @checkstack/backend-api → common packages cannot depend on backend packagesFix: Depend on @checkstack/common instead:
{ "name": "@checkstack/catalog-common", "dependencies": { "@checkstack/common": "workspace:*" // ✅ OK }}Violation: Frontend Depending on Backend
Section titled “Violation: Frontend Depending on Backend”{ "name": "@checkstack/catalog-frontend-plugin", "dependencies": { "@checkstack/catalog-backend-plugin": "workspace:*" // ❌ VIOLATION }}Error:
❌ Dependency Architecture Violations Found:
@checkstack/catalog-frontend-plugin → depends on @checkstack/catalog-backend-plugin → frontend packages cannot depend on backend packagesFix: Depend on common package instead:
{ "name": "@checkstack/catalog-frontend-plugin", "dependencies": { "@checkstack/catalog-common": "workspace:*" // ✅ OK }}Allowed Dependencies
Section titled “Allowed Dependencies”✅ Common → Common
Section titled “✅ Common → Common”{ "name": "@checkstack/catalog-common", "dependencies": { "@checkstack/common": "workspace:*" }}✅ Frontend → Frontend or Common
Section titled “✅ Frontend → Frontend or Common”{ "name": "@checkstack/catalog-frontend-plugin", "dependencies": { "@checkstack/frontend-api": "workspace:*", "@checkstack/catalog-common": "workspace:*", "@checkstack/ui": "workspace:*" }}✅ Backend → Backend or Common
Section titled “✅ Backend → Backend or Common”{ "name": "@checkstack/catalog-backend-plugin", "dependencies": { "@checkstack/backend-api": "workspace:*", "@checkstack/catalog-common": "workspace:*" }}✅ External Dependencies
Section titled “✅ External Dependencies”All packages can depend on external (non-@checkstack/*) packages:
{ "name": "@checkstack/catalog-common", "dependencies": { "zod": "^4.2.1", "react": "^18.2.0" }}CI/CD Integration
Section titled “CI/CD Integration”The lint check runs in CI/CD pipelines. If dependency violations are detected, the build will fail, preventing broken architectures from being merged.
Benefits
Section titled “Benefits”- Enforces Clean Architecture: Prevents runtime-specific code from leaking into shared packages
- Prevents Circular Dependencies: Type system issues are caught early
- Maintains Separation of Concerns: Frontend, backend, and common code stay properly isolated
- Fail Fast: Violations are caught during development, not deployment
- Clear Error Messages: Developers immediately know what’s wrong and how to fix it
Troubleshooting
Section titled “Troubleshooting”False Positives
Section titled “False Positives”If you have a package that doesn’t follow naming conventions, it will be treated as “unknown” and won’t be validated. To fix this:
- Update the package name to follow conventions
- Or update
getPackageType()inscripts/validate-dependencies.tsto recognize your package
Adding New Package Types
Section titled “Adding New Package Types”To add support for new package types (e.g., *-node, *-react):
- Add the type to
PackageTypeunion in the script - Update
getPackageType()to recognize the pattern - Add validation rules in
isDependencyAllowed()