@pukujan/create-modular-monolith 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -0
- package/bin/create-modular-monolith.js +132 -0
- package/package.json +39 -0
- package/template/README.md +73 -0
- package/template/backend/package-lock.json +882 -0
- package/template/backend/package.json +20 -0
- package/template/backend/scripts/check-module-boundaries.mjs +69 -0
- package/template/backend/scripts/check-module-layers.mjs +152 -0
- package/template/backend/src/core/module-loader.js +35 -0
- package/template/backend/src/core/server.js +24 -0
- package/template/backend/src/modules/.gitkeep +0 -0
- package/template/backend/src/modules/_reference/README.md +11 -0
- package/template/backend/src/modules/_reference/adapters/README.md +3 -0
- package/template/backend/src/modules/_reference/config/index.js +4 -0
- package/template/backend/src/modules/_reference/domain/README.md +3 -0
- package/template/backend/src/modules/_reference/evals/README.md +6 -0
- package/template/backend/src/modules/_reference/evals/datasets/example.cases.json +12 -0
- package/template/backend/src/modules/_reference/evals/runners/example.eval.mjs +25 -0
- package/template/backend/src/modules/_reference/events/index.js +4 -0
- package/template/backend/src/modules/_reference/index.js +9 -0
- package/template/backend/src/modules/_reference/prompts/manifest.json +14 -0
- package/template/backend/src/modules/_reference/prompts/templates/example.prompt.js +7 -0
- package/template/backend/src/modules/_reference/repositories/.gitkeep +0 -0
- package/template/backend/src/modules/_reference/routes/health.routes.js +10 -0
- package/template/backend/src/modules/_reference/routes/index.js +8 -0
- package/template/backend/src/modules/_reference/schemas/health.schema.js +8 -0
- package/template/backend/src/modules/_reference/services/health.service.js +7 -0
- package/template/backend/src/modules/_reference/tests/integration/health.routes.test.js +20 -0
- package/template/backend/src/modules/_reference/tests/unit/health.service.test.js +9 -0
- package/template/backend/src/modules/_reference/utils/index.js +3 -0
- package/template/backend/src/shared/ai/prompt-registry.js +42 -0
- package/template/backend/src/shared/events/index.js +8 -0
- package/template/backend/src/shared/http/errors.js +10 -0
- package/template/backend/src/shared/testing/create-test-app.js +13 -0
- package/template/docs/DEVLOG_V2.md +369 -0
- package/template/docs/PUBLISHING.md +39 -0
- package/template/docs/README.md +13 -0
- package/template/docs/STARTER_PACK.md +98 -0
- package/template/docs/architecture/ARCHITECTURE_GUARDRAILS.md +74 -0
- package/template/docs/architecture/MODULE_INTERNAL_CONTRACT.md +164 -0
- package/template/frontend/index.html +12 -0
- package/template/frontend/package-lock.json +1724 -0
- package/template/frontend/package.json +21 -0
- package/template/frontend/src/core/App.jsx +35 -0
- package/template/frontend/src/core/moduleRegistry.jsx +39 -0
- package/template/frontend/src/index.css +53 -0
- package/template/frontend/src/main.jsx +10 -0
- package/template/frontend/src/modules/.gitkeep +0 -0
- package/template/frontend/src/modules/_reference/README.md +3 -0
- package/template/frontend/src/modules/_reference/components/ModuleHealthCard.jsx +14 -0
- package/template/frontend/src/modules/_reference/hooks/use-module-health.js +27 -0
- package/template/frontend/src/modules/_reference/index.jsx +7 -0
- package/template/frontend/src/modules/_reference/pages/_referencePage.jsx +11 -0
- package/template/frontend/src/modules/_reference/prompts/README.md +3 -0
- package/template/frontend/src/modules/_reference/schemas/health.schema.js +3 -0
- package/template/frontend/src/modules/_reference/services/health-api.js +5 -0
- package/template/frontend/src/modules/_reference/tests/unit/health.schema.test.js +8 -0
- package/template/frontend/src/modules/_reference/utils/index.js +3 -0
- package/template/frontend/src/shared/api/client.js +10 -0
- package/template/frontend/vite.config.js +6 -0
- package/template/package.json +16 -0
- package/template/scripts/lib/module-scaffold.mjs +409 -0
- package/template/scripts/new-module.mjs +58 -0
- package/template/scripts/run-module-evals.mjs +43 -0
- package/template/scripts/sync-cli-template.mjs +44 -0
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Module internal contract
|
|
2
|
+
|
|
3
|
+
This document defines the **inside** of a feature module. [Architecture guardrails](./ARCHITECTURE_GUARDRAILS.md) define how modules talk to each other; this contract defines how code is organized **within** a module so the modular monolith can grow into a legal-services platform without repeated refactors.
|
|
4
|
+
|
|
5
|
+
Design goals:
|
|
6
|
+
|
|
7
|
+
- **Replaceable features** — each module can later become a service.
|
|
8
|
+
- **Testable layers** — unit tests on services/domain; integration tests on routes; evals on prompts.
|
|
9
|
+
- **AI-ready** — prompts and evals are first-class, versioned, and colocated with the feature that uses them.
|
|
10
|
+
- **Predictable dependencies** — one direction of imports; lint catches violations early.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Backend layout
|
|
15
|
+
|
|
16
|
+
Every feature module lives at `backend/src/modules/<module-name>/` and **must** follow this tree. Folders may start empty (`.gitkeep`); the scaffolder creates them all.
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
<module-name>/
|
|
20
|
+
├── index.js # Composition root ONLY — wires routes, events, config
|
|
21
|
+
├── config/ # Module env & constants
|
|
22
|
+
├── routes/ # HTTP (Express routers + thin handlers)
|
|
23
|
+
├── services/ # Use cases & orchestration (including AI flows)
|
|
24
|
+
├── repositories/ # Persistence & query access
|
|
25
|
+
├── domain/ # Entities, value objects, domain rules (no I/O)
|
|
26
|
+
├── adapters/ # External systems (courts, e-file, storage, LLM clients)
|
|
27
|
+
├── events/ # Subscribe/emit helpers for this module
|
|
28
|
+
├── schemas/ # Request/response validation & DTO shapes
|
|
29
|
+
├── prompts/ # Versioned LLM prompt templates + manifest
|
|
30
|
+
│ ├── manifest.json
|
|
31
|
+
│ └── templates/
|
|
32
|
+
├── evals/ # Prompt/flow evaluation (datasets + runners)
|
|
33
|
+
│ ├── datasets/
|
|
34
|
+
│ └── runners/
|
|
35
|
+
├── utils/ # Pure helpers private to this module
|
|
36
|
+
└── tests/
|
|
37
|
+
├── unit/
|
|
38
|
+
└── integration/
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Layer responsibilities
|
|
42
|
+
|
|
43
|
+
| Layer | Responsibility | May import |
|
|
44
|
+
| --- | --- | --- |
|
|
45
|
+
| **index** | `register(app, context)` — mount routes, register listeners | Any layer in **this** module, `src/shared/*`, npm |
|
|
46
|
+
| **routes** | HTTP mapping, status codes, call services | `services`, `schemas`, `shared`, npm |
|
|
47
|
+
| **services** | Business logic, transactions, AI orchestration | `domain`, `repositories`, `adapters`, `prompts`, `schemas`, `events`, `utils`, `config`, `shared`, npm |
|
|
48
|
+
| **repositories** | DB/files/API persistence | `domain`, `adapters`, `schemas`, `utils`, `shared`, npm |
|
|
49
|
+
| **adapters** | Third-party APIs, SDK wrappers | `domain`, `schemas`, `utils`, `shared`, npm |
|
|
50
|
+
| **domain** | Pure rules and types | `utils` (pure only), `shared` (types/helpers only), npm |
|
|
51
|
+
| **events** | Module event handlers | `services`, `schemas`, `shared`, npm |
|
|
52
|
+
| **prompts** | Prompt templates & metadata (no side effects) | `schemas`, `utils`, npm |
|
|
53
|
+
| **evals** | Offline evaluation of prompts/flows | `services`, `prompts`, `schemas`, `shared`, npm |
|
|
54
|
+
| **schemas** | Validation contracts | `utils`, npm |
|
|
55
|
+
| **utils** | Pure functions | Other `utils`, `shared`, npm |
|
|
56
|
+
| **config** | Env parsing for this module | `shared`, npm |
|
|
57
|
+
| **tests** | Automated tests | Anything in module (test code is exempt from layer lint) |
|
|
58
|
+
|
|
59
|
+
### Dependency rules (enforced)
|
|
60
|
+
|
|
61
|
+
The layer linter (`npm run lint:layers`) rejects imports that skip layers or create cycles.
|
|
62
|
+
|
|
63
|
+
**Hard rules:**
|
|
64
|
+
|
|
65
|
+
1. **routes** must not import `repositories`, `adapters`, `domain`, `prompts`, `events`, or `evals` directly — go through **services**.
|
|
66
|
+
2. **domain** must stay pure — no `services`, `routes`, `repositories`, `adapters`, `events`, `prompts`, or `evals`.
|
|
67
|
+
3. **prompts** stay declarative — no `services`, `routes`, `repositories`, `adapters`, or `events`.
|
|
68
|
+
4. **repositories** must not import `services` or `routes`.
|
|
69
|
+
5. **utils** stay leaf nodes — no `services`, `routes`, `repositories`, etc.
|
|
70
|
+
6. **evals** exercise behavior through **services** (and `prompts`/`schemas`), not HTTP.
|
|
71
|
+
|
|
72
|
+
`index.js` is the only composition root and may wire everything.
|
|
73
|
+
|
|
74
|
+
### Prompts & evals (platform / AI)
|
|
75
|
+
|
|
76
|
+
**Prompts**
|
|
77
|
+
|
|
78
|
+
- One file per prompt under `prompts/templates/` exporting at minimum: `id`, `version`, `template`.
|
|
79
|
+
- Register every prompt in `prompts/manifest.json` for discovery and eval runners.
|
|
80
|
+
- Bump `version` when template text changes (aids regression and audit for legal workflows).
|
|
81
|
+
|
|
82
|
+
**Evals**
|
|
83
|
+
|
|
84
|
+
- **datasets/** — JSON fixtures: input, expected constraints, optional golden output.
|
|
85
|
+
- **runners/** — Node scripts or `node:test` files that load a prompt + call a service, assert structure/thresholds.
|
|
86
|
+
- Evals are **not** production routes; they run in CI or locally via `npm run test:evals -- <module-name>`.
|
|
87
|
+
|
|
88
|
+
This keeps prompt engineering colocated with the feature that owns the legal workflow, while services remain the single runtime orchestration point.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Frontend layout
|
|
93
|
+
|
|
94
|
+
```text
|
|
95
|
+
<module-name>/
|
|
96
|
+
├── index.jsx # Route contract ONLY (route, label, Component)
|
|
97
|
+
├── pages/ # Route-level screens
|
|
98
|
+
├── components/ # Presentational UI (props in, JSX out)
|
|
99
|
+
├── hooks/ # Stateful UI logic, data fetching
|
|
100
|
+
├── services/ # API client calls for this module
|
|
101
|
+
├── schemas/ # Client-side validation / types
|
|
102
|
+
├── utils/ # Module-private helpers
|
|
103
|
+
├── prompts/ # UX copy, assistant hints, tool instructions (optional)
|
|
104
|
+
└── tests/
|
|
105
|
+
└── unit/
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Frontend dependency rules
|
|
109
|
+
|
|
110
|
+
| Layer | May import |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| **index** | `pages`, `shared` |
|
|
113
|
+
| **pages** | `components`, `hooks`, `services`, `schemas`, `utils`, `shared` |
|
|
114
|
+
| **components** | `utils`, `schemas`, `shared` (no direct `services`) |
|
|
115
|
+
| **hooks** | `services`, `schemas`, `utils`, `shared` |
|
|
116
|
+
| **services** | `schemas`, `utils`, `shared` |
|
|
117
|
+
| **schemas** | `utils`, npm |
|
|
118
|
+
| **utils** | `shared`, npm |
|
|
119
|
+
|
|
120
|
+
Pages and hooks talk to the backend; presentational components do not call `fetch` directly.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Cross-cutting conventions
|
|
125
|
+
|
|
126
|
+
### Naming
|
|
127
|
+
|
|
128
|
+
- Files: **kebab-case** (`intake-form.service.js`, `use-intake-form.js`).
|
|
129
|
+
- Tests: `*.test.js` / `*.test.jsx` under `tests/`.
|
|
130
|
+
- Eval runners: `*.eval.mjs` under `evals/runners/`.
|
|
131
|
+
|
|
132
|
+
### API & routes
|
|
133
|
+
|
|
134
|
+
- Backend mount: `/api/<module-name>` (in `index.js` only).
|
|
135
|
+
- Frontend route: `/<module-name>` (in `index.jsx` only).
|
|
136
|
+
|
|
137
|
+
### Reference module
|
|
138
|
+
|
|
139
|
+
`backend/src/modules/_reference/` and `frontend/src/modules/_reference/` are a **non-loaded** example (names starting with `_` are skipped by the loaders). Copy from them when building by hand; prefer `npm run new:module` for real features.
|
|
140
|
+
|
|
141
|
+
### When to split into subfolders
|
|
142
|
+
|
|
143
|
+
Stay in one module until you have multiple unrelated subdomains or teams. Then add **capability subfolders** inside a layer (e.g. `services/filing/`, `services/deadlines/`) — not new top-level modules — until a clear extraction boundary exists.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Enforcement
|
|
148
|
+
|
|
149
|
+
| Command | Checks |
|
|
150
|
+
| --- | --- |
|
|
151
|
+
| `npm run lint:boundaries` | No imports across `modules/<other>/` (backend `.js`/`.mjs`, frontend `.js`/`.jsx`) |
|
|
152
|
+
| `npm run lint:layers` | Layer import rules inside each backend module |
|
|
153
|
+
| `npm test` | Unit + integration tests (`node:test`) |
|
|
154
|
+
| `npm run test:evals` | Module eval runners |
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Related files
|
|
159
|
+
|
|
160
|
+
- [Architecture guardrails](./ARCHITECTURE_GUARDRAILS.md) — inter-module contract
|
|
161
|
+
- `scripts/new-module.mjs` — scaffolds this layout
|
|
162
|
+
- `backend/scripts/check-module-layers.mjs`
|
|
163
|
+
- `backend/scripts/check-module-boundaries.mjs`
|
|
164
|
+
- `backend/src/modules/_reference/` — living backend example
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Modular Litigation Starter</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.jsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|