feat(dx): gen:context generator (WP-44)
npm run gen:context scaffolds a bounded context: folders + starter page, the @<ctx>/* tsconfig alias, a dependency-cruiser boundary entry, and a lazy authGuard route. Refactors .dependency-cruiser.js's per-context contextRule calls into a single CONTEXT_ALLOWED map that every rule derives from, so adding a context is really one config entry (verified behavior-preserving: same dep:check counts, same graph output). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,26 +14,21 @@ shared/reusable code is English. The context name is the ubiquitous language ter
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Folders** — `src/app/<ctx>/{domain,application,infrastructure,ui}` (`contracts/`
|
||||
only once it gets a wire seam). Empty layers can wait; don't scaffold placeholders.
|
||||
2. **Path alias** — add `"@<ctx>/*": ["src/app/<ctx>/*"]` to `tsconfig.json` `paths`.
|
||||
Aliases are direction statements; always import cross-context via the alias.
|
||||
3. **Boundaries** (`.dependency-cruiser.js`, WP-38 — the single declarative source;
|
||||
dependencies point inward and toward `shared` only). Add ONE `contextRule(...)` entry
|
||||
for the new context listing the contexts it may **not** import (copy the `brief` leaf
|
||||
example), and add the new context to the forbidden list of any context that must not
|
||||
depend on it. The layer rules (`domain/` framework-free, `contracts/` import-nothing,
|
||||
ApiClient confinement, `ui ↛ infrastructure`) match by glob and cover it automatically.
|
||||
Verify with `npm run dep:check`; regenerate the graph with `npm run dep:graph`. (Boundaries
|
||||
are no longer in `eslint.config.mjs` — that now holds only `no-explicit-any` + template a11y.)
|
||||
4. **Route** — lazy child under the persistent shell in `app.routes.ts`:
|
||||
|
||||
```ts
|
||||
{ path: '<ctx>', canActivate: [authGuard],
|
||||
loadComponent: () => import('@<ctx>/ui/<ctx>.page').then(m => m.CtxPage) }
|
||||
```
|
||||
|
||||
5. Build the first feature slice with the **new-feature** skill.
|
||||
1. Run `npm run gen:context` (WP-44) and give it the lowercase context name. It
|
||||
mechanises the manual edits below in one shot:
|
||||
- Folders — `src/app/<ctx>/{domain,application,infrastructure,contracts}/.gitkeep` +
|
||||
a starter `ui/<ctx>.page.ts` (replace with the real first feature).
|
||||
- Path alias — `"@<ctx>/*": ["src/app/<ctx>/*"]` added to `tsconfig.json` `paths`.
|
||||
- Boundary entry — one new key in `.dependency-cruiser.js`'s `CONTEXT_ALLOWED` map
|
||||
(WP-38's single declarative source; every context's forbidden list is _derived_
|
||||
from that map, so adding one key is enough — nothing else to hand-edit). List the
|
||||
OTHER contexts the new one may import (usually `[]` — a leaf, like `brief`).
|
||||
- Route — a lazy child under the persistent shell in `app.routes.ts`, gated by
|
||||
`authGuard`.
|
||||
2. Verify: `npm run dep:check && npm run lint && npm run build` (regenerate the graph
|
||||
with `npm run dep:graph` if you want the committed diagram to reflect it too).
|
||||
3. Build the first feature slice with the **new-feature** skill — replace the
|
||||
generated placeholder page.
|
||||
|
||||
## Worked example
|
||||
|
||||
|
||||
Reference in New Issue
Block a user