create-daloy 1.0.0-beta.4 → 1.0.0-beta.6
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 +3 -0
- package/bin/create-daloy.mjs +33 -8
- package/package.json +2 -2
- package/sbom.cdx.json +9 -9
- package/sbom.spdx.json +5 -5
- package/templates/bun-basic/AGENTS.md +17 -7
- package/templates/bun-basic/_agents/skills/daloyjs-best-practices/SKILL.md +50 -13
- package/templates/bun-basic/package.json +1 -1
- package/templates/cloudflare-worker/AGENTS.md +17 -6
- package/templates/cloudflare-worker/_agents/skills/daloyjs-best-practices/SKILL.md +45 -8
- package/templates/cloudflare-worker/package.json +1 -1
- package/templates/deno-basic/AGENTS.md +17 -7
- package/templates/deno-basic/_agents/skills/daloyjs-best-practices/SKILL.md +46 -9
- package/templates/deno-basic/deno.json +5 -5
- package/templates/node-basic/AGENTS.md +20 -8
- package/templates/node-basic/_agents/skills/daloyjs-best-practices/SKILL.md +50 -13
- package/templates/node-basic/package.json +2 -2
- package/templates/vercel/AGENTS.md +25 -13
- package/templates/vercel/_agents/skills/daloyjs-best-practices/SKILL.md +44 -7
- package/templates/vercel/package.json +1 -1
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
# AGENTS.md
|
|
2
2
|
|
|
3
|
-
A [DaloyJS](https://daloyjs.dev) REST API deployed to **Vercel** on the **Node.js runtime**
|
|
3
|
+
A [DaloyJS](https://daloyjs.dev) REST API deployed to **Vercel** on the **Node.js runtime**. **Contract-first**: routes use validation schemas (Zod here; DaloyJS also supports Standard Schema-compatible validators) and generate OpenAPI 3.1. With `docs: true`, DaloyJS auto-mounts `GET /openapi.json`, `GET /openapi.yaml`, and `GET /docs` (Scalar UI).
|
|
4
4
|
|
|
5
5
|
- Package manager: pnpm (use `pnpm` unless the project's `package.json` was rewritten for npm/yarn/bun).
|
|
6
6
|
- Runtime: Vercel Node.js Functions on Fluid Compute (Web Standard `Request`/`Response`).
|
|
7
7
|
|
|
8
|
+
## Agent guidance
|
|
9
|
+
|
|
10
|
+
- Treat this file as the short, durable project contract for AI coding agents.
|
|
11
|
+
- Use `.agents/skills/daloyjs-best-practices/SKILL.md` for the detailed DaloyJS workflow; keep this file concise and do not duplicate that skill.
|
|
12
|
+
- If instructions conflict, follow the user's latest prompt first, then the nearest `AGENTS.md`, then the skill.
|
|
13
|
+
- Change route definitions, schemas, metadata, and tests first; regenerate generated files instead of hand-editing OpenAPI output.
|
|
14
|
+
|
|
8
15
|
## Commands
|
|
9
16
|
|
|
10
17
|
- `pnpm dev` — local Node dev server (`src/dev.ts`) on http://localhost:3000 (no `vercel dev` / login needed; serves the same app the Vercel Function runs)
|
|
11
18
|
- `pnpm typecheck` — `tsc --noEmit`
|
|
12
19
|
- `pnpm test` — run test suite
|
|
20
|
+
- `pnpm contract` — run `daloy inspect --check api/index.ts`
|
|
21
|
+
- `pnpm hooks:install` — enable the optional pre-push contract gate
|
|
13
22
|
- `pnpm deploy` — deploy to Vercel
|
|
14
23
|
- `pnpm audit` — supply-chain audit
|
|
15
24
|
|
|
16
25
|
## Project shape
|
|
17
26
|
|
|
18
|
-
- `api/index.ts` — the single Vercel Node.js Functions entrypoint.
|
|
19
|
-
-
|
|
20
|
-
- `
|
|
27
|
+
- `api/index.ts` — the single Vercel Node.js Functions entrypoint. Export `default toFetchHandler(app)` from `@daloyjs/core/vercel`; add `runtime = "edge"` and switch to `toWebHandler(app)` only when the user asks for Edge.
|
|
28
|
+
- This template is not a Next.js App Router project. Do not add `app/api` routes, `next.config.*`, or Next-specific file structure unless the user asks to convert or embed the API in a Next.js app.
|
|
29
|
+
- `vercel.json` — routes all paths to `/api` so DaloyJS owns root routing; do not remove this rewrite.
|
|
30
|
+
- `src/dev.ts` — local Node dev server (`pnpm dev`) for fast iteration without `vercel dev`. Dev-only; Vercel does not deploy it.
|
|
21
31
|
- `tests/` — test files.
|
|
22
32
|
|
|
23
33
|
## Imports
|
|
@@ -28,34 +38,36 @@ This project uses TypeScript with `"allowImportingTsExtensions"`, so relative im
|
|
|
28
38
|
import handler from "../api/index.ts";
|
|
29
39
|
```
|
|
30
40
|
|
|
31
|
-
You import the file you see. Vercel
|
|
41
|
+
You import the file you see. Vercel and tsx resolve `.ts` directly. Bare package imports (`@daloyjs/core`, `zod`, ...) need no extension.
|
|
32
42
|
|
|
33
43
|
## Core rules
|
|
34
44
|
|
|
35
45
|
1. The route definition is the contract. Method, path, request schemas, and response schemas live in one place — `app.route({...})`.
|
|
36
|
-
2. Validate every input with Zod
|
|
46
|
+
2. Validate every input with Zod or another Standard Schema-compatible validator. For Zod object schemas, use `.strict()` to reject unknown keys at the boundary.
|
|
37
47
|
3. Preserve literal types in responses: `status: 200 as const`, `z.literal(...)` on discriminator fields.
|
|
38
48
|
4. Throw typed errors (`NotFoundError`, `BadRequestError`, etc.) from `@daloyjs/core`.
|
|
39
49
|
5. Keep `requestId()`, `secureHeaders()`, and `rateLimit()` enabled. For production traffic, back rate-limiting with Vercel KV or another shared store (the in-memory limiter resets per instance).
|
|
40
|
-
6.
|
|
50
|
+
6. Prefer Web Standards (`Request`/`Response`, `fetch`, `Web Crypto`) even though Node APIs are available; Edge runtime code must avoid `node:` modules.
|
|
41
51
|
7. Keep a single `api/index.ts` entry and the `vercel.json` `/(.*)` → `/api` rewrite so DaloyJS handles all routing at the site root.
|
|
42
|
-
8.
|
|
52
|
+
8. Keep operation IDs stable and examples schema-valid; `pnpm contract` must pass after route, metadata, or OpenAPI-facing changes.
|
|
53
|
+
9. Every new route ships with a test that covers a happy path and at least one unhappy path.
|
|
43
54
|
|
|
44
55
|
## Secure-by-default (do not let an AI strip these)
|
|
45
56
|
|
|
46
|
-
Per Supabase + Aikido on [secure-by-default development](https://www.aikido.dev/blog/supabase-approach-to-secure-by-default-development):
|
|
57
|
+
Per Supabase + Aikido on [secure-by-default development](https://www.aikido.dev/blog/supabase-approach-to-secure-by-default-development): _"If you tell an AI to make something work, it might remove the very security checks that protect you."_ When a guard rejects a request, **satisfy it, do not delete it.**
|
|
47
58
|
|
|
48
|
-
- Keep `secureHeaders()`, `requestId()`, `rateLimit()
|
|
49
|
-
- Keep Zod `.strict()` on top-level request objects; do not switch to `.passthrough()`. Keep `responses[N].body` schemas tight; never widen to `z.any()` to let a privileged field escape.
|
|
50
|
-
- Every protected route attaches
|
|
59
|
+
- Keep `secureHeaders()`, `requestId()`, `rateLimit()`, `bodyLimitBytes`, and `requestTimeoutMs`. For production, back rate limits with Vercel KV or another shared store.
|
|
60
|
+
- Keep Zod `.strict()` on top-level request objects; do not switch to `.passthrough()`. For other validators, use the strict / no-extra-keys equivalent. Keep `responses[N].body` schemas tight; never widen to `z.any()` to let a privileged field escape.
|
|
61
|
+
- Every protected route attaches auth `beforeHandle` and tests unauthenticated `401` plus wrong-scope `403`.
|
|
51
62
|
- JWT verifiers keep an explicit `algorithms` allowlist; never trust the token's `alg` header, never allow `none`, always check `exp` / `nbf`.
|
|
52
|
-
- Credential / HMAC comparisons use
|
|
63
|
+
- Credential / HMAC comparisons use constant-time comparison, never `===`. Throw typed errors so problem+json redacts in prod.
|
|
53
64
|
- Keep the single `api/index.ts` entry and the `vercel.json` rewrite so DaloyJS owns routing — do not split into per-path files that bypass the middleware chain, and do not remove the rewrite (the root domain would 404).
|
|
54
65
|
- `.env`, `.env.local`, secrets, private keys: never commit. Use `vercel env` for production secrets.
|
|
55
66
|
|
|
56
67
|
## Process expectations
|
|
57
68
|
|
|
58
69
|
- Quality gates must pass before declaring work done: `pnpm typecheck` and `pnpm test`.
|
|
70
|
+
- Run the contract gate (`pnpm contract`) whenever route shapes, examples, operation IDs, or OpenAPI metadata change.
|
|
59
71
|
- Bug fixes include a regression test.
|
|
60
72
|
- For deploys, ensure the user has run `vercel login`; do not authenticate on their behalf.
|
|
61
73
|
- Never bypass safety checks without a clear reason.
|
|
@@ -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,
|
|
6
|
-
schemas, middleware,
|
|
7
|
-
typed Hey API client; keeping the
|
|
8
|
-
Web-Standard handler;
|
|
9
|
-
|
|
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. **
|
|
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
|
|
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.
|