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
+11
View File
@@ -0,0 +1,11 @@
# shared-tokens
This library was generated with [Nx](https://nx.dev).
## Building
Run `nx build shared-tokens` to build the library.
## Running unit tests
Run `nx test shared-tokens` to execute the unit tests via [Vitest](https://vitest.dev/).
+22
View File
@@ -0,0 +1,22 @@
import baseConfig from '../../../eslint.config.mjs';
export default [
...baseConfig,
{
files: ['**/*.json'],
rules: {
'@nx/dependency-checks': [
'error',
{
ignoredFiles: [
'{projectRoot}/eslint.config.{js,cjs,mjs,ts,cts,mts}',
'{projectRoot}/vite.config.{js,ts,mjs,mts}',
],
},
],
},
languageOptions: {
parser: await import('jsonc-eslint-parser'),
},
},
];
+13
View File
@@ -0,0 +1,13 @@
{
"name": "shared-tokens",
"version": "0.0.1",
"private": true,
"type": "commonjs",
"main": "./src/index.js",
"types": "./src/index.d.ts",
"dependencies": {
"tslib": "^2.3.0",
"vitest": "^4.0.8",
"@nx/vite": "^22.7.1"
}
}
+19
View File
@@ -0,0 +1,19 @@
{
"name": "shared-tokens",
"$schema": "../../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/shared/tokens/src",
"projectType": "library",
"tags": ["scope:shared", "type:shared"],
"targets": {
"build": {
"executor": "@nx/js:tsc",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/shared/tokens",
"main": "libs/shared/tokens/src/index.ts",
"tsConfig": "libs/shared/tokens/tsconfig.lib.json",
"assets": ["libs/shared/tokens/*.md"]
}
}
}
}
+1
View File
@@ -0,0 +1 @@
export * from './lib/shared-tokens';
@@ -0,0 +1,7 @@
import { sharedTokens } from './shared-tokens';
describe('sharedTokens', () => {
it('should work', () => {
expect(sharedTokens()).toEqual('shared-tokens');
});
});
@@ -0,0 +1,3 @@
export function sharedTokens(): string {
return 'shared-tokens';
}
+23
View File
@@ -0,0 +1,23 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"forceConsistentCasingInFileNames": true,
"strict": true,
"importHelpers": true,
"noImplicitOverride": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noPropertyAccessFromIndexSignature": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}
+23
View File
@@ -0,0 +1,23 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx"
]
}
+22
View File
@@ -0,0 +1,22 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../dist/out-tsc",
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node", "vitest"]
},
"include": [
"vite.config.ts",
"vite.config.mts",
"vitest.config.ts",
"vitest.config.mts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.test.tsx",
"src/**/*.spec.tsx",
"src/**/*.test.js",
"src/**/*.spec.js",
"src/**/*.test.jsx",
"src/**/*.spec.jsx",
"src/**/*.d.ts"
]
}
+21
View File
@@ -0,0 +1,21 @@
import { defineConfig } from 'vitest/config';
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../../node_modules/.vite/libs/shared/tokens',
plugins: [nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
test: {
name: 'shared-tokens',
watch: false,
globals: true,
environment: 'node',
include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
reporters: ['default'],
coverage: {
reportsDirectory: '../../../coverage/libs/shared/tokens',
provider: 'v8' as const,
},
},
}));