create-daloy 0.36.0 → 0.38.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/bin/create-daloy.mjs +59 -27
- package/package.json +1 -1
- package/sbom.cdx.json +9 -9
- package/sbom.spdx.json +5 -5
- package/templates/bun-basic/CLAUDE.md +1 -0
- package/templates/bun-basic/_agents/skills/daloyjs-best-practices/SKILL.md +11 -0
- package/templates/bun-basic/package.json +1 -1
- package/templates/cloudflare-worker/CLAUDE.md +1 -0
- package/templates/cloudflare-worker/_agents/skills/daloyjs-best-practices/SKILL.md +11 -0
- package/templates/cloudflare-worker/package.json +1 -1
- package/templates/deno-basic/AGENTS.md +2 -2
- package/templates/deno-basic/CLAUDE.md +1 -0
- package/templates/deno-basic/README.md +1 -1
- package/templates/deno-basic/_agents/skills/daloyjs-best-practices/SKILL.md +12 -1
- package/templates/deno-basic/deno.json +4 -2
- package/templates/deno-basic/deno.lock +35 -0
- package/templates/node-basic/AGENTS.md +3 -3
- package/templates/node-basic/CLAUDE.md +1 -0
- package/templates/node-basic/README.md +3 -3
- package/templates/node-basic/_agents/skills/daloyjs-best-practices/SKILL.md +10 -0
- package/templates/node-basic/package.json +1 -1
- package/templates/node-basic/scripts/dump-openapi.ts +1 -1
- package/templates/node-basic/src/index.ts +1 -1
- package/templates/node-basic/tsconfig.json +3 -1
- package/templates/vercel-edge/AGENTS.md +3 -3
- package/templates/vercel-edge/CLAUDE.md +1 -0
- package/templates/vercel-edge/README.md +3 -3
- package/templates/vercel-edge/_agents/skills/daloyjs-best-practices/SKILL.md +12 -0
- package/templates/vercel-edge/package.json +1 -1
- package/templates/vercel-edge/tests/app.test.ts +1 -1
- package/templates/vercel-edge/tsconfig.json +2 -1
package/bin/create-daloy.mjs
CHANGED
|
@@ -216,7 +216,8 @@ const SYMBOLS = SUPPORTS_UNICODE
|
|
|
216
216
|
const BAR = color(COLORS.gray, SYMBOLS.bar);
|
|
217
217
|
|
|
218
218
|
function printIntro(title) {
|
|
219
|
-
console.log(`${color(COLORS.cyan, SYMBOLS.cornerTL + SYMBOLS.lineH)} ${color(COLORS.bold, title)}`);
|
|
219
|
+
console.log(`${color(COLORS.cyan, SYMBOLS.cornerTL + SYMBOLS.lineH)} ${color(COLORS.bold + COLORS.white, title)}`);
|
|
220
|
+
console.log(`${BAR} ${color(COLORS.dim, "Answer a few prompts \u2014 arrow keys to move, Enter to confirm.")}`);
|
|
220
221
|
console.log(BAR);
|
|
221
222
|
}
|
|
222
223
|
|
|
@@ -259,17 +260,18 @@ function renderBox(lines, options = {}) {
|
|
|
259
260
|
// requests, and responses moving cleanly between client and server.
|
|
260
261
|
const LOGO_WAVE_LINES = SUPPORTS_UNICODE
|
|
261
262
|
? [
|
|
262
|
-
"\
|
|
263
|
-
"\
|
|
264
|
-
"\
|
|
263
|
+
"\u2248\u2248\u2248\u2248\u2248\u2248", // ≈≈≈≈≈≈
|
|
264
|
+
"\u2248\u2248\u2248\u2248\u2248\u2248",
|
|
265
|
+
"\u2248\u2248\u2248\u2248\u2248\u2248",
|
|
265
266
|
]
|
|
266
|
-
: ["
|
|
267
|
+
: ["~~~~~~", "~~~~~~", "~~~~~~"];
|
|
267
268
|
|
|
268
|
-
// Sky-blue palette
|
|
269
|
-
//
|
|
269
|
+
// Sky-blue palette anchored to the brand mark (website/public/assets/source/
|
|
270
|
+
// mark.svg): the three stacked waves are sky-200, sky-400, and sky-600. Each
|
|
271
|
+
// row fades slightly along its length so the cascade reads as flowing water.
|
|
270
272
|
const LOGO_WAVE_GRADIENTS = [
|
|
271
273
|
{ start: [186, 230, 253], end: [125, 211, 252] }, // sky-200 -> sky-300
|
|
272
|
-
{ start: [56, 189, 248], end: [
|
|
274
|
+
{ start: [56, 189, 248], end: [2, 132, 199] }, // sky-400 -> sky-600
|
|
273
275
|
{ start: [2, 132, 199], end: [3, 105, 161] }, // sky-600 -> sky-700
|
|
274
276
|
];
|
|
275
277
|
|
|
@@ -291,25 +293,45 @@ function gradientLine(line, startRgb, endRgb) {
|
|
|
291
293
|
function printBanner(version) {
|
|
292
294
|
if (!SUPPORTS_UNICODE) {
|
|
293
295
|
console.log(`\n${color(COLORS.bold + COLORS.cyan, "create-daloy")} ${color(COLORS.dim, `v${version}`)}`);
|
|
294
|
-
console.log(color(COLORS.dim, "
|
|
296
|
+
console.log(color(COLORS.dim, "The runtime-portable framework with supply-chain-aware defaults"));
|
|
297
|
+
console.log(color(COLORS.dim, "Secure-by-default runtime | Blocked install scripts | Source-verified lockfiles | Typed end-to-end"));
|
|
295
298
|
console.log(color(COLORS.dim, "https://daloyjs.dev\n"));
|
|
296
299
|
return;
|
|
297
300
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
302
|
-
// Centered wordmark beneath the waves: "Daloy" in neutral text, "JS" in
|
|
303
|
-
// brand sky-blue. Mirrors the SVG lockup used on the website.
|
|
301
|
+
|
|
302
|
+
// Brand lockup: the three-wave mark on the left sits beside the wordmark and
|
|
303
|
+
// tagline on the right — mirroring the social banner on https://daloyjs.dev.
|
|
304
304
|
const wordmark = `${color(COLORS.bold + COLORS.white, "Daloy")}${color(COLORS.bold + COLORS.cyan, "JS")}`;
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
305
|
+
const versionTag = color(COLORS.gray, `v${version}`);
|
|
306
|
+
const tagline = color(COLORS.gray, "The runtime-portable framework with supply-chain-aware defaults");
|
|
307
|
+
|
|
308
|
+
const waves = LOGO_WAVE_LINES.map((line, i) =>
|
|
309
|
+
gradientLine(line, LOGO_WAVE_GRADIENTS[i].start, LOGO_WAVE_GRADIENTS[i].end),
|
|
310
|
+
);
|
|
311
|
+
const gap = " ";
|
|
312
|
+
|
|
313
|
+
console.log("");
|
|
314
|
+
console.log(` ${waves[0]}`);
|
|
315
|
+
console.log(` ${waves[1]}${gap}${wordmark} ${versionTag}`);
|
|
316
|
+
console.log(` ${waves[2]}${gap}${tagline}`);
|
|
311
317
|
console.log("");
|
|
312
|
-
|
|
318
|
+
|
|
319
|
+
// Feature chips, brand-styled with cyan middots between dim labels.
|
|
320
|
+
const dot = color(COLORS.cyan, " \u00B7 ");
|
|
321
|
+
const chips = [
|
|
322
|
+
"Secure-by-default",
|
|
323
|
+
"Blocked install scripts",
|
|
324
|
+
"Source-verified lockfiles",
|
|
325
|
+
"Typed end-to-end",
|
|
326
|
+
]
|
|
327
|
+
.map((chip) => color(COLORS.dim, chip))
|
|
328
|
+
.join(dot);
|
|
329
|
+
console.log(` ${chips}`);
|
|
330
|
+
|
|
331
|
+
// Inverse-video "daloyjs.dev" badge, echoing the rounded pill in the brand
|
|
332
|
+
// banner. Inverse degrades to plain text when color is unavailable.
|
|
333
|
+
const pill = color(COLORS.cyan + COLORS.inverse, " daloyjs.dev ");
|
|
334
|
+
console.log(` ${pill} ${color(COLORS.gray, "docs:")} ${color(COLORS.cyan + COLORS.underline, "https://daloyjs.dev/docs")}`);
|
|
313
335
|
console.log("");
|
|
314
336
|
}
|
|
315
337
|
|
|
@@ -608,8 +630,12 @@ async function patchDockerfileForPackageManager(dir, packageManager) {
|
|
|
608
630
|
|
|
609
631
|
const raw = await readFile(file, "utf8");
|
|
610
632
|
const install = dockerInstallSnippet(packageManager);
|
|
633
|
+
// Match the pnpm install block tolerant of both LF and CRLF line endings.
|
|
634
|
+
// Windows checkouts (and packages published from Windows) can carry CRLF;
|
|
635
|
+
// an `\n`-only pattern would silently fail to match there, leaving the
|
|
636
|
+
// pnpm-specific COPY/RUN lines in place for npm/yarn/bun scaffolds.
|
|
611
637
|
let next = raw.replace(
|
|
612
|
-
/COPY package\.json pnpm-lock\.yaml\* \.\/\nRUN corepack enable && corepack prepare pnpm@latest --activate && \\\n
|
|
638
|
+
/COPY package\.json pnpm-lock\.yaml\* \.\/\r?\nRUN corepack enable && corepack prepare pnpm@latest --activate && \\\r?\n\s+pnpm install --frozen-lockfile --ignore-scripts/,
|
|
613
639
|
`${install.copy}\n${install.run}`,
|
|
614
640
|
);
|
|
615
641
|
|
|
@@ -623,8 +649,11 @@ async function patchDockerfileForPackageManager(dir, packageManager) {
|
|
|
623
649
|
|
|
624
650
|
if (packageManager === "bun" && next.includes("FROM ${NODE_IMAGE} AS builder")) {
|
|
625
651
|
if (!next.includes("ARG BUN_IMAGE=")) {
|
|
652
|
+
// CRLF-tolerant: the working tree may carry `\r\n`, so a plain
|
|
653
|
+
// `"...alpine\n"` substring replace would miss and the BUN_IMAGE ARG
|
|
654
|
+
// would never be inserted.
|
|
626
655
|
next = next.replace(
|
|
627
|
-
|
|
656
|
+
/ARG NODE_IMAGE=node:24-alpine\r?\n/,
|
|
628
657
|
"ARG NODE_IMAGE=node:24-alpine\nARG BUN_IMAGE=oven/bun:1-alpine\n",
|
|
629
658
|
);
|
|
630
659
|
}
|
|
@@ -1312,7 +1341,9 @@ async function askChoice(rl, question, choices, defaultChoice) {
|
|
|
1312
1341
|
const rawInput = rawInputHandle.stream;
|
|
1313
1342
|
|
|
1314
1343
|
printPromptHeader(question);
|
|
1315
|
-
printRailLine(
|
|
1344
|
+
printRailLine(
|
|
1345
|
+
`${color(COLORS.dim, "\u2191/\u2193")} ${color(COLORS.gray, "navigate")} ${color(COLORS.dim, "1\u20139")} ${color(COLORS.gray, "jump")} ${color(COLORS.dim, "enter")} ${color(COLORS.gray, "confirm")}`,
|
|
1346
|
+
);
|
|
1316
1347
|
|
|
1317
1348
|
let index = Math.max(
|
|
1318
1349
|
0,
|
|
@@ -1326,15 +1357,16 @@ async function askChoice(rl, question, choices, defaultChoice) {
|
|
|
1326
1357
|
.map((choice, i) => {
|
|
1327
1358
|
const isActive = i === active;
|
|
1328
1359
|
const isDefault = optionValue(choice) === defaultChoice;
|
|
1360
|
+
const pointer = isActive ? color(COLORS.cyan, SYMBOLS.pointer) : " ";
|
|
1329
1361
|
const marker = isActive ? color(COLORS.cyan, SYMBOLS.radioOn) : color(COLORS.gray, SYMBOLS.radioOff);
|
|
1330
1362
|
const titleRaw = optionTitle(choice).padEnd(titleWidth);
|
|
1331
1363
|
const valueRaw = optionValue(choice).padEnd(valueWidth);
|
|
1332
1364
|
const title = isActive ? color(COLORS.bold + COLORS.cyan, titleRaw) : color(COLORS.white, titleRaw);
|
|
1333
|
-
const value = color(COLORS.dim,
|
|
1365
|
+
const value = color(COLORS.dim, `${valueRaw}`);
|
|
1334
1366
|
const description = optionDescription(choice);
|
|
1335
1367
|
const descColored = isActive ? color(COLORS.cyan, description) : color(COLORS.dim, description);
|
|
1336
1368
|
const recommended = isDefault ? color(COLORS.green, ` ${SYMBOLS.star} recommended`) : "";
|
|
1337
|
-
return `${BAR} ${marker} ${title} ${value} ${descColored}${recommended}`;
|
|
1369
|
+
return `${BAR} ${pointer} ${marker} ${title} ${value} ${descColored}${recommended}`;
|
|
1338
1370
|
})
|
|
1339
1371
|
.join("\n");
|
|
1340
1372
|
}
|
package/package.json
CHANGED
package/sbom.cdx.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.5",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:b1a2eb69-121b-5cae-87a9-5d036a3e1a7a",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
|
-
"timestamp": "2026-
|
|
7
|
+
"timestamp": "2026-06-10T11:58:38.391Z",
|
|
8
8
|
"tools": [
|
|
9
9
|
{
|
|
10
10
|
"vendor": "DaloyJS",
|
|
11
11
|
"name": "daloy-generate-sbom",
|
|
12
|
-
"version": "0.
|
|
12
|
+
"version": "0.38.0"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
15
15
|
"authors": [],
|
|
16
16
|
"component": {
|
|
17
17
|
"type": "library",
|
|
18
|
-
"bom-ref": "pkg:npm/create-daloy@0.
|
|
18
|
+
"bom-ref": "pkg:npm/create-daloy@0.38.0",
|
|
19
19
|
"name": "create-daloy",
|
|
20
|
-
"version": "0.
|
|
20
|
+
"version": "0.38.0",
|
|
21
21
|
"description": "Scaffold a new DaloyJS project. Run with `pnpm create daloy`, `npm create daloy@latest`, `yarn create daloy`, or `bun create daloy`.",
|
|
22
|
-
"purl": "pkg:npm/create-daloy@0.
|
|
22
|
+
"purl": "pkg:npm/create-daloy@0.38.0",
|
|
23
23
|
"licenses": [
|
|
24
24
|
{
|
|
25
25
|
"license": {
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
}
|
|
43
43
|
],
|
|
44
44
|
"swid": {
|
|
45
|
-
"tagId": "swidtag-create-daloy-0.
|
|
45
|
+
"tagId": "swidtag-create-daloy-0.38.0",
|
|
46
46
|
"name": "create-daloy",
|
|
47
|
-
"version": "0.
|
|
47
|
+
"version": "0.38.0",
|
|
48
48
|
"tagVersion": 0,
|
|
49
49
|
"patch": false
|
|
50
50
|
}
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"components": [],
|
|
54
54
|
"dependencies": [
|
|
55
55
|
{
|
|
56
|
-
"ref": "pkg:npm/create-daloy@0.
|
|
56
|
+
"ref": "pkg:npm/create-daloy@0.38.0",
|
|
57
57
|
"dependsOn": []
|
|
58
58
|
}
|
|
59
59
|
]
|
package/sbom.spdx.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"spdxVersion": "SPDX-2.3",
|
|
3
3
|
"dataLicense": "CC0-1.0",
|
|
4
4
|
"SPDXID": "SPDXRef-DOCUMENT",
|
|
5
|
-
"name": "create-daloy-0.
|
|
6
|
-
"documentNamespace": "https://github.com/daloyjs/daloy/sbom/create-daloy-0.
|
|
5
|
+
"name": "create-daloy-0.38.0",
|
|
6
|
+
"documentNamespace": "https://github.com/daloyjs/daloy/sbom/create-daloy-0.38.0-b1a2eb69-121b-5cae-87a9-5d036a3e1a7a",
|
|
7
7
|
"creationInfo": {
|
|
8
|
-
"created": "2026-
|
|
8
|
+
"created": "2026-06-10T11:58:38.391Z",
|
|
9
9
|
"creators": [
|
|
10
10
|
"Tool: daloy-generate-sbom",
|
|
11
11
|
"Organization: DaloyJS"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{
|
|
17
17
|
"SPDXID": "SPDXRef-Package-create-daloy",
|
|
18
18
|
"name": "create-daloy",
|
|
19
|
-
"versionInfo": "0.
|
|
19
|
+
"versionInfo": "0.38.0",
|
|
20
20
|
"downloadLocation": "https://github.com/daloyjs/daloy",
|
|
21
21
|
"filesAnalyzed": false,
|
|
22
22
|
"licenseConcluded": "MIT",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
{
|
|
28
28
|
"referenceCategory": "PACKAGE-MANAGER",
|
|
29
29
|
"referenceType": "purl",
|
|
30
|
-
"referenceLocator": "pkg:npm/create-daloy@0.
|
|
30
|
+
"referenceLocator": "pkg:npm/create-daloy@0.38.0"
|
|
31
31
|
}
|
|
32
32
|
]
|
|
33
33
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: daloyjs-best-practices
|
|
3
|
+
description: >-
|
|
4
|
+
Best practices for building, testing, and hardening this DaloyJS REST API on
|
|
5
|
+
the Bun runtime. Use when adding or changing HTTP routes, Zod schemas,
|
|
6
|
+
middleware, or error handling; regenerating the OpenAPI spec or the typed
|
|
7
|
+
Hey API client; or working on auth, rate limits, secrets, and the project's
|
|
8
|
+
quality gates.
|
|
9
|
+
license: MIT
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# SKILL.md — DaloyJS best practices (Bun)
|
|
2
13
|
|
|
3
14
|
Operational guidance and best practices for AI coding agents working in this
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: daloyjs-best-practices
|
|
3
|
+
description: >-
|
|
4
|
+
Best practices for building, testing, and hardening this DaloyJS REST API on
|
|
5
|
+
Cloudflare Workers. Use when adding or changing HTTP routes, Zod schemas,
|
|
6
|
+
middleware, or error handling; wiring Worker bindings (KV, D1, R2, Queues,
|
|
7
|
+
env, secrets); or working on auth, rate limits, and the project's quality
|
|
8
|
+
gates.
|
|
9
|
+
license: MIT
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# SKILL.md — DaloyJS best practices (Cloudflare Workers)
|
|
2
13
|
|
|
3
14
|
Operational guidance and best practices for AI coding agents working in this
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A [DaloyJS](https://daloyjs.dev) REST API for the [Deno](https://deno.com) runtime. **Contract-first**: routes are defined with Zod schemas and OpenAPI 3.1 is generated from them. When `docs: true` is set in `new App({...})`, three routes are auto-mounted: `GET /openapi.json`, `GET /openapi.yaml`, and `GET /docs` (Scalar UI).
|
|
4
4
|
|
|
5
|
-
- Runtime: Deno (no Node package manager).
|
|
5
|
+
- Runtime: Deno (no Node package manager). DaloyJS loads from `jsr:` and third-party packages such as Zod load from `npm:` in `deno.json`.
|
|
6
6
|
|
|
7
7
|
## Commands
|
|
8
8
|
|
|
@@ -18,7 +18,7 @@ The typed Hey API SDK is generated outside Deno (Hey API has no Deno entrypoint
|
|
|
18
18
|
- `src/build-app.ts` — `buildApp()` factory. Routes, schemas, and middleware live here. **Pure, no side effects.**
|
|
19
19
|
- `src/main.ts` — calls `buildApp()` and starts the listener via `@daloyjs/core/deno`. The only file that opens a port.
|
|
20
20
|
- `scripts/dump-openapi.ts` — imports `buildApp()` and writes `generated/openapi.json`. Codegen reads from `buildApp()` only — never import `src/main.ts` from scripts.
|
|
21
|
-
- `deno.json` — tasks, import map, and
|
|
21
|
+
- `deno.json` — tasks, import map, and JSR-first dependency specifiers. There is no `package.json` in this project.
|
|
22
22
|
- `generated/` — machine-written. Do not edit by hand.
|
|
23
23
|
- `tests/` — Deno test files.
|
|
24
24
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -49,7 +49,7 @@ deno task test
|
|
|
49
49
|
|
|
50
50
|
## What's included
|
|
51
51
|
|
|
52
|
-
- `@daloyjs/core` (loaded via `
|
|
52
|
+
- `@daloyjs/core` (loaded via `jsr:` specifiers in `deno.json`).
|
|
53
53
|
- Starter security middleware: `secureHeaders`, `requestId`, and `rateLimit`.
|
|
54
54
|
<!-- daloy-minimal:strip-start books -->
|
|
55
55
|
- A health route and contract-first `/books/:id` route with Zod validation.
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: daloyjs-best-practices
|
|
3
|
+
description: >-
|
|
4
|
+
Best practices for building, testing, and hardening this DaloyJS REST API on
|
|
5
|
+
the Deno runtime. Use when adding or changing HTTP routes, Zod schemas,
|
|
6
|
+
middleware, or error handling; regenerating the OpenAPI spec; managing Deno
|
|
7
|
+
permissions and tasks; or working on auth, rate limits, secrets, and the
|
|
8
|
+
project's quality gates.
|
|
9
|
+
license: MIT
|
|
10
|
+
---
|
|
11
|
+
|
|
1
12
|
# SKILL.md — DaloyJS best practices (Deno)
|
|
2
13
|
|
|
3
14
|
Operational guidance and best practices for AI coding agents working in this
|
|
@@ -43,7 +54,7 @@ DaloyJS is a **contract-first** framework. Internalize these rules:
|
|
|
43
54
|
`@daloyjs/core/deno`. The only file allowed to open a port.
|
|
44
55
|
- `scripts/dump-openapi.ts` — imports `buildApp()` and writes
|
|
45
56
|
`generated/openapi.json`.
|
|
46
|
-
- `deno.json` — tasks, import map, and
|
|
57
|
+
- `deno.json` — tasks, import map, and JSR-first dependency specifiers. **There is no
|
|
47
58
|
`package.json`** in this project — do not add one.
|
|
48
59
|
- `tests/` — Deno test files (`*.test.ts`).
|
|
49
60
|
- `generated/` — **machine-written**. Never edit by hand.
|
|
@@ -8,8 +8,10 @@
|
|
|
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": "
|
|
12
|
-
"@daloyjs/core/": "
|
|
11
|
+
"@daloyjs/core": "jsr:@daloyjs/daloy@^0.38.0",
|
|
12
|
+
"@daloyjs/core/banner": "jsr:@daloyjs/daloy@^0.38.0/banner",
|
|
13
|
+
"@daloyjs/core/deno": "jsr:@daloyjs/daloy@^0.38.0/deno",
|
|
14
|
+
"@daloyjs/core/openapi": "jsr:@daloyjs/daloy@^0.38.0/openapi",
|
|
13
15
|
"zod": "npm:zod@^4.4.3"
|
|
14
16
|
},
|
|
15
17
|
"compilerOptions": {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "5",
|
|
3
|
+
"specifiers": {
|
|
4
|
+
"jsr:@std/assert@1": "1.0.19",
|
|
5
|
+
"jsr:@std/internal@^1.0.12": "1.0.14",
|
|
6
|
+
"npm:@daloyjs/core@0.37": "0.37.0",
|
|
7
|
+
"npm:zod@^4.4.3": "4.4.3"
|
|
8
|
+
},
|
|
9
|
+
"jsr": {
|
|
10
|
+
"@std/assert@1.0.19": {
|
|
11
|
+
"integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e",
|
|
12
|
+
"dependencies": [
|
|
13
|
+
"jsr:@std/internal"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
"@std/internal@1.0.14": {
|
|
17
|
+
"integrity": "291516b3d4c35024d6ffbc0a9df5bf4c64116e05b50012cf846710152d2ffdf7"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"npm": {
|
|
21
|
+
"@daloyjs/core@0.37.0": {
|
|
22
|
+
"integrity": "sha512-z7XRaoue2TqDIyQIdsg8ZKlBPmvYU8WX2ieYk3sGBMyt181bkb9NBgnxD/m6W54ojpiz4ArFRxyJ9BQTfjLvnQ==",
|
|
23
|
+
"bin": true
|
|
24
|
+
},
|
|
25
|
+
"zod@4.4.3": {
|
|
26
|
+
"integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"workspace": {
|
|
30
|
+
"dependencies": [
|
|
31
|
+
"npm:@daloyjs/core@0.37",
|
|
32
|
+
"npm:zod@^4.4.3"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -27,13 +27,13 @@ When `docs: true` is set in `new App({...})`, three routes are auto-mounted:
|
|
|
27
27
|
|
|
28
28
|
## Imports
|
|
29
29
|
|
|
30
|
-
This project uses TypeScript with `"module": "NodeNext"`
|
|
30
|
+
This project uses TypeScript with `"module": "NodeNext"` plus `"rewriteRelativeImportExtensions"`, so relative imports use the **`.ts` extension** — the actual file you see on disk:
|
|
31
31
|
|
|
32
32
|
```ts
|
|
33
|
-
import { buildApp } from "./build-app.
|
|
33
|
+
import { buildApp } from "./build-app.ts";
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
You import the file you see. On `pnpm build`, TypeScript rewrites the `.ts` specifier to `.js` in the compiled `dist/` output, so the deployed code is still valid Node ESM. (Node ESM has no extensionless relative imports — `.ts` is the most natural form available.) Bare-specifier imports from packages (`@daloyjs/core`, `zod`, …) do not need an extension.
|
|
37
37
|
|
|
38
38
|
## Core rules
|
|
39
39
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -48,13 +48,13 @@ node dist/index.js
|
|
|
48
48
|
|
|
49
49
|
## Imports
|
|
50
50
|
|
|
51
|
-
This project uses Node.js **ESM** with `"module": "NodeNext"`. Relative imports
|
|
51
|
+
This project uses Node.js **ESM** with `"module": "NodeNext"` and `"rewriteRelativeImportExtensions"`. Relative imports use the `.ts` extension — the actual file on disk:
|
|
52
52
|
|
|
53
53
|
```ts
|
|
54
|
-
import { buildApp } from "./build-app.
|
|
54
|
+
import { buildApp } from "./build-app.ts";
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
TypeScript
|
|
57
|
+
On `pnpm build`, TypeScript rewrites the `.ts` specifier to `.js` in the compiled `dist/` output, so the deployed code is valid Node ESM. (Node ESM has no extensionless relative imports — `.ts` is the most natural form available.)
|
|
58
58
|
|
|
59
59
|
## What's included
|
|
60
60
|
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: daloyjs-best-practices
|
|
3
|
+
description: >-
|
|
4
|
+
Best practices for building, testing, and hardening this DaloyJS REST API on
|
|
5
|
+
Node.js. Use when adding or changing HTTP routes, Zod schemas, middleware, or
|
|
6
|
+
error handling; regenerating the OpenAPI spec or the typed Hey API client; or
|
|
7
|
+
working on auth, rate limits, secrets, and the project's quality gates.
|
|
8
|
+
license: MIT
|
|
9
|
+
---
|
|
10
|
+
|
|
1
11
|
# SKILL.md — DaloyJS best practices (Node)
|
|
2
12
|
|
|
3
13
|
Operational guidance and best practices for AI coding agents working in this
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { writeFile, mkdir } from "node:fs/promises";
|
|
2
2
|
import { generateOpenAPI } from "@daloyjs/core/openapi";
|
|
3
|
-
import { buildApp } from "../src/build-app.
|
|
3
|
+
import { buildApp } from "../src/build-app.ts";
|
|
4
4
|
|
|
5
5
|
// Build a fresh app from the factory so the spec dump never starts the HTTP
|
|
6
6
|
// listener as a side effect. Keep this script deterministic so codegen output
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { serve } from "@daloyjs/core/node";
|
|
2
2
|
import { printStartupBanner, type StartupBannerLink } from "@daloyjs/core/banner";
|
|
3
|
-
import { buildApp } from "./build-app.
|
|
3
|
+
import { buildApp } from "./build-app.ts";
|
|
4
4
|
|
|
5
5
|
const app = buildApp();
|
|
6
6
|
const port = Number(process.env.PORT ?? 3000);
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
"esModuleInterop": true,
|
|
12
12
|
"skipLibCheck": true,
|
|
13
13
|
"forceConsistentCasingInFileNames": true,
|
|
14
|
-
"resolveJsonModule": true
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"allowImportingTsExtensions": true,
|
|
16
|
+
"rewriteRelativeImportExtensions": true
|
|
15
17
|
},
|
|
16
18
|
"include": ["src/**/*", "scripts/**/*", "tests/**/*"],
|
|
17
19
|
"exclude": ["node_modules", "dist"]
|
|
@@ -21,13 +21,13 @@ A [DaloyJS](https://daloyjs.dev) REST API deployed to **Vercel Edge**. **Contrac
|
|
|
21
21
|
|
|
22
22
|
## Imports
|
|
23
23
|
|
|
24
|
-
This project uses TypeScript with `"
|
|
24
|
+
This project uses TypeScript with `"allowImportingTsExtensions"`, so relative imports use the **`.ts` extension** — the actual file you see on disk:
|
|
25
25
|
|
|
26
26
|
```ts
|
|
27
|
-
import handler from "../api/[...path].
|
|
27
|
+
import handler from "../api/[...path].ts";
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
You import the file you see. Vercel bundles the `api/` functions at deploy time and resolves `.ts` directly, and the test runner (tsx) does too. Bare-specifier imports from packages (`@daloyjs/core`, `zod`, …) do not need an extension.
|
|
31
31
|
|
|
32
32
|
## Core rules
|
|
33
33
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@AGENTS.md
|
|
@@ -59,13 +59,13 @@ That catch-all API route lets DaloyJS own routing while Vercel handles the runti
|
|
|
59
59
|
|
|
60
60
|
## Imports
|
|
61
61
|
|
|
62
|
-
This project uses TypeScript with `"
|
|
62
|
+
This project uses TypeScript with `"allowImportingTsExtensions"`. Relative imports use the `.ts` extension — the actual file on disk:
|
|
63
63
|
|
|
64
64
|
```ts
|
|
65
|
-
import handler from "../api/[...path].
|
|
65
|
+
import handler from "../api/[...path].ts";
|
|
66
66
|
```
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
Vercel bundles the `api/` functions at deploy time and resolves `.ts` directly, and the test runner (tsx) does too.
|
|
69
69
|
|
|
70
70
|
## What's included
|
|
71
71
|
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: daloyjs-best-practices
|
|
3
|
+
description: >-
|
|
4
|
+
Best practices for building, testing, and hardening this DaloyJS REST API on
|
|
5
|
+
Vercel Edge. Use when adding or changing HTTP routes, Zod schemas,
|
|
6
|
+
middleware, or error handling; regenerating the OpenAPI spec or the typed
|
|
7
|
+
Hey API client; keeping the catch-all Edge entrypoint and Web-Standard
|
|
8
|
+
runtime constraints; or working on auth, rate limits, secrets, and the
|
|
9
|
+
project's quality gates.
|
|
10
|
+
license: MIT
|
|
11
|
+
---
|
|
12
|
+
|
|
1
13
|
# SKILL.md — DaloyJS best practices (Vercel Edge)
|
|
2
14
|
|
|
3
15
|
Operational guidance and best practices for AI coding agents working in this
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
|
-
import handler from "../api/[...path].
|
|
3
|
+
import handler from "../api/[...path].ts";
|
|
4
4
|
|
|
5
5
|
test("Vercel Edge handler responds through DaloyJS", async () => {
|
|
6
6
|
const response = await handler(new Request("https://example.test/healthz"));
|