feat(dx): create-ssp bootstrap generator (WP-45)
Mechanises the new-ssp skill's manual fork-and-strip recipe into a runnable script: strips the four business contexts and every wiring point that references them (routes, tsconfig aliases, dependency-cruiser boundaries, nav links, capability union, the debug-state panel, showcase snippet tooling), renames BigRegister.* throughout including the backend solution/projects, re-runs gen:api, and reuses gen:context (WP-44) to seed the new portal's first context. Backend business rules and real branding can't be generated from nothing, so those print an explicit checklist instead of pretending to be automated. Verified end-to-end against an isolated clone (not this working tree): lint, dep:check, check:tokens, all frontend tests, ng build, dotnet build/test on the renamed backend, and gen:api against it all pass clean with zero remaining references to the stripped contexts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,38 +9,89 @@ The template's value is the **enforced architecture** (layer fences, token gate,
|
||||
a11y gate, API-drift gate) and the shared building blocks — not the BIG-register
|
||||
business content. Keep the machinery, replace the domain.
|
||||
|
||||
## Run the script
|
||||
|
||||
Clone this repo, `npm ci`, then mechanise the mechanical parts (WP-45):
|
||||
|
||||
```bash
|
||||
node scripts/create-ssp.mjs --name Kvk --context inschrijving
|
||||
```
|
||||
|
||||
`--name` (PascalCase) replaces `BigRegister.*` everywhere; `--context` (lowercase Dutch
|
||||
ubiquitous term) is passed straight to `gen:context` (`plop context`, WP-44) to seed the new
|
||||
portal's first real context. Add `--dry-run` to preview file operations first, `--keep
|
||||
<context>` to leave one business context in place temporarily as a worked example, and
|
||||
`--skip-backend` if no .NET SDK is available yet (skips `gen:api`).
|
||||
|
||||
It strips the four business contexts and their wiring, renames the backend, re-runs
|
||||
`gen:api`, and seeds the first context — then **prints a checklist** for what it deliberately
|
||||
doesn't script: backend business rules and real branding can't be generated from nothing.
|
||||
Work through that checklist, keeping the GREEN gate below passing at every step.
|
||||
|
||||
## Keep as-is
|
||||
|
||||
- `src/app/shared/` — kernel (`fp.ts`), application (`remote-data`, `store`,
|
||||
`submit`), ui atoms/molecules, layout templates, upload subtree.
|
||||
- Tooling: `eslint.config.mjs`, `scripts/check-tokens.sh`, `.github/workflows/ci.yml`,
|
||||
`submit`), ui atoms/molecules, layout templates, upload subtree — **except**
|
||||
`shared/ui/debug-state/`, which the script deletes (see below).
|
||||
- Tooling: `eslint.config.mjs`, `.dependency-cruiser.js` (edited by the script, not
|
||||
hand-stripped — see below), `scripts/check-tokens.sh`, `.github/workflows/ci.yml`,
|
||||
`nswag.json`, `.storybook/`, `proxy.conf.json`, `.npmrc` (`legacy-peer-deps` —
|
||||
and never `npm audit fix --force`, it downgrades Angular).
|
||||
- `src/app/auth/` (fake auth shell) and `src/app/shared/infrastructure/scenario.interceptor.ts` (dev-only).
|
||||
- `docs/reference/architecture/` ADRs 0001–0003 — the decisions still apply; amend, don't delete.
|
||||
- `CLAUDE.md`, `docs/reference/architecture/ARCHITECTURE.md`, `docs/reference/fp-tea-atomic-design.md` — update names/examples as contexts change.
|
||||
- `.claude/skills/` — these recipes are the point of the template.
|
||||
- `src/app/beheer/` — its frontend is genuinely generic (data-driven off a `StamdataTable`/
|
||||
`AuditEntry` shape, nothing BIG-specific). Its _backend_ Stamdata catalog is not — see below.
|
||||
|
||||
## Strip / replace
|
||||
## Strip / replace — what the script does
|
||||
|
||||
- Business contexts `registratie/`, `herregistratie/`, `brief/`, and `showcase/`:
|
||||
delete or keep one slice temporarily as the worked example while building the
|
||||
first real context (**new-context** + **new-feature** skills). If deleted, update
|
||||
the worked-example paths in these skills to the new flagship context.
|
||||
- `app.routes.ts` routes and `tsconfig.json` aliases for removed contexts, plus
|
||||
their eslint blocks in `eslint.config.mjs`.
|
||||
- Business contexts `registratie/`, `herregistratie/`, `brief/`, `showcase/`: deleted (or one
|
||||
kept temporarily via `--keep` as the worked example while building the first real context —
|
||||
**new-context** + **new-feature** skills; if kept, update the worked-example paths in those
|
||||
skills to the new flagship context once you drop it for real).
|
||||
- `app.routes.ts` route blocks and `tsconfig.json` aliases for removed contexts, and their
|
||||
`CONTEXT_ALLOWED` entry in **`.dependency-cruiser.js`** — boundary rules moved there in
|
||||
WP-38 and are no longer in `eslint.config.mjs` (which only keeps `no-explicit-any` + a11y
|
||||
template rules). Route stripping matches on the _import alias_ a route uses, not its own
|
||||
path segment — `beheer/zaken` imports `@registratie/ui/admin-cases.page` and gets dropped
|
||||
along with `registratie` even though its own path doesn't say so.
|
||||
- `src/app/shared/ui/debug-state/` (the dev `⚙ state` panel): imports
|
||||
`@registratie/application/big-profile.store` directly and is the one path
|
||||
`.dependency-cruiser.js`'s `shared-no-features` rule exempts — there's no generic way to
|
||||
re-target it at an arbitrary new context, so it's deleted alongside `registratie`, along
|
||||
with its three wiring lines in `shell.component.ts` (import, `imports:` entry, template tag).
|
||||
- The `dashboard` route is **not** deleted even though it currently imports
|
||||
`@registratie/ui/dashboard.page` — too much else hardcodes `/dashboard` (login's post-auth
|
||||
redirect, `authGuard`'s fallback, header nav/logo, breadcrumb trail, several stories/specs).
|
||||
The script rewrites its `loadComponent` to point at the freshly scaffolded `--context` page
|
||||
instead (a `TODO(create-ssp)` stopgap landing page, not a real overview).
|
||||
- `scripts/gen-snippets.mjs` (showcase-only) + its `package.json` script entry + its CI/
|
||||
`ci-local.sh` "showcase snippets drift" steps: deleted alongside `showcase/` — they run
|
||||
unconditionally, so leaving them breaks `npm run ci` immediately once `showcase/` is gone.
|
||||
- Backend: keep the skeleton (`Program.cs` minimal-API style, ProblemDetails 422,
|
||||
`X-Correlation-Id` audit line, `/api/v1` versioning, `Contracts/`/`Domain/`/`Data/`
|
||||
split, test project) — replace `Data/SeedData.cs`, `Domain/*` rules, and
|
||||
`Contracts/*` DTOs with the new domain's. Rename the solution/projects from
|
||||
`BigRegister.*` (also update `package.json` `gen:api` and `ci.yml` paths).
|
||||
split, test project, and the generic `Stamdata/StamdataFile.cs`+`StamdataTable.cs`
|
||||
reflection-driven `/stamdata` endpoint machinery, ADR-0004) — replace `Data/SeedData.cs`,
|
||||
`Domain/*` rules, `Contracts/*` DTOs, and the three concrete Stamdata catalog entries
|
||||
(`Beroep`/`Opleiding`/`Specialisme`/`ProfessionMapping` + their JSON) with the new
|
||||
register's. The script renames the solution/projects from `BigRegister.*` (and updates
|
||||
`package.json`'s `gen:api`, `ci.yml`'s paths, `docker-compose.yml`) — it does not rewrite
|
||||
business content; that's the printed checklist.
|
||||
- Regenerate the seam: `npm run gen:api` (commits `backend/swagger.json` +
|
||||
`src/app/shared/infrastructure/api-client.ts`).
|
||||
- Branding: `public/cibg-huisstijl/` + the token bridge in `src/styles.scss` — for a
|
||||
different house style, swap the vendored CSS and re-point the `--rhc-*` bridge
|
||||
(ADR-0003 pattern: bridge, don't rewrite tokens).
|
||||
`src/app/shared/infrastructure/api-client.ts`) — only reflects a new shape once the backend
|
||||
content above is actually rewritten.
|
||||
- Branding: the script swaps `src/index.html`'s stylesheet `<link>` + `<title>` to a
|
||||
placeholder path and creates an empty `public/<name>-huisstijl/` — it cannot generate a
|
||||
real house style. Vendor your CSS there, then re-point the `--rhc-*` bridge in
|
||||
`src/styles.scss` (ADR-0003 pattern: bridge, don't rewrite tokens), then `npm run check:tokens`.
|
||||
- `docs/project/backlog/` WPs, PRDs, and memory-specific docs — new portal, new backlog
|
||||
(keep `docs/project/backlog/README.md`'s WP process/template if you like the workflow).
|
||||
`docs/reference/scaffolding.md` also names `BigRegister.Api` in prose — update by hand.
|
||||
- `e2e/*.spec.ts` (`smoke.spec.ts`, `brief-v2.spec.ts`, `error-state.spec.ts`): full
|
||||
BIG-register user-flow tests (BSN login → registration wizard → submission assertions).
|
||||
Not touched by the script (they don't block `npm run ci` — the `e2e` job runs separately)
|
||||
but are 100% stale business content; rewrite once you have real flows to test.
|
||||
|
||||
## Verify — the GREEN gate must pass at every step
|
||||
|
||||
@@ -51,5 +102,5 @@ cd backend && dotnet test && cd ..
|
||||
npm run gen:api && git diff --exit-code backend/swagger.json src/app/shared/infrastructure/api-client.ts
|
||||
```
|
||||
|
||||
Strip incrementally and keep this green — the fences are only worth having if they
|
||||
never go red.
|
||||
Or just `npm run ci` for the non-storybook subset. Strip incrementally and keep this green
|
||||
— the fences are only worth having if they never go red.
|
||||
|
||||
Reference in New Issue
Block a user