create-daloy 0.1.24 → 0.3.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 +1 -0
- package/bin/create-daloy.mjs +16 -12
- package/package.json +1 -1
- package/templates/bun-basic/package.json +1 -1
- package/templates/bun-basic/src/index.ts +6 -2
- package/templates/cloudflare-worker/AGENTS.md +2 -2
- package/templates/cloudflare-worker/_agents/skills/daloyjs-best-practices/SKILL.md +5 -6
- package/templates/cloudflare-worker/package.json +1 -1
- package/templates/cloudflare-worker/src/index.ts +1 -1
- package/templates/cloudflare-worker/wrangler.toml +1 -1
- package/templates/deno-basic/deno.json +2 -2
- package/templates/deno-basic/src/main.ts +11 -7
- package/templates/node-basic/package.json +1 -1
- package/templates/vercel-edge/AGENTS.md +1 -1
- package/templates/vercel-edge/README.md +13 -2
- package/templates/vercel-edge/_agents/skills/daloyjs-best-practices/SKILL.md +4 -3
- package/templates/vercel-edge/api/[...path].ts +5 -2
- package/templates/vercel-edge/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,6 +83,7 @@ A Vercel Edge API bootstrap using `@daloyjs/core/vercel` with:
|
|
|
83
83
|
|
|
84
84
|
- `api/[...path].ts` catch-all routing so DaloyJS owns the API surface.
|
|
85
85
|
- `export const config = { runtime: "edge" }` ready for Vercel Edge.
|
|
86
|
+
- Node.js migration notes using Vercel's default `{ fetch }` export shape.
|
|
86
87
|
- `vercel dev` / `vercel deploy` scripts.
|
|
87
88
|
- `secureHeaders` and `requestId` enabled by default, with smaller edge-friendly body and timeout limits.
|
|
88
89
|
- A health route and bookstore route mirroring the Node starter.
|
package/bin/create-daloy.mjs
CHANGED
|
@@ -25,7 +25,7 @@ const TEMPLATE_OPTIONS = [
|
|
|
25
25
|
{
|
|
26
26
|
value: "vercel-edge",
|
|
27
27
|
title: "Vercel Edge",
|
|
28
|
-
description: "Catch-all Edge
|
|
28
|
+
description: "Catch-all Vercel Edge route with Node.js migration notes",
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
value: "cloudflare-worker",
|
|
@@ -248,13 +248,15 @@ function renderBox(lines, options = {}) {
|
|
|
248
248
|
return out.join("\n");
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
-
// Block-letter "
|
|
252
|
-
//
|
|
253
|
-
//
|
|
254
|
-
// from half-block characters so it stays
|
|
251
|
+
// Block-letter "DALOYJS" banner rendered with a left-to-right golden
|
|
252
|
+
// gradient (dark goldenrod → bright gold) on truecolor terminals. Falls back
|
|
253
|
+
// to a single bold-yellow line on 256-color TTYs and to plain text in dumb
|
|
254
|
+
// terminals. The shape is built from half-block characters so it stays
|
|
255
|
+
// compact (2 lines tall) and each glyph is 3 columns wide with a single
|
|
256
|
+
// space between letters, keeping the top and bottom rows perfectly aligned.
|
|
255
257
|
const LOGO_LINES = [
|
|
256
|
-
" \u2588\u2580\u2584
|
|
257
|
-
" \u2588\u2584\u2580
|
|
258
|
+
" \u2588\u2580\u2584 \u2584\u2580\u2588 \u2588 \u2588\u2580\u2588 \u2588 \u2588 \u2588 \u2584\u2580\u2580 ",
|
|
259
|
+
" \u2588\u2584\u2580 \u2588\u2580\u2588 \u2588\u2584\u2584 \u2588\u2584\u2588 \u2588 \u2584\u2584\u2588 \u2584\u2584\u2580 ",
|
|
258
260
|
];
|
|
259
261
|
|
|
260
262
|
function gradientLine(line, startRgb, endRgb) {
|
|
@@ -274,23 +276,25 @@ function gradientLine(line, startRgb, endRgb) {
|
|
|
274
276
|
|
|
275
277
|
function printBanner(version) {
|
|
276
278
|
if (!SUPPORTS_UNICODE) {
|
|
277
|
-
console.log(`\n${color(COLORS.bold, "create-daloy")} ${color(COLORS.dim, `v${version}`)}`);
|
|
279
|
+
console.log(`\n${color(COLORS.bold + COLORS.yellow, "create-daloy")} ${color(COLORS.dim, `v${version}`)}`);
|
|
278
280
|
console.log(color(COLORS.dim, "Contract-first REST APIs for Node, Bun, Deno, Vercel Edge, and Workers"));
|
|
279
281
|
console.log(color(COLORS.dim, "https://daloyjs.dev\n"));
|
|
280
282
|
return;
|
|
281
283
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
+
// Golden gradient: DarkGoldenrod → Gold. Evokes the DaloyJS "flow of gold"
|
|
285
|
+
// brand and stays legible on both light and dark terminal backgrounds.
|
|
286
|
+
const start = [184, 134, 11]; // DarkGoldenrod
|
|
287
|
+
const end = [255, 215, 0]; // Gold
|
|
284
288
|
console.log("");
|
|
285
289
|
for (const line of LOGO_LINES) {
|
|
286
290
|
console.log(` ${gradientLine(line, start, end)}`);
|
|
287
291
|
}
|
|
288
292
|
// Build the welcome content lines (each contains its own ANSI color codes).
|
|
289
|
-
const headline = `${color(COLORS.bold, "Welcome to DaloyJS")} ${color(COLORS.gray, `\u2014 v${version}`)}`;
|
|
293
|
+
const headline = `${color(COLORS.bold + COLORS.yellow, "Welcome to DaloyJS")} ${color(COLORS.gray, `\u2014 v${version}`)}`;
|
|
290
294
|
const subline = color(COLORS.dim, "Contract-first REST APIs for Node, Bun, Deno, Vercel Edge, and Workers.");
|
|
291
295
|
const docs = `${color(COLORS.gray, "docs:")} ${color(COLORS.cyan, "https://daloyjs.dev/docs")}`;
|
|
292
296
|
console.log("");
|
|
293
|
-
console.log(renderBox([headline, subline, "", docs]));
|
|
297
|
+
console.log(renderBox([headline, subline, "", docs], { accent: COLORS.yellow }));
|
|
294
298
|
console.log("");
|
|
295
299
|
}
|
|
296
300
|
|
package/package.json
CHANGED
|
@@ -4,8 +4,12 @@ import { buildApp } from "./build-app.ts";
|
|
|
4
4
|
const app = buildApp();
|
|
5
5
|
const port = Number(process.env.PORT ?? 3000);
|
|
6
6
|
|
|
7
|
-
serve(app, {
|
|
8
|
-
|
|
7
|
+
const handle = serve(app, {
|
|
8
|
+
port,
|
|
9
|
+
// Bun closes idle keep-alive connections after this many seconds.
|
|
10
|
+
idleTimeout: 30,
|
|
11
|
+
});
|
|
12
|
+
console.log(`DaloyJS (Bun) listening on ${handle.url ?? `http://localhost:${port}`}`);
|
|
9
13
|
// daloy-minimal:strip-start docs
|
|
10
14
|
console.log(` Swagger UI: http://localhost:${port}/docs`);
|
|
11
15
|
console.log(` OpenAPI JSON: http://localhost:${port}/openapi.json`);
|
|
@@ -15,7 +15,7 @@ A [DaloyJS](https://daloyjs.dev) REST API deployed to **Cloudflare Workers**. **
|
|
|
15
15
|
|
|
16
16
|
## Project shape
|
|
17
17
|
|
|
18
|
-
- `src/index.ts` — Worker entrypoint. Builds the `App`, registers routes/middleware, and exports `default
|
|
18
|
+
- `src/index.ts` — Worker entrypoint. Builds the `App`, registers routes/middleware, and exports `default toFetchHandler(app)` from `@daloyjs/core/cloudflare`. Do NOT wrap the result in another `{ fetch }` object — `toFetchHandler` already returns the shape Workers expect.
|
|
19
19
|
- `wrangler.toml` — Worker configuration (name, compatibility date, bindings, routes).
|
|
20
20
|
- `tests/` — test files.
|
|
21
21
|
|
|
@@ -26,7 +26,7 @@ A [DaloyJS](https://daloyjs.dev) REST API deployed to **Cloudflare Workers**. **
|
|
|
26
26
|
3. Preserve literal types in responses: `status: 200 as const`, `z.literal(...)` on discriminator fields.
|
|
27
27
|
4. Throw typed errors (`NotFoundError`, `BadRequestError`, etc.) from `@daloyjs/core`.
|
|
28
28
|
5. Keep `requestId()`, `secureHeaders()`, and `rateLimit()` enabled. For high-traffic routes, attach Cloudflare's native rate-limit binding (the in-memory limiter resets per isolate).
|
|
29
|
-
6. Stay on the Workers runtime: only Web Standards APIs + Cloudflare bindings. No `node:` modules unless `nodejs_compat`
|
|
29
|
+
6. Stay on the Workers runtime: only Web Standards APIs + Cloudflare bindings. No `node:` modules unless you explicitly add `nodejs_compat` and require it.
|
|
30
30
|
7. Bindings flow through `env`. Read KV/D1/R2/secrets from the `env` argument; never read them via globals.
|
|
31
31
|
8. Long-running work belongs in `ctx.waitUntil(...)`, not blocking the response.
|
|
32
32
|
9. Every new route ships with a test that covers a happy path and at least one unhappy path.
|
|
@@ -23,9 +23,8 @@ Do **not** use this skill for tasks unrelated to the API itself.
|
|
|
23
23
|
DaloyJS is a **contract-first** framework. On Workers, additionally:
|
|
24
24
|
|
|
25
25
|
1. **Stay on the Workers runtime.** Only Web Standards APIs and
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
opts in.
|
|
26
|
+
Cloudflare-specific bindings. No `node:` modules unless the user
|
|
27
|
+
explicitly adds `nodejs_compat` to `wrangler.toml` and opts in.
|
|
29
28
|
2. **The route definition is the contract.** Method, path, request
|
|
30
29
|
schemas, and response schemas live in one place (`app.route({...})`).
|
|
31
30
|
3. **Zod schemas validate at every boundary.**
|
|
@@ -40,8 +39,8 @@ DaloyJS is a **contract-first** framework. On Workers, additionally:
|
|
|
40
39
|
## Project shape
|
|
41
40
|
|
|
42
41
|
- `src/index.ts` — the Worker entrypoint. Builds the `App`, registers
|
|
43
|
-
routes/middleware, and exports `default
|
|
44
|
-
|
|
42
|
+
routes/middleware, and exports `default toFetchHandler(app)` from
|
|
43
|
+
`@daloyjs/core/cloudflare`. Do not wrap the result in another `{ fetch }`.
|
|
45
44
|
- `wrangler.toml` — Worker config (name, compatibility date, bindings,
|
|
46
45
|
routes).
|
|
47
46
|
- `tests/` — test files using Workers-compatible test runners (e.g.
|
|
@@ -115,7 +114,7 @@ function buildApp(env: Env) {
|
|
|
115
114
|
|
|
116
115
|
export default {
|
|
117
116
|
fetch: (req: Request, env: Env, ctx: ExecutionContext) =>
|
|
118
|
-
toFetchHandler(buildApp(env))(req, env, ctx),
|
|
117
|
+
toFetchHandler<Env>(buildApp(env)).fetch(req, env, ctx),
|
|
119
118
|
};
|
|
120
119
|
```
|
|
121
120
|
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"gen:openapi": "deno run --allow-net --allow-env --allow-read --allow-write scripts/dump-openapi.ts"
|
|
9
9
|
},
|
|
10
10
|
"imports": {
|
|
11
|
-
"@daloyjs/core": "npm:@daloyjs/core@^0.
|
|
12
|
-
"@daloyjs/core/": "npm:@daloyjs/core@^0.
|
|
11
|
+
"@daloyjs/core": "npm:@daloyjs/core@^0.8.2",
|
|
12
|
+
"@daloyjs/core/": "npm:@daloyjs/core@^0.8.2/",
|
|
13
13
|
"zod": "npm:zod@^4.4.3"
|
|
14
14
|
},
|
|
15
15
|
"compilerOptions": {
|
|
@@ -4,10 +4,14 @@ import { buildApp } from "./build-app.ts";
|
|
|
4
4
|
const app = buildApp();
|
|
5
5
|
const port = Number(Deno.env.get("PORT") ?? 3000);
|
|
6
6
|
|
|
7
|
-
serve(app, {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
console.log(`
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
console.log(`
|
|
7
|
+
serve(app, {
|
|
8
|
+
port,
|
|
9
|
+
onListen: ({ hostname, port: actualPort }) => {
|
|
10
|
+
console.log(`DaloyJS (Deno) listening on http://${hostname}:${actualPort}`);
|
|
11
|
+
// daloy-minimal:strip-start docs
|
|
12
|
+
console.log(` Swagger UI: http://${hostname}:${actualPort}/docs`);
|
|
13
|
+
console.log(` OpenAPI JSON: http://${hostname}:${actualPort}/openapi.json`);
|
|
14
|
+
// daloy-minimal:strip-end docs
|
|
15
|
+
console.log(` Health: http://${hostname}:${actualPort}/healthz`);
|
|
16
|
+
},
|
|
17
|
+
});
|
|
@@ -15,7 +15,7 @@ A [DaloyJS](https://daloyjs.dev) REST API deployed to **Vercel Edge**. **Contrac
|
|
|
15
15
|
|
|
16
16
|
## Project shape
|
|
17
17
|
|
|
18
|
-
- `api/[...path].ts` — Edge entrypoint. Builds the `App`, registers routes/middleware, and exports `default
|
|
18
|
+
- `api/[...path].ts` — Vercel Edge entrypoint. Builds the `App`, registers routes/middleware, and exports `default toWebHandler(app)` plus `export const config = { runtime: "edge" }`. **Keep it a catch-all** so DaloyJS owns routing. For Vercel's recommended Node.js runtime, remove the Edge config and export `default toFetchHandler(app)` from `@daloyjs/core/vercel`.
|
|
19
19
|
- `vercel.json` — Vercel build/runtime configuration.
|
|
20
20
|
- `tests/` — test files.
|
|
21
21
|
|
|
@@ -37,10 +37,21 @@ The API entry lives at `api/[...path].ts` and uses `@daloyjs/core/vercel`:
|
|
|
37
37
|
|
|
38
38
|
```ts
|
|
39
39
|
export const config = { runtime: "edge" };
|
|
40
|
-
export default
|
|
40
|
+
export default toWebHandler(app);
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
This starter defaults to Vercel's Edge runtime for compatibility with the
|
|
44
|
+
`vercel-edge` template name. Vercel now recommends Node.js for new projects;
|
|
45
|
+
for Node.js Functions, remove the `config` export and use the official default
|
|
46
|
+
`{ fetch }` shape instead:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { toFetchHandler } from "@daloyjs/core/vercel";
|
|
50
|
+
|
|
51
|
+
export default toFetchHandler(app);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
That catch-all API route lets DaloyJS own routing while Vercel handles the runtime.
|
|
44
55
|
|
|
45
56
|
## What's included
|
|
46
57
|
|
|
@@ -39,7 +39,7 @@ DaloyJS is a **contract-first** framework. On Vercel Edge, additionally:
|
|
|
39
39
|
## Project shape
|
|
40
40
|
|
|
41
41
|
- `api/[...path].ts` — the Edge entrypoint. Builds the `App`, registers
|
|
42
|
-
routes/middleware, and exports `default
|
|
42
|
+
routes/middleware, and exports `default toWebHandler(app)` plus
|
|
43
43
|
`export const config = { runtime: "edge" }`.
|
|
44
44
|
- `vercel.json` — Vercel build/runtime configuration.
|
|
45
45
|
- `tests/` — test files (`*.test.ts`).
|
|
@@ -179,8 +179,9 @@ Aim for **100% line and function coverage** on the routes you add.
|
|
|
179
179
|
handles routing. Do not split routes into multiple Vercel API files
|
|
180
180
|
unless the user explicitly asks (it disables shared middleware and a
|
|
181
181
|
unified OpenAPI).
|
|
182
|
-
- Use `
|
|
183
|
-
a `fetch(req)` adapter.
|
|
182
|
+
- Use `toWebHandler(app)` from `@daloyjs/core/vercel` for Edge — never
|
|
183
|
+
hand-roll a `fetch(req)` adapter. For Vercel's recommended Node.js
|
|
184
|
+
runtime, remove the Edge config and export `default toFetchHandler(app)`.
|
|
184
185
|
- Do not import `@daloyjs/core/node`, `@daloyjs/core/bun`, etc. — only
|
|
185
186
|
`@daloyjs/core` and `@daloyjs/core/vercel`.
|
|
186
187
|
- Avoid Node-only APIs (`Buffer`, `fs`, full `process` API). If a
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { App, NotFoundError, requestId, secureHeaders } from "@daloyjs/core";
|
|
3
|
-
import {
|
|
3
|
+
import { toWebHandler } from "@daloyjs/core/vercel";
|
|
4
4
|
// daloy-minimal:strip-start docs
|
|
5
5
|
import { generateOpenAPI } from "@daloyjs/core/openapi";
|
|
6
6
|
import { htmlResponse, swaggerUiHtml } from "@daloyjs/core/docs";
|
|
7
7
|
// daloy-minimal:strip-end docs
|
|
8
8
|
|
|
9
|
+
// This template defaults to Vercel's Edge runtime for compatibility with the
|
|
10
|
+
// existing `vercel-edge` starter. For Vercel's recommended Node.js runtime,
|
|
11
|
+
// remove this config and export `toFetchHandler(app)` from @daloyjs/core/vercel.
|
|
9
12
|
export const config = { runtime: "edge" };
|
|
10
13
|
|
|
11
14
|
const app = new App({
|
|
@@ -95,4 +98,4 @@ app.route({
|
|
|
95
98
|
});
|
|
96
99
|
// daloy-minimal:strip-end docs
|
|
97
100
|
|
|
98
|
-
export default
|
|
101
|
+
export default toWebHandler(app);
|