create-claude-workspace 2.3.4 → 2.3.5
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/dist/scheduler/git/manager.mjs +40 -0
- package/dist/scheduler/loop.mjs +5 -12
- package/dist/template/.claude/CLAUDE.md +1 -1
- package/dist/template/.claude/agents/angular-engineer.md +10 -29
- package/dist/template/.claude/agents/backend-ts-architect.md +8 -61
- package/dist/template/.claude/agents/project-initializer.md +1 -1
- package/dist/template/.claude/agents/react-engineer.md +10 -29
- package/dist/template/.claude/agents/senior-code-reviewer.md +18 -8
- package/dist/template/.claude/agents/svelte-engineer.md +10 -29
- package/dist/template/.claude/agents/technical-planner.md +7 -3
- package/dist/template/.claude/agents/test-engineer.md +97 -33
- package/dist/template/.claude/agents/ui-engineer.md +6 -22
- package/dist/template/.claude/agents/vue-engineer.md +10 -29
- package/dist/template/.claude/standards/architecture.md +108 -0
- package/dist/template/.claude/standards/backend-patterns.md +82 -0
- package/dist/template/.claude/standards/coding-standards.md +64 -0
- package/dist/template/.claude/standards/testing-standards.md +94 -0
- package/dist/template/.claude/templates/claude-md.md +6 -292
- package/package.json +1 -1
|
@@ -63,304 +63,18 @@ Ensure these are in `.gitignore`:
|
|
|
63
63
|
|
|
64
64
|
[Add any special tech from user answers]
|
|
65
65
|
|
|
66
|
-
###
|
|
67
|
-
|
|
68
|
-
- **`apps/` are thin shells** — each app is just configuration + routing + bootstrap. Minimal code.
|
|
69
|
-
- **`libs/` contain all logic** — each domain/feature has its **own library group** with sub-libraries per layer. Apps import only from entry points.
|
|
70
|
-
- **Feature-first library organization (STRICT)** — every distinct feature/domain gets its own group of libraries:
|
|
71
|
-
```
|
|
72
|
-
libs/
|
|
73
|
-
scan/ # feature: scan
|
|
74
|
-
domain/ # scan types, schemas, interfaces
|
|
75
|
-
ui/ # scan UI components
|
|
76
|
-
feature/ # scan smart components
|
|
77
|
-
data-access/ # scan HTTP/DB services
|
|
78
|
-
streak/ # feature: streak
|
|
79
|
-
domain/
|
|
80
|
-
ui/
|
|
81
|
-
feature/
|
|
82
|
-
achievement/ # feature: achievement
|
|
83
|
-
domain/
|
|
84
|
-
feature/
|
|
85
|
-
shared/ # ONLY truly cross-domain code
|
|
86
|
-
ui/ # generic UI primitives (buttons, modals)
|
|
87
|
-
domain/ # cross-domain types (if any)
|
|
88
|
-
infrastructure/
|
|
89
|
-
```
|
|
90
|
-
**NEVER dump multiple features into a single library** (e.g. `shared/types` with `scan.ts`, `streak.ts`, `achievement.ts`). Each feature owns its types in its own `domain/` library.
|
|
91
|
-
- **Frontend and backend are separate apps** with separate build configurations per environment:
|
|
92
|
-
- `apps/[APP_NAME]/` — Frontend application
|
|
93
|
-
- `apps/api/` — Backend API (if applicable)
|
|
94
|
-
- **Environment configs**: each app has per-target settings via Nx `configurations` in `project.json` (API URLs, feature flags, etc.)
|
|
95
|
-
- **Entry point pattern**: each domain lib has a root `index.ts` that re-exports the public API. Apps and other libs import ONLY from `@[PREFIX]/<lib-name>`, never from deep paths like `@[PREFIX]/<lib-name>/src/lib/internal/...`
|
|
96
|
-
|
|
97
|
-
### CLI-First Principle
|
|
98
|
-
|
|
99
|
-
**ALWAYS prioritize CLI commands and generators over manual file creation.** This applies to:
|
|
100
|
-
- Nx workspace scaffolding (`create-nx-workspace`)
|
|
101
|
-
- Libraries, components, applications (`nx generate`)
|
|
102
|
-
- Adding plugins (`nx add`)
|
|
103
|
-
- Package installation (package manager CLI)
|
|
104
|
-
- Git operations (`gh`, `glab`)
|
|
105
|
-
|
|
106
|
-
NEVER manually create `project.json`, `tsconfig.*`, or boilerplate files that a generator would produce. Generators configure dependencies, paths, and targets correctly.
|
|
107
|
-
|
|
108
|
-
**NEVER use `nx:run-commands` executor** in project.json. Always use the proper built-in executor (`@nx/js:node` for serve, `@nx/vite:build` for build, `@nx/eslint:lint` for lint, etc.). `nx:run-commands` is an escape hatch for one-off scripts, not for standard targets.
|
|
109
|
-
|
|
110
|
-
### Nx Generators
|
|
111
|
-
|
|
112
|
-
[If Nx monorepo:]
|
|
113
|
-
|
|
114
|
-
**Generator defaults** are configured in `nx.json` — no need to repeat flags like `--unitTestRunner`, `--linter`, `--style` in every command. See `.claude/profiles/frontend.md` for framework-specific generator commands.
|
|
115
|
-
|
|
116
|
-
**Creating libraries:**
|
|
117
|
-
```bash
|
|
118
|
-
# Plain TypeScript library (for domain models, business logic, shared utils)
|
|
119
|
-
nx g @nx/js:library --directory=libs/[domain]/[layer] --no-interactive
|
|
120
|
-
|
|
121
|
-
# Framework-specific library — see frontend profile for the correct generator
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**Bundler rule (STRICT):** Internal monorepo libs do NOT need a bundler — Nx handles compilation. NEVER install or configure tsup, tsdown, rollup, or any standalone bundler for internal libs. Only add `--bundler=esbuild|tsc|swc` to `nx generate` for **publishable** libraries (npm packages). If `nx generate` created a lib without `--bundler`, do NOT retroactively add one.
|
|
66
|
+
### Standards
|
|
125
67
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
+-----------------------------------------------------+
|
|
132
|
-
| apps/[app] |
|
|
133
|
-
| App shell — assembles features into routing |
|
|
134
|
-
+-----------------------------------------------------+
|
|
135
|
-
| feature/ |
|
|
136
|
-
| Smart components, orchestrate UI + data |
|
|
137
|
-
+-----------------------------------------------------+
|
|
138
|
-
| ui/ | data-access/ |
|
|
139
|
-
| Presentational components | HTTP / DB services |
|
|
140
|
-
| (dumb, input/output) | |
|
|
141
|
-
+-----------------------------------------------------+
|
|
142
|
-
| api/ |
|
|
143
|
-
| API routes, validation (if backend) |
|
|
144
|
-
+-----------------------------------------------------+
|
|
145
|
-
| business/ |
|
|
146
|
-
| Use cases, business logic |
|
|
147
|
-
+-----------------------------------------------------+
|
|
148
|
-
| domain/ |
|
|
149
|
-
| TypeBox schemas (single source of truth), types, |
|
|
150
|
-
| repository interfaces, value objects |
|
|
151
|
-
+-----------------------------------------------------+
|
|
152
|
-
| infrastructure/ |
|
|
153
|
-
| Repository implementations (database, API, mock) |
|
|
154
|
-
+-----------------------------------------------------+
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Dependency rules:
|
|
158
|
-
- domain -> only shared/domain
|
|
159
|
-
- business -> domain, shared/infrastructure/di
|
|
160
|
-
- api -> business, domain
|
|
161
|
-
- infrastructure -> domain, shared/infrastructure
|
|
162
|
-
- data-access -> domain (for types)
|
|
163
|
-
- ui -> shared/ui, domain (for types)
|
|
164
|
-
- feature -> ui, data-access, shared/ui
|
|
165
|
-
|
|
166
|
-
**TypeBox as single source of truth**: Define TypeBox schemas in `domain/` layer (`libs/[domain]/domain/`). These schemas are the canonical definition — derive everything from them:
|
|
167
|
-
- **TypeScript types**: `Static<typeof MySchema>` — no separate interface definitions
|
|
168
|
-
- **API validation**: `openAPIRouteHandler` uses the same schemas for request/response validation + OpenAPI spec
|
|
169
|
-
- **Frontend types**: Frontend imports types from domain lib via `@[PREFIX]/[domain]-domain` — no copy-paste
|
|
170
|
-
- **DB mapping**: Infrastructure layer maps between DB rows and domain types
|
|
171
|
-
- NEVER duplicate type definitions. If a type exists as a TypeBox schema, use `Static<>` everywhere.
|
|
172
|
-
|
|
173
|
-
### @cibule/* Ecosystem (Preferred Libraries)
|
|
174
|
-
|
|
175
|
-
[Include only if project uses backend or fullstack architecture]
|
|
176
|
-
|
|
177
|
-
**ALWAYS prefer `@cibule/*` packages** over custom implementations or third-party alternatives for: DI, database access, file storage, image processing, and Nx workspace scaffolding. These are driver-agnostic abstractions designed for the onion architecture pattern.
|
|
178
|
-
|
|
179
|
-
| Package | Purpose | Replaces |
|
|
180
|
-
|---------|---------|----------|
|
|
181
|
-
| `@cibule/di` | Dependency injection (InjectionToken, Injector, inject()) | Custom DI |
|
|
182
|
-
| `@cibule/db` | Database abstraction (Kysely-based, driver-agnostic) | Raw Kysely |
|
|
183
|
-
| `@cibule/db-d1` | Cloudflare D1 driver for @cibule/db | kysely-d1 |
|
|
184
|
-
| `@cibule/db-sqlite` | SQLite driver for @cibule/db (better-sqlite3) | Direct better-sqlite3 |
|
|
185
|
-
| `@cibule/db-migrate` | Migration orchestrator (Prisma + D1 PRAGMA fixes) | Manual migrations |
|
|
186
|
-
| `@cibule/storage` | File storage abstraction (upload, download, presigned URLs) | Custom storage |
|
|
187
|
-
| `@cibule/storage-r2` | Cloudflare R2 driver for @cibule/storage | Direct R2 API |
|
|
188
|
-
| `@cibule/storage-s3` | AWS S3 driver for @cibule/storage | Direct AWS SDK |
|
|
189
|
-
| `@cibule/image` | Image transformation abstraction | Custom image processing |
|
|
190
|
-
| `@cibule/image-sharp` | Sharp-based driver with FileStorage caching (Node.js) | Direct Sharp |
|
|
191
|
-
| `@cibule/image-cf` | Cloudflare Image Resizing driver | Direct CF API |
|
|
192
|
-
| `@cibule/wiring` | Per-request DI middleware, AsyncLocalStorage helpers | Custom middleware |
|
|
193
|
-
| `@cibule/devkit` | Nx generators for onion architecture scaffolding | Manual Nx setup |
|
|
194
|
-
|
|
195
|
-
**DI core API** (`@cibule/di`):
|
|
196
|
-
- `InjectionToken<T>` — typed token, `Injector.create({ providers, parent? })` — container
|
|
197
|
-
- `inject<T>(token)` / `inject<T>(token, { optional: true })` — resolve from context
|
|
198
|
-
- `runInInjectionContext(injector, fn)` — scoped execution
|
|
199
|
-
- Provider types: `useValue`, `useClass`, `useFactory`, `multi: true`
|
|
200
|
-
|
|
201
|
-
**Database pattern** (`@cibule/db` + driver):
|
|
202
|
-
```typescript
|
|
203
|
-
// Domain layer — driver-agnostic
|
|
204
|
-
import type { Db } from '@cibule/db';
|
|
205
|
-
import { DB_ACCESSOR, UNIT_OF_WORK_FACTORY } from '@cibule/db';
|
|
206
|
-
|
|
207
|
-
// Infrastructure — pick driver per platform
|
|
208
|
-
import { provideD1Db } from '@cibule/db-d1'; // Cloudflare Workers
|
|
209
|
-
import { provideSqliteDb } from '@cibule/db-sqlite'; // Node.js local dev
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
**Workspace scaffolding** (`@cibule/devkit`):
|
|
213
|
-
```bash
|
|
214
|
-
nx g @cibule/devkit:preset myorg # Initialize workspace with onion layers
|
|
215
|
-
nx g @cibule/devkit:scope market --frontend # Create domain scope
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
**Dependency bug handling**: If a bug is caused by a third-party dependency (not by project code), mark the task as `[~] BLOCKED` with the bug details and the package version. Continue with other tasks. The dependency freshness check at phase transitions will detect new versions — re-attempt blocked tasks after the package is updated.
|
|
68
|
+
Shared coding standards are in `.claude/standards/` — agents read them on demand:
|
|
69
|
+
- `coding-standards.md` — file organization, TypeScript config, coding style, code cleanliness, modern JS/TS
|
|
70
|
+
- `architecture.md` — app separation, CLI-first, Nx generators, onion architecture
|
|
71
|
+
- `backend-patterns.md` — @cibule/* ecosystem, platform-agnostic backend, Hono/OpenAPI patterns
|
|
72
|
+
- `testing-standards.md` — test coverage, VRT setup, code quality & linting
|
|
219
73
|
|
|
220
74
|
### Frontend Profile
|
|
221
75
|
|
|
222
76
|
Framework-specific best practices, component architecture, state management, SSR patterns, theme system, and UI component library conventions are defined in `.claude/profiles/frontend.md`. This file is read by `ui-engineer`, `senior-code-reviewer`, and `test-engineer` agents — not by backend or infrastructure agents.
|
|
223
77
|
|
|
224
|
-
### File Organization & Size Limits
|
|
225
|
-
|
|
226
|
-
**Single-purpose files (STRICT):**
|
|
227
|
-
- Each `.ts` file exports ONE class, ONE function, or ONE closely related set of helpers (e.g., a type + its factory)
|
|
228
|
-
- Name files after their single export: `get-image.ts`, `parse-html.ts`, `price-calculator.ts`
|
|
229
|
-
- NEVER bundle unrelated exports into a barrel file like `utils.ts` or `helpers.ts` — split into individual files
|
|
230
|
-
- Index files (`index.ts`) are the ONLY exception — they re-export the public API of a library
|
|
231
|
-
|
|
232
|
-
**File size limits:**
|
|
233
|
-
- MAX 200 lines per TypeScript file — split into types, utils, sub-components if larger
|
|
234
|
-
- MAX 200 lines per SCSS file — split into partials
|
|
235
|
-
- MAX 100 lines per HTML template — decompose into child components
|
|
236
|
-
|
|
237
|
-
**Co-located tests:**
|
|
238
|
-
- Test files live next to the source file: `price-calculator.spec.ts` beside `price-calculator.ts`
|
|
239
|
-
- NEVER create `__tests__/` directories — tests are always co-located
|
|
240
|
-
- One test file per source file — do NOT bundle multiple files' tests together
|
|
241
|
-
|
|
242
|
-
### TypeScript Config
|
|
243
|
-
|
|
244
|
-
- `moduleResolution: "bundler"` in `tsconfig.base.json` — all code goes through a bundler, so use bundler-style resolution
|
|
245
|
-
- NEVER add `.js` extensions to TypeScript imports — write `import { Foo } from './foo'`, not `'./foo.js'`
|
|
246
|
-
- `module: "ESNext"` + `target: "ES2022"` (or as appropriate)
|
|
247
|
-
- `strict: true`, `noUncheckedIndexedAccess: true`
|
|
248
|
-
- Path aliases via `compilerOptions.paths` in `tsconfig.base.json` — managed by Nx generators, do not edit manually
|
|
249
|
-
|
|
250
|
-
### Coding Style
|
|
251
|
-
|
|
252
|
-
- No comments in code — write self-explanatory code
|
|
253
|
-
- Explicit access modifiers: `public` for API, `protected` for template-used, `private` for internal
|
|
254
|
-
- Import order enforced by `eslint-plugin-simple-import-sort` (automatic)
|
|
255
|
-
- Use `type` imports for type-only imports (`import type { Foo }`)
|
|
256
|
-
- DRY: 3+ repeats = extract to shared utility/component/directive
|
|
257
|
-
- Prefer composition over inheritance
|
|
258
|
-
- `readonly` on all fields that don't need reassignment
|
|
259
|
-
- No `any` — use `unknown` + type narrowing
|
|
260
|
-
- No non-null assertions (`!`) — handle nullability explicitly with narrowing, `??`, or early returns
|
|
261
|
-
- No `as unknown as T` double-casting — if types don't align, fix the types or use proper type guards
|
|
262
|
-
- No `eslint-disable` comments — NEVER suppress linter rules. If ESLint flags an error, fix the code instead of disabling the rule. This includes `eslint-disable-next-line`, `eslint-disable-line`, and block `eslint-disable` comments.
|
|
263
|
-
|
|
264
|
-
### Code Cleanliness (STRICT — clean code enables high coverage)
|
|
265
|
-
|
|
266
|
-
- **Pure functions first**: business logic and domain operations are pure — same input, same output, no side effects. This makes them trivially testable.
|
|
267
|
-
- **Minimal branching**: avoid nested conditionals (max 2 levels). Prefer early returns, lookup maps/objects, `??`/`?.` chains, polymorphism. If a function has 4+ branches, split it.
|
|
268
|
-
- **Side effects at boundaries**: I/O (HTTP, DB, logging, DOM) happens at the edges — infrastructure layer, entry points. Business and domain code stays pure.
|
|
269
|
-
- **Data transformations over mutations**: prefer `map`/`filter`/spread/new objects over `push`/`splice`/`delete`/mutation. Immutable data is predictable and testable.
|
|
270
|
-
- **Small focused functions**: each function does ONE thing. Max ~20 lines of logic. Extract complex expressions into named pure helpers.
|
|
271
|
-
- **Declarative over imperative**: describe WHAT, not HOW. Prefer expressions over statement sequences.
|
|
272
|
-
|
|
273
|
-
### Modern JavaScript Syntax (STRICT — enforced by ESLint)
|
|
274
|
-
|
|
275
|
-
- `for...of` over `.forEach()` — clearer, supports `break`/`continue`/`await`
|
|
276
|
-
- `const` by default — `let` only when reassignment is needed, NEVER `var`
|
|
277
|
-
- Arrow functions in callbacks — `array.map(x => x.id)`, not `array.map(function(x) { ... })`
|
|
278
|
-
- Template literals — `` `Hello ${name}` ``, not `'Hello ' + name`
|
|
279
|
-
- Object shorthand — `{ name, age }`, not `{ name: name, age: age }`
|
|
280
|
-
- Destructuring — `const { id, name } = user`, not `const id = user.id`
|
|
281
|
-
- Nullish coalescing `??` over `||` for defaults (avoids falsy pitfalls)
|
|
282
|
-
- Optional chaining `?.` over nested `if` checks
|
|
283
|
-
- `Promise.all()` for parallel async, `for await...of` for async iteration
|
|
284
|
-
|
|
285
|
-
### Test Coverage
|
|
286
|
-
|
|
287
|
-
80% minimum for statements, branches, functions, lines (enforced in CI).
|
|
288
|
-
|
|
289
|
-
- **Config template**: `.claude/templates/vitest.coverage.ts` — merge into each project's `vite.config.ts` or `vitest.config.ts` during scaffolding. Replace `[PROJECT_NAME]` with actual name.
|
|
290
|
-
- Reporters: `cobertura` (GitLab/GitHub MR coverage), `html` (browsable), `text-summary`
|
|
291
|
-
- Coverage aggregated at workspace root under `coverage/` (add to `.gitignore`)
|
|
292
|
-
- Run: `nx test [PROJECT] --coverage` or `nx affected --target=test -- --coverage`
|
|
293
|
-
|
|
294
|
-
### Visual Regression Testing
|
|
295
|
-
|
|
296
|
-
Page-level VRT using Playwright `toHaveScreenshot()` at 3 viewports (375px, 768px, 1280px). Catches unintended visual regressions across pages.
|
|
297
|
-
|
|
298
|
-
- **Files**: `*.vrt.spec.ts` in E2E project (co-located with functional E2E tests)
|
|
299
|
-
- **Baselines**: `*-snapshots/` directories — committed to git
|
|
300
|
-
- **Threshold**: `maxDiffPixelRatio: 0.01` (1%), animations disabled
|
|
301
|
-
- **Update baselines**: `nx e2e [APP]-e2e -- --update-snapshots` after intentional visual changes
|
|
302
|
-
- **CI**: use Playwright Docker image (`mcr.microsoft.com/playwright`) for consistent rendering
|
|
303
|
-
|
|
304
|
-
### Code Quality & Linting
|
|
305
|
-
|
|
306
|
-
Config templates are in `.claude/templates/` — copy to project root during Phase 0 scaffolding:
|
|
307
|
-
- **ESLint**: `.claude/templates/eslint.config.js` → `eslint.config.js` (flat config, `@typescript-eslint/strict-type-checked` + `@nx/eslint-plugin` + `eslint-plugin-simple-import-sort` + `eslint-plugin-prefer-arrow-functions`). Add framework-specific rules from `.claude/profiles/frontend.md`.
|
|
308
|
-
- **Prettier**: `.claude/templates/.prettierrc` → `.prettierrc`, `.claude/templates/.prettierignore` → `.prettierignore`
|
|
309
|
-
- **Stylelint**: `.claude/templates/.stylelintrc.json` → `.stylelintrc.json` (SCSS only, forces theme tokens over hardcoded colors)
|
|
310
|
-
- **Pre-commit hooks**: `.claude/templates/.lefthook.yml` → `.lefthook.yml`
|
|
311
|
-
|
|
312
|
-
Each library's `project.json` must declare tags: `"tags": ["type:domain", "scope:auth"]`
|
|
313
|
-
|
|
314
|
-
Key rules enforced (do NOT weaken):
|
|
315
|
-
- `prefer-arrow-functions/prefer-arrow-functions` — const arrow over function declarations
|
|
316
|
-
- `max-classes-per-file: 1`, `max-depth: 4`
|
|
317
|
-
- `@typescript-eslint/explicit-member-accessibility` — explicit public/private/protected
|
|
318
|
-
- `@typescript-eslint/prefer-readonly` — readonly where possible
|
|
319
|
-
- `@typescript-eslint/no-non-null-assertion`, `no-explicit-any`, `consistent-type-imports`, `strict-boolean-expressions`
|
|
320
|
-
- `no-warning-comments: ['eslint-disable']` — no eslint-disable comments
|
|
321
|
-
- `@nx/enforce-module-boundaries` — onion architecture layer constraints
|
|
322
|
-
- `eslint-config-prettier` installed to disable conflicting rules. Do NOT use `eslint-plugin-prettier`.
|
|
323
|
-
|
|
324
|
-
**Enforcement:**
|
|
325
|
-
- All three tools run in CI pipeline (fail on violations)
|
|
326
|
-
- `nx affected --target=lint` for incremental linting
|
|
327
|
-
- Pre-commit hooks prevent committing violations
|
|
328
|
-
|
|
329
|
-
### Backend Patterns (if applicable)
|
|
330
|
-
|
|
331
|
-
[Include only if the project has a backend]
|
|
332
|
-
|
|
333
|
-
- Hono routes with validation (**TypeBox** — `typebox` for schema + type inference, `TypeCompiler` for runtime validation). **NEVER use `@sinclair/typebox`** — the correct package is `typebox`.
|
|
334
|
-
- **OpenAPI-first**: Use `hono-openapi` with `openAPIRouteHandler` for all API routes — generates OpenAPI spec from TypeBox schemas automatically. API docs served via `@scalar/hono-api-reference` at `/reference`.
|
|
335
|
-
- `@cibule/di` for dependency injection (see @cibule/* Ecosystem section above)
|
|
336
|
-
- `@cibule/db` + driver for database access, UnitOfWork for atomic writes
|
|
337
|
-
- `@cibule/storage` + driver for file storage, `@cibule/image` + driver for image processing
|
|
338
|
-
- `@cibule/wiring` for per-request DI middleware
|
|
339
|
-
|
|
340
|
-
**Platform-Agnostic Backend (STRICT):**
|
|
341
|
-
- Backend code MUST run on both Node.js and Cloudflare Workers without modification
|
|
342
|
-
- NEVER use Node.js-specific APIs (`fs`, `path`, `process`, `Buffer`) in business/domain/api layers
|
|
343
|
-
- NEVER use Cloudflare-specific APIs (`env.DB`, `ctx.waitUntil()`) in business/domain layers
|
|
344
|
-
- Platform-specific code lives ONLY in `infrastructure/` layer behind abstract interfaces
|
|
345
|
-
- Use Web Standard APIs where possible: `fetch`, `Request`, `Response`, `URL`, `crypto`, `TextEncoder`/`TextDecoder`, `Headers`, `FormData`, `ReadableStream`
|
|
346
|
-
- **Platform-specific code MUST be in separate libraries (STRICT)** — NEVER mix Node.js and Cloudflare code in the same library. Barrel exports (`index.ts`) would pull both platforms into the bundle, causing compilation errors (e.g. `better-sqlite3` in Cloudflare, or D1 bindings in Node.js):
|
|
347
|
-
```
|
|
348
|
-
libs/[domain]/
|
|
349
|
-
infrastructure-d1/ # Cloudflare D1 implementation ONLY
|
|
350
|
-
infrastructure-sqlite/ # Node.js SQLite implementation ONLY
|
|
351
|
-
libs/shared/
|
|
352
|
-
infrastructure-d1/ # shared D1 providers (provideD1Database)
|
|
353
|
-
infrastructure-sqlite/ # shared SQLite providers (provideSqliteDatabase)
|
|
354
|
-
```
|
|
355
|
-
Each entry point imports ONLY its platform's library:
|
|
356
|
-
- Worker entry → `@[PREFIX]/shared-infrastructure-d1`
|
|
357
|
-
- Node entry → `@[PREFIX]/shared-infrastructure-sqlite`
|
|
358
|
-
- Hono is inherently platform-agnostic — use its standard APIs, avoid `c.env` directly in routes (inject via DI)
|
|
359
|
-
- Entry points handle platform wiring:
|
|
360
|
-
- `apps/api/src/main.ts` — Node.js entry (optional, for local dev)
|
|
361
|
-
- `apps/api/src/index.ts` — Cloudflare Worker entry (production)
|
|
362
|
-
- Default deployment: **Cloudflare Workers** (production), **Node.js** (local development via `@nx/js:node` executor + Node.js entry point). Wrangler is deployment-only — NEVER used for local dev or in Nx targets.
|
|
363
|
-
|
|
364
78
|
### Project-Specific Details
|
|
365
79
|
|
|
366
80
|
[Add critical implementation details, key patterns, special requirements from the discovery conversation and codebase exploration. This section is expanded by architect agents as they make technical decisions during development.]
|