Dependencies flow one direction
Dependencies flow one way: apps → feature → data-access → shared — shared never imports a domain.
nx-isolation-deps-one-direction
Why it matters
| Stake | If ignored |
|---|---|
| Hidden coupling |
|
| Hard to change |
|
How to fix
Layering: apps → features → data-access/ui → util/shared. shared may not know about a specific domain. ui may not import feature. Nx enforces with type: tags.
shared provides a mechanism (a registry, an interface, a base class). The domain registers into it from its own app entry point. nx graph shows flow goes one way.
Examples
ts
// libs/shared/auth/src/lib/permissions.ts
import { StudioPermissions } from '@acme/studio/permissions';
import { SitesPermissions } from '@acme/sites-management/permissions';
export function canAccess(user: User, resource: string) {
if (resource.startsWith('studio/')) return StudioPermissions.check(user);
if (resource.startsWith('sites/')) return SitesPermissions.check(user);
}ts
// libs/shared/auth/src/lib/registry.ts
type Checker = (user: User, resource: string) => boolean;
const checkers = new Map<string, Checker>();
export function registerPermissionChecker(prefix: string, checker: Checker) {
checkers.set(prefix, checker);
}
export function canAccess(user: User, resource: string) {
const prefix = resource.split('/')[0];
return checkers.get(prefix)?.(user, resource) ?? false;
}
// apps/studio/src/main.ts
import { registerPermissionChecker } from '@acme/shared/auth';
import { StudioPermissions } from '@acme/studio/feature-permissions';
registerPermissionChecker('studio', StudioPermissions.check);