Add Zod dependency and update API interfaces
- Added Zod as a dependency in package.json. - Updated pnpm-lock.yaml to include Zod. - Refactored API interfaces: exported new modules for perk, survivor, mission, and encounter. - Removed obsolete api-interfaces.ts file. - Enhanced tests for new schemas in api-interfaces.spec.ts, covering various validation scenarios.
This commit is contained in:
70
docs/adr/0002-nx-monorepo-with-strict-boundaries.md
Executable file
70
docs/adr/0002-nx-monorepo-with-strict-boundaries.md
Executable file
@@ -0,0 +1,70 @@
|
||||
# 0002 — Nx monorepo with enforced module boundaries
|
||||
|
||||
- **Status:** Accepted
|
||||
- **Date:** 2026-05-06
|
||||
|
||||
## Context and problem statement
|
||||
|
||||
Fog Expedition has at least three distinct deployable surfaces (Twitch Video Overlay frontend, NestJS EBS backend, content/balance library), and types must be shared between them (DTOs, domain models, encounter records). The project is being built with heavy AI assistance, which adds a specific failure mode: AI assistants happily reach across project boundaries with relative imports if not constrained.
|
||||
|
||||
How should the codebase be structured?
|
||||
|
||||
## Decision drivers
|
||||
|
||||
- **Type sharing without duplication.** The overlay and EBS exchange `Mission`, `Survivor`, `EncounterResult` etc. Hand-keeping types in sync across separate repos is bug-prone.
|
||||
- **AI-assisted-build discipline.** AI tools generate plausible-looking code that violates architectural conventions unless those conventions are mechanically enforced.
|
||||
- **Solo-developer simplicity.** Multiple repos mean multiple CI configs, multiple versioning streams, multiple onboarding paths.
|
||||
- **Future scaling.** Should the project ever grow to more contributors, the architecture should still be coherent.
|
||||
- **Tooling support for the chosen language stack** (TypeScript, Angular, NestJS).
|
||||
|
||||
## Considered options
|
||||
|
||||
1. **Multi-repo (polyrepo).** Frontend, backend, and shared types each in their own repository. Shared types published to a private npm registry.
|
||||
2. **Loose monorepo (npm/pnpm workspaces only).** All projects in one repo, no orchestrator. No automated boundary enforcement.
|
||||
3. **Nx monorepo with `enforce-module-boundaries`.** All projects in one repo. Project tags (`scope:api`, `scope:overlay`, `scope:shared`, `type:app`, `type:lib`) define dependency rules enforced at lint time.
|
||||
4. **Turborepo.** Lighter monorepo orchestrator, focused on caching and task running. No native module boundary enforcement.
|
||||
|
||||
## Decision outcome
|
||||
|
||||
**Chosen: Nx monorepo with enforced module boundaries.**
|
||||
|
||||
Project structure:
|
||||
|
||||
```
|
||||
apps/
|
||||
api/ # scope:api, type:app
|
||||
overlay/ # scope:overlay, type:app
|
||||
libs/
|
||||
api-interfaces/ # scope:shared, type:lib (Zod schemas, DTOs)
|
||||
mission-logic/ # scope:shared, type:lib (encounter resolver, perk math)
|
||||
encounter-library/ # scope:shared, type:lib (content + helpers)
|
||||
```
|
||||
|
||||
Boundary rules enforced via `@nx/enforce-module-boundaries`:
|
||||
|
||||
- Apps can only depend on libs (not other apps).
|
||||
- `scope:api` can depend on `scope:api` and `scope:shared`.
|
||||
- `scope:overlay` can depend on `scope:overlay` and `scope:shared`.
|
||||
- `scope:shared` can only depend on `scope:shared`.
|
||||
|
||||
Violations fail lint (verified at workspace setup with a deliberate negative test).
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- Type sharing is direct via TypeScript imports, no version coordination needed.
|
||||
- Module boundary enforcement catches architecturally incorrect AI-generated code at lint time before code review.
|
||||
- Single CI pipeline, single dependency tree, single onboarding flow.
|
||||
- `nx affected` runs only what changed, keeping CI fast as the project grows.
|
||||
- Per-project `package.json` files keep workspace libs publish-ready (e.g., `api-interfaces` could later be published as a community SDK without restructuring).
|
||||
|
||||
### Negative
|
||||
|
||||
- Steeper learning curve than plain pnpm workspaces — Nx generators, executors, and project configuration are non-trivial.
|
||||
- Tighter coupling to Nx's release cadence; `nx migrate` is required for major version upgrades but generally handles them well.
|
||||
- Some Nx generators lag behind the underlying tooling (e.g., `@nx/nest` doesn't yet support Vitest natively — see ADR-0003).
|
||||
|
||||
### Neutral
|
||||
|
||||
- The monorepo single source of truth makes architectural mistakes more visible; it also makes them more impactful when they happen.
|
||||
Reference in New Issue
Block a user