chore: generate shared and feature libs with module boundaries per ADR-0003

Generate the four phase-4 libraries:

- libs/shared/tokens (project name shared-tokens) - plain TS lib via
  @nx/js:library; will host the a11y design tokens (palette,
  contrast tiers, spacing, motion) once Tailwind lands in phase 5;
  consumable by both apps; tagged scope:shared, type:shared.
- libs/shared/util (shared-util) - plain TS lib for cross-cutting
  utility code; tagged scope:shared, type:shared.
- libs/shared/ui (shared-ui) - Angular standalone library that will
  host the spartan-ng components copy-pasted in phase 5; Angular-only
  so tagged scope:portal-shell, type:shared. unitTestRunner=
  vitest-analog because vitest-angular requires a buildable lib.
- libs/feature/auth (feature-auth) - placeholder Angular standalone
  feature lib to demonstrate the type:feature pattern; tagged
  scope:portal-shell, type:feature.

@nx/enforce-module-boundaries depConstraints replaced (root
eslint.config.mjs) with the rules from ADR-0003:

  scope:portal-shell -> scope:portal-shell, scope:shared
  scope:portal-bff   -> scope:portal-bff,   scope:shared
  scope:shared       -> scope:shared
  type:app           -> type:feature, type:shared
  type:feature       -> type:feature, type:shared
  type:shared        -> type:shared

This forbids portal-shell from importing portal-bff code (and vice
versa) and prevents shared libs from depending on feature libs.

Project names follow the convention of ADR-0003 (feature-<name> /
shared-<scope>) by passing --name explicitly to the generator; the Nx
22 default takes only the last directory segment.

Sanity check: pnpm nx run-many -t lint and -t test pass for the 8
projects (4 apps/e2e + 4 libs).

Side effects from the generators: tsconfig.base.json paths populated
with the lib import aliases; nx.json gains vite/playwright plugin
entries; .gitignore picks up vitest.config.*.timestamp* (Vitest temp
files); package.json gains @analogjs/vitest-angular and related
devDeps; pnpm-lock.yaml regenerated. Two eslint-disable comments in
portal-bff-e2e support files were trimmed by lint --fix - those files
already lint clean without the directive.
This commit is contained in:
Julien Gautier
2026-04-30 17:37:29 +02:00
parent 2b0e20bd85
commit 8de19320c5
57 changed files with 1143 additions and 99 deletions
+31 -3
View File
@@ -5,7 +5,7 @@ export default [
...nx.configs['flat/typescript'],
...nx.configs['flat/javascript'],
{
ignores: ['**/dist', '**/out-tsc'],
ignores: ['**/dist', '**/out-tsc', '**/vitest.config.*.timestamp*'],
},
{
files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'],
@@ -15,10 +15,38 @@ export default [
{
enforceBuildableLibDependency: true,
allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?[jt]s$'],
// Module boundaries per ADR-0003.
//
// Scope tags partition the workspace into front (portal-shell) /
// back (portal-bff) / shared (consumable by both). Type tags
// partition into apps / feature libs / shared libs.
//
// Both axes apply: a lib must satisfy both scope and type rules
// to be importable.
depConstraints: [
{
sourceTag: '*',
onlyDependOnLibsWithTags: ['*'],
sourceTag: 'scope:portal-shell',
onlyDependOnLibsWithTags: ['scope:portal-shell', 'scope:shared'],
},
{
sourceTag: 'scope:portal-bff',
onlyDependOnLibsWithTags: ['scope:portal-bff', 'scope:shared'],
},
{
sourceTag: 'scope:shared',
onlyDependOnLibsWithTags: ['scope:shared'],
},
{
sourceTag: 'type:app',
onlyDependOnLibsWithTags: ['type:feature', 'type:shared'],
},
{
sourceTag: 'type:feature',
onlyDependOnLibsWithTags: ['type:feature', 'type:shared'],
},
{
sourceTag: 'type:shared',
onlyDependOnLibsWithTags: ['type:shared'],
},
],
},