create-daloy 1.0.0-beta.4 → 1.0.0-beta.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.
@@ -2,11 +2,11 @@
2
2
  name: daloyjs-best-practices
3
3
  description: >-
4
4
  Best practices for building, testing, and hardening this DaloyJS REST API on
5
- Vercel (Node.js runtime). Use when adding or changing HTTP routes, Zod
6
- schemas, middleware, or error handling; regenerating the OpenAPI spec or the
7
- typed Hey API client; keeping the single Vercel Functions entrypoint and
8
- Web-Standard handler; or working on auth, rate limits, secrets, and the
9
- project's quality gates.
5
+ Vercel (Node.js runtime). Use when adding or changing HTTP routes,
6
+ Zod/Standard Schema validation schemas, middleware, route metadata, or error
7
+ handling; regenerating the OpenAPI spec or typed Hey API client; keeping the
8
+ single Vercel Functions entrypoint and Web-Standard handler; running contract
9
+ gates; or working on auth, rate limits, secrets, and security defaults.
10
10
  license: MIT
11
11
  ---
12
12
 
@@ -42,7 +42,8 @@ DaloyJS is a **contract-first** framework. On Vercel, additionally:
42
42
  then drop `node:` modules.
43
43
  2. **The route definition is the contract.** Method, path, request
44
44
  schemas, and response schemas live in one place (`app.route({...})`).
45
- 3. **Zod schemas validate at every boundary.**
45
+ 3. **Validation schemas protect every boundary.** This template uses Zod,
46
+ and Daloy accepts any Standard Schema-compatible library.
46
47
  4. **Preserve literal types.** Return `status: 200 as const`.
47
48
  5. **Secure by default.** `requestId()`, `secureHeaders()`, and
48
49
  `rateLimit()` are registered before route definitions. Note the
@@ -53,6 +54,9 @@ DaloyJS is a **contract-first** framework. On Vercel, additionally:
53
54
  and `vercel.json` rewrites every path (`/(.*)` → `/api`) to it, so
54
55
  DaloyJS owns all routing at the site root and generates a unified
55
56
  OpenAPI spec. Removing the rewrite makes the root domain 404.
57
+ 7. **Contract gates are part of done.** Keep `operationId` values stable,
58
+ examples schema-valid, declared error responses accurate, and the
59
+ generated OpenAPI contract in sync with the live route table.
56
60
 
57
61
  ## Project shape
58
62
 
@@ -73,11 +77,14 @@ DaloyJS is a **contract-first** framework. On Vercel, additionally:
73
77
  pnpm dev # local Node dev server (src/dev.ts) on http://localhost:3000
74
78
  pnpm typecheck # tsc --noEmit
75
79
  pnpm test # run test suite
80
+ pnpm contract # daloy inspect --check api/index.ts
76
81
  pnpm deploy # deploy to Vercel
77
82
  pnpm audit # supply-chain audit
78
83
  ```
79
84
 
80
85
  Always run `pnpm typecheck` and `pnpm test` before declaring a task done.
86
+ `pnpm test` includes the contract gate; if you need a focused contract
87
+ check, run `pnpm contract`.
81
88
 
82
89
  ## OpenAPI & docs routes
83
90
 
@@ -97,17 +104,32 @@ On Vercel the YAML serializer is pure-string (no extra deps) and adds
97
104
  <1KB to the bundle. For hand-rolled mounting, `openapiToYAML` is exported
98
105
  from `@daloyjs/core/openapi`.
99
106
 
107
+ ## AI-ready contract metadata
108
+
109
+ Daloy can expose route metadata to OpenAPI and agent tooling. Add metadata
110
+ when it helps consumers understand or safely automate the route:
111
+
112
+ - Use `summary`, `description`, and `tags` for concise human-facing docs.
113
+ - Use `meta.examples` for realistic happy-path and unhappy-path examples.
114
+ Examples must match the declared schemas; the contract gate rejects drift.
115
+ - Use `meta.extensions` for stable `x-*` fields consumed by internal tools.
116
+ - Use `deprecated` and `sunset` when changing API lifecycle. Do not remove
117
+ a route or response shape silently if generated clients may depend on it.
118
+
100
119
  ## Workflow: add a new route
101
120
 
102
121
  1. **Open `api/index.ts`.**
103
122
  2. **Design schemas first.** Use `z.object({...}).strict()` for inputs.
104
123
  3. **Call `app.route({...})`** with `method`, `path`, `operationId`,
105
124
  `tags`, `responses`, `handler` (plus `request` when accepting input).
125
+ Add `meta` examples / descriptions when the route is user-facing or
126
+ consumed by agents.
106
127
  4. **Return `{ status, body, headers? }`** with `status: 200 as const`.
107
128
  5. **Throw typed errors** (`NotFoundError`, `BadRequestError`, etc.)
108
129
  from `@daloyjs/core`.
109
130
  6. **Add a test** under `tests/` using in-process `app.request(...)`.
110
- 7. **Run the quality gates**: `pnpm typecheck && pnpm test`.
131
+ 7. **Run the contract gate**: `pnpm contract` or `pnpm test`.
132
+ 8. **Run the quality gates**: `pnpm typecheck && pnpm test`.
111
133
 
112
134
  ### Example: a typed route
113
135
 
@@ -146,6 +168,8 @@ app.route({
146
168
  - **Pagination**: standardize on `{ items, nextCursor }` cursor
147
169
  pagination.
148
170
  - **Discriminated unions**: `z.discriminatedUnion("kind", [...])`.
171
+ - Keep response examples close to the route definition and schema-valid.
172
+ The contract test intentionally fails invalid examples.
149
173
 
150
174
  ## Error handling
151
175
 
@@ -183,6 +207,8 @@ Cover **happy paths and unhappy paths** for every route: valid input,
183
207
  validation failures (400), auth failures (401/403), not-found (404),
184
208
  conflict (409), rate limiting (429). For external services, inject an
185
209
  in-memory fake during tests.
210
+ The shipped contract test should fail invalid examples, duplicate/missing
211
+ `operationId`, or missing responses.
186
212
 
187
213
  Aim for **100% line and function coverage** on the routes you add.
188
214
 
@@ -191,6 +217,10 @@ Aim for **100% line and function coverage** on the routes you add.
191
217
  - Keep `secureHeaders()`, `requestId()`, and `rateLimit()` enabled. For
192
218
  production traffic, back rate-limiting with Vercel KV or another
193
219
  shared store so limits apply across instances.
220
+ - Never make a failing test pass by deleting or weakening a security guard.
221
+ If a guard blocks a legitimate route, add the narrowest per-route
222
+ override or configuration knob and cover both the allowed and rejected
223
+ paths in tests.
194
224
  - Never log secrets — filter `authorization`, `cookie`, etc.
195
225
  - Read secrets from `process.env` (available on Node.js Functions).
196
226
  Validate via Zod at module load.
@@ -200,6 +230,9 @@ Aim for **100% line and function coverage** on the routes you add.
200
230
  - Validate redirects against an allowlist.
201
231
  - Set `bodyLimitBytes` and `requestTimeoutMs` on `new App({...})` to
202
232
  mitigate DoS.
233
+ - For outbound HTTP, prefer `fetchGuard()` or a transport layered on top
234
+ of it when URLs can be influenced by users or tenants. SSRF protections
235
+ should fail closed for private ranges and cloud metadata endpoints.
203
236
  - Serverless functions still have bundle-size and cold-start costs; be
204
237
  cautious about adding heavy dependencies. Inspect bundle size during
205
238
  deploy.
@@ -229,6 +262,8 @@ Aim for **100% line and function coverage** on the routes you add.
229
262
  Edge runtime, use `toWebHandler(app)` with `export const runtime = "edge"`.
230
263
  - Do not import `@daloyjs/core/node`, `@daloyjs/core/bun`, etc. — only
231
264
  `@daloyjs/core` and `@daloyjs/core/vercel`.
265
+ - Do not hand-edit OpenAPI paths or client types. Fix the route definition,
266
+ schema, or metadata and regenerate.
232
267
  - Node APIs (`Buffer`, `fs`, full `process`) are available on the Node.js
233
268
  runtime, but keep handlers Web-Standard where practical so the app can
234
269
  also run on the Edge runtime unchanged.
@@ -241,6 +276,8 @@ Aim for **100% line and function coverage** on the routes you add.
241
276
  - Every new feature ships with happy-path and unhappy-path tests.
242
277
  - Bug fixes include a regression test.
243
278
  - `pnpm typecheck` and `pnpm test` must pass before completion.
279
+ - When route metadata, examples, lifecycle flags, or operation IDs change,
280
+ run the contract gate and inspect the relevant generated OpenAPI diff.
244
281
  - For deploys, ensure the user is logged in via `vercel login`; do not
245
282
  authenticate on their behalf.
246
283
  - Keep `README.md`, this `SKILL.md`, and `AGENTS.md` consistent.
@@ -13,7 +13,7 @@
13
13
  "hooks:install": "git config core.hooksPath .githooks"
14
14
  },
15
15
  "dependencies": {
16
- "@daloyjs/core": "^1.0.0-beta.4",
16
+ "@daloyjs/core": "^1.0.0-beta.5",
17
17
  "zod": "^4.4.3"
18
18
  },
19
19
  "devDependencies": {