create-daloy 0.37.0 → 0.38.1

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.
Files changed (38) hide show
  1. package/README.md +14 -0
  2. package/bin/create-daloy.mjs +9 -2
  3. package/package.json +1 -1
  4. package/sbom.cdx.json +9 -9
  5. package/sbom.spdx.json +5 -5
  6. package/templates/_ci/deno/_github/workflows/codeql.yml +2 -2
  7. package/templates/_ci/deno/_github/workflows/container-scan.yml +3 -3
  8. package/templates/_ci/deno/_github/workflows/opengrep.yml +1 -1
  9. package/templates/_ci/deno/_github/workflows/scorecard.yml +1 -1
  10. package/templates/_ci/node/_github/workflows/codeql.yml +2 -2
  11. package/templates/_ci/node/_github/workflows/container-scan.yml +3 -3
  12. package/templates/_ci/node/_github/workflows/opengrep.yml +1 -1
  13. package/templates/_ci/node/_github/workflows/scorecard.yml +1 -1
  14. package/templates/bun-basic/CLAUDE.md +1 -0
  15. package/templates/bun-basic/README.md +14 -0
  16. package/templates/bun-basic/package.json +1 -1
  17. package/templates/cloudflare-worker/CLAUDE.md +1 -0
  18. package/templates/cloudflare-worker/README.md +16 -0
  19. package/templates/cloudflare-worker/package.json +1 -1
  20. package/templates/deno-basic/AGENTS.md +2 -2
  21. package/templates/deno-basic/CLAUDE.md +1 -0
  22. package/templates/deno-basic/README.md +15 -1
  23. package/templates/deno-basic/_agents/skills/daloyjs-best-practices/SKILL.md +1 -1
  24. package/templates/deno-basic/deno.json +4 -2
  25. package/templates/deno-basic/deno.lock +35 -0
  26. package/templates/node-basic/AGENTS.md +3 -3
  27. package/templates/node-basic/CLAUDE.md +1 -0
  28. package/templates/node-basic/README.md +17 -3
  29. package/templates/node-basic/package.json +1 -1
  30. package/templates/node-basic/scripts/dump-openapi.ts +1 -1
  31. package/templates/node-basic/src/index.ts +1 -1
  32. package/templates/node-basic/tsconfig.json +3 -1
  33. package/templates/vercel-edge/AGENTS.md +3 -3
  34. package/templates/vercel-edge/CLAUDE.md +1 -0
  35. package/templates/vercel-edge/README.md +17 -3
  36. package/templates/vercel-edge/package.json +1 -1
  37. package/templates/vercel-edge/tests/app.test.ts +1 -1
  38. package/templates/vercel-edge/tsconfig.json +2 -1
package/README.md CHANGED
@@ -120,6 +120,20 @@ A [Deno](https://deno.com) runtime starter using `@daloyjs/core/deno` with:
120
120
  - A health route and contract-first `/books/:id` route with Zod validation.
121
121
  - The CLI skips Node-style installs for this template (no `package.json`).
122
122
 
123
+ ## Authentication (OAuth2 / OpenID Connect)
124
+
125
+ Scaffolded apps are **resource servers**: DaloyJS verifies and enforces access
126
+ tokens, it does **not** issue them. There is no built-in login UI, user
127
+ database, or OAuth2 authorization server (it is not an identity provider like
128
+ Keycloak, Auth0, or Duende IdentityServer). To add login, bring an OpenID
129
+ Connect provider — managed (Auth0, Okta, Clerk, Microsoft Entra ID, AWS
130
+ Cognito) or self-hosted open source (Keycloak, Zitadel, Ory, Logto) — and have
131
+ DaloyJS verify its JWTs with the first-party `jwk()`, `bearerAuth()`, and
132
+ `requireScopes()` helpers. Don't build your own authorization server.
133
+
134
+ See [Auth architecture](https://daloyjs.dev/docs/auth/architecture) for the full
135
+ picture and the two recommended designs (API resource server and browser BFF).
136
+
123
137
  ## Minimal scaffolds
124
138
 
125
139
  Pass `--minimal` to drop the bookstore demo route and the built-in
@@ -630,8 +630,12 @@ async function patchDockerfileForPackageManager(dir, packageManager) {
630
630
 
631
631
  const raw = await readFile(file, "utf8");
632
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.
633
637
  let next = raw.replace(
634
- /COPY package\.json pnpm-lock\.yaml\* \.\/\nRUN corepack enable && corepack prepare pnpm@latest --activate && \\\n+\s+pnpm install --frozen-lockfile --ignore-scripts/,
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/,
635
639
  `${install.copy}\n${install.run}`,
636
640
  );
637
641
 
@@ -645,8 +649,11 @@ async function patchDockerfileForPackageManager(dir, packageManager) {
645
649
 
646
650
  if (packageManager === "bun" && next.includes("FROM ${NODE_IMAGE} AS builder")) {
647
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.
648
655
  next = next.replace(
649
- "ARG NODE_IMAGE=node:24-alpine\n",
656
+ /ARG NODE_IMAGE=node:24-alpine\r?\n/,
650
657
  "ARG NODE_IMAGE=node:24-alpine\nARG BUN_IMAGE=oven/bun:1-alpine\n",
651
658
  );
652
659
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-daloy",
3
- "version": "0.37.0",
3
+ "version": "0.38.1",
4
4
  "description": "Scaffold a new DaloyJS project. Run with `pnpm create daloy`, `npm create daloy@latest`, `yarn create daloy`, or `bun create daloy`.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/sbom.cdx.json CHANGED
@@ -1,25 +1,25 @@
1
1
  {
2
2
  "bomFormat": "CycloneDX",
3
3
  "specVersion": "1.5",
4
- "serialNumber": "urn:uuid:a4416ef1-59e7-5669-9295-8eb452a49fdf",
4
+ "serialNumber": "urn:uuid:5874d6d1-4f7c-5889-b1dc-59abaf86bc40",
5
5
  "version": 1,
6
6
  "metadata": {
7
- "timestamp": "2026-05-31T20:28:16.974Z",
7
+ "timestamp": "2026-06-11T09:54:26.989Z",
8
8
  "tools": [
9
9
  {
10
10
  "vendor": "DaloyJS",
11
11
  "name": "daloy-generate-sbom",
12
- "version": "0.37.0"
12
+ "version": "0.38.1"
13
13
  }
14
14
  ],
15
15
  "authors": [],
16
16
  "component": {
17
17
  "type": "library",
18
- "bom-ref": "pkg:npm/create-daloy@0.37.0",
18
+ "bom-ref": "pkg:npm/create-daloy@0.38.1",
19
19
  "name": "create-daloy",
20
- "version": "0.37.0",
20
+ "version": "0.38.1",
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.37.0",
22
+ "purl": "pkg:npm/create-daloy@0.38.1",
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.37.0",
45
+ "tagId": "swidtag-create-daloy-0.38.1",
46
46
  "name": "create-daloy",
47
- "version": "0.37.0",
47
+ "version": "0.38.1",
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.37.0",
56
+ "ref": "pkg:npm/create-daloy@0.38.1",
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.37.0",
6
- "documentNamespace": "https://github.com/daloyjs/daloy/sbom/create-daloy-0.37.0-a4416ef1-59e7-5669-9295-8eb452a49fdf",
5
+ "name": "create-daloy-0.38.1",
6
+ "documentNamespace": "https://github.com/daloyjs/daloy/sbom/create-daloy-0.38.1-5874d6d1-4f7c-5889-b1dc-59abaf86bc40",
7
7
  "creationInfo": {
8
- "created": "2026-05-31T20:28:16.974Z",
8
+ "created": "2026-06-11T09:54:26.989Z",
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.37.0",
19
+ "versionInfo": "0.38.1",
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.37.0"
30
+ "referenceLocator": "pkg:npm/create-daloy@0.38.1"
31
31
  }
32
32
  ]
33
33
  }
@@ -44,13 +44,13 @@ jobs:
44
44
  show-progress: false
45
45
 
46
46
  - name: Initialize CodeQL
47
- uses: github/codeql-action/init@52485aec7be33610227643b0fe83936b8b5f061a # v3
47
+ uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
48
48
  with:
49
49
  languages: ${{ matrix.language }}
50
50
  build-mode: ${{ matrix.build-mode }}
51
51
  queries: security-extended,security-and-quality
52
52
 
53
53
  - name: Perform CodeQL Analysis
54
- uses: github/codeql-action/analyze@52485aec7be33610227643b0fe83936b8b5f061a # v3
54
+ uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
55
55
  with:
56
56
  category: "/language:${{ matrix.language }}"
@@ -139,7 +139,7 @@ jobs:
139
139
 
140
140
  - name: Upload hadolint SARIF
141
141
  if: steps.detect.outputs.present == 'true'
142
- uses: github/codeql-action/upload-sarif@52485aec7be33610227643b0fe83936b8b5f061a # v3
142
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
143
143
  with:
144
144
  sarif_file: hadolint.sarif
145
145
  category: hadolint
@@ -162,7 +162,7 @@ jobs:
162
162
  exit-code: "0"
163
163
 
164
164
  - name: Upload Trivy filesystem SARIF
165
- uses: github/codeql-action/upload-sarif@52485aec7be33610227643b0fe83936b8b5f061a # v3
165
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
166
166
  with:
167
167
  sarif_file: trivy-fs.sarif
168
168
  category: trivy-fs
@@ -186,7 +186,7 @@ jobs:
186
186
 
187
187
  - name: Upload Trivy image SARIF
188
188
  if: always() && steps.detect.outputs.present == 'true'
189
- uses: github/codeql-action/upload-sarif@52485aec7be33610227643b0fe83936b8b5f061a # v3
189
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
190
190
  with:
191
191
  sarif_file: trivy-image.sarif
192
192
  category: trivy-image
@@ -131,7 +131,7 @@ jobs:
131
131
 
132
132
  - name: Upload SARIF to GitHub code scanning
133
133
  if: always()
134
- uses: github/codeql-action/upload-sarif@52485aec7be33610227643b0fe83936b8b5f061a # v3
134
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
135
135
  with:
136
136
  sarif_file: opengrep.sarif
137
137
  category: opengrep
@@ -41,6 +41,6 @@ jobs:
41
41
  publish_results: true
42
42
 
43
43
  - name: Upload to code-scanning
44
- uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
44
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
45
45
  with:
46
46
  sarif_file: results.sarif
@@ -44,13 +44,13 @@ jobs:
44
44
  show-progress: false
45
45
 
46
46
  - name: Initialize CodeQL
47
- uses: github/codeql-action/init@52485aec7be33610227643b0fe83936b8b5f061a # v3
47
+ uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
48
48
  with:
49
49
  languages: ${{ matrix.language }}
50
50
  build-mode: ${{ matrix.build-mode }}
51
51
  queries: security-extended,security-and-quality
52
52
 
53
53
  - name: Perform CodeQL Analysis
54
- uses: github/codeql-action/analyze@52485aec7be33610227643b0fe83936b8b5f061a # v3
54
+ uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
55
55
  with:
56
56
  category: "/language:${{ matrix.language }}"
@@ -157,7 +157,7 @@ jobs:
157
157
 
158
158
  - name: Upload hadolint SARIF
159
159
  if: steps.detect.outputs.present == 'true'
160
- uses: github/codeql-action/upload-sarif@52485aec7be33610227643b0fe83936b8b5f061a # v3
160
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
161
161
  with:
162
162
  sarif_file: hadolint.sarif
163
163
  category: hadolint
@@ -180,7 +180,7 @@ jobs:
180
180
  exit-code: "0"
181
181
 
182
182
  - name: Upload Trivy filesystem SARIF
183
- uses: github/codeql-action/upload-sarif@52485aec7be33610227643b0fe83936b8b5f061a # v3
183
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
184
184
  with:
185
185
  sarif_file: trivy-fs.sarif
186
186
  category: trivy-fs
@@ -207,7 +207,7 @@ jobs:
207
207
 
208
208
  - name: Upload Trivy image SARIF
209
209
  if: always() && steps.detect.outputs.present == 'true'
210
- uses: github/codeql-action/upload-sarif@52485aec7be33610227643b0fe83936b8b5f061a # v3
210
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
211
211
  with:
212
212
  sarif_file: trivy-image.sarif
213
213
  category: trivy-image
@@ -163,7 +163,7 @@ jobs:
163
163
 
164
164
  - name: Upload SARIF to GitHub code scanning
165
165
  if: always()
166
- uses: github/codeql-action/upload-sarif@52485aec7be33610227643b0fe83936b8b5f061a # v3
166
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
167
167
  with:
168
168
  sarif_file: opengrep.sarif
169
169
  category: opengrep
@@ -41,6 +41,6 @@ jobs:
41
41
  publish_results: true
42
42
 
43
43
  - name: Upload to code-scanning
44
- uses: github/codeql-action/upload-sarif@e46ed2cbd01164d986452f91f178727624ae40d7 # v4.35.3
44
+ uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2
45
45
  with:
46
46
  sarif_file: results.sarif
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -63,4 +63,18 @@ Do not use `.js` here — that's the Node NodeNext convention and will not resol
63
63
  - Hot reload via `bun --hot`.
64
64
  - Hey API codegen wired to `bun run gen:openapi` + `bun run gen:client`.
65
65
 
66
+ ## Authentication (OAuth2 / OpenID Connect)
67
+
68
+ This app is a **resource server**: DaloyJS verifies and enforces access tokens,
69
+ it does **not** issue them. There is no built-in login UI, user database, or
70
+ OAuth2 authorization server (it is not an identity provider like Keycloak,
71
+ Auth0, or Duende IdentityServer). To add login, bring an OpenID Connect provider
72
+ — managed (Auth0, Okta, Clerk, Microsoft Entra ID, AWS Cognito) or self-hosted
73
+ open source (Keycloak, Zitadel, Ory, Logto) — and verify its JWTs with the
74
+ first-party `jwk()`, `bearerAuth()`, and `requireScopes()` helpers. Don't build
75
+ your own authorization server.
76
+
77
+ See [Auth architecture](https://daloyjs.dev/docs/auth/architecture) for the
78
+ recommended designs (API resource server and browser BFF).
79
+
66
80
  Read the docs at <https://daloyjs.dev/docs>.
@@ -17,7 +17,7 @@
17
17
  "audit": "pnpm audit --prod"
18
18
  },
19
19
  "dependencies": {
20
- "@daloyjs/core": "^0.37.0",
20
+ "@daloyjs/core": "^0.38.1",
21
21
  "zod": "^4.4.3"
22
22
  },
23
23
  "devDependencies": {
@@ -0,0 +1 @@
1
+ @AGENTS.md
@@ -22,3 +22,19 @@ pnpm deploy
22
22
  - `@daloyjs/core/cloudflare` with starter security middleware: `secureHeaders` and `requestId`.
23
23
  - Smaller edge-friendly body and timeout limits in the generated app.
24
24
  - `wrangler.toml` ready for local development and deploys.
25
+
26
+ ## Authentication (OAuth2 / OpenID Connect)
27
+
28
+ This app is a **resource server**: DaloyJS verifies and enforces access tokens,
29
+ it does **not** issue them. There is no built-in login UI, user database, or
30
+ OAuth2 authorization server (it is not an identity provider like Keycloak,
31
+ Auth0, or Duende IdentityServer). To add login, bring an OpenID Connect provider
32
+ — managed (Auth0, Okta, Clerk, Microsoft Entra ID, AWS Cognito) or self-hosted
33
+ open source (Keycloak, Zitadel, Ory, Logto) — and verify its JWTs with the
34
+ first-party `jwk()`, `bearerAuth()`, and `requireScopes()` helpers. Don't build
35
+ your own authorization server.
36
+
37
+ See [Auth architecture](https://daloyjs.dev/docs/auth/architecture) for the
38
+ recommended designs (API resource server and browser BFF).
39
+
40
+ Read the docs at <https://daloyjs.dev/docs>.
@@ -11,7 +11,7 @@
11
11
  "audit": "pnpm audit --prod"
12
12
  },
13
13
  "dependencies": {
14
- "@daloyjs/core": "^0.37.0",
14
+ "@daloyjs/core": "^0.38.1",
15
15
  "zod": "^4.4.3"
16
16
  },
17
17
  "devDependencies": {
@@ -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). Dependencies are loaded via `npm:` and `jsr:` specifiers in `deno.json`.
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 `npm:` specifiers. There is no `package.json` in this project.
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,11 +49,25 @@ deno task test
49
49
 
50
50
  ## What's included
51
51
 
52
- - `@daloyjs/core` (loaded via `npm:` specifiers in `deno.json`).
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.
56
56
  <!-- daloy-minimal:strip-end books -->
57
57
  - Minimal permissions: `--allow-net --allow-env --allow-read` for `dev`.
58
58
 
59
+ ## Authentication (OAuth2 / OpenID Connect)
60
+
61
+ This app is a **resource server**: DaloyJS verifies and enforces access tokens,
62
+ it does **not** issue them. There is no built-in login UI, user database, or
63
+ OAuth2 authorization server (it is not an identity provider like Keycloak,
64
+ Auth0, or Duende IdentityServer). To add login, bring an OpenID Connect provider
65
+ — managed (Auth0, Okta, Clerk, Microsoft Entra ID, AWS Cognito) or self-hosted
66
+ open source (Keycloak, Zitadel, Ory, Logto) — and verify its JWTs with the
67
+ first-party `jwk()`, `bearerAuth()`, and `requireScopes()` helpers. Don't build
68
+ your own authorization server.
69
+
70
+ See [Auth architecture](https://daloyjs.dev/docs/auth/architecture) for the
71
+ recommended designs (API resource server and browser BFF).
72
+
59
73
  Read the docs at <https://daloyjs.dev/docs>.
@@ -54,7 +54,7 @@ DaloyJS is a **contract-first** framework. Internalize these rules:
54
54
  `@daloyjs/core/deno`. The only file allowed to open a port.
55
55
  - `scripts/dump-openapi.ts` — imports `buildApp()` and writes
56
56
  `generated/openapi.json`.
57
- - `deno.json` — tasks, import map, and `npm:` specifiers. **There is no
57
+ - `deno.json` — tasks, import map, and JSR-first dependency specifiers. **There is no
58
58
  `package.json`** in this project — do not add one.
59
59
  - `tests/` — Deno test files (`*.test.ts`).
60
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": "npm:@daloyjs/core@^0.37.0",
12
- "@daloyjs/core/": "npm:@daloyjs/core@^0.37.0/",
11
+ "@daloyjs/core": "jsr:@daloyjs/daloy@^0.38.1",
12
+ "@daloyjs/core/banner": "jsr:@daloyjs/daloy@^0.38.1/banner",
13
+ "@daloyjs/core/deno": "jsr:@daloyjs/daloy@^0.38.1/deno",
14
+ "@daloyjs/core/openapi": "jsr:@daloyjs/daloy@^0.38.1/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"` (ESM). Relative imports **must include a `.js` extension**, even when the source file is `.ts`:
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.js"; // resolves to build-app.ts at typecheck, build-app.js at runtime
33
+ import { buildApp } from "./build-app.ts";
34
34
  ```
35
35
 
36
- This is the official Node.js ESM convention TypeScript rewrites the specifier during typecheck, and the compiled output really is `.js`. Bare-specifier imports from packages (`@daloyjs/core`, `zod`, …) do not need an extension.
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 must include a `.js` extension, even when the source file is `.ts`:
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.js"; // ./build-app.ts on disk
54
+ import { buildApp } from "./build-app.ts";
55
55
  ```
56
56
 
57
- TypeScript resolves the `.js` specifier to the matching `.ts` file at typecheck, and the compiled output really is `.js`. This is the official Node ESM conventionnot a typo.
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
 
@@ -65,4 +65,18 @@ TypeScript resolves the `.js` specifier to the matching `.ts` file at typecheck,
65
65
  - Hardened `.npmrc` for safer installs.
66
66
  - Hey API codegen wired to `pnpm gen`.
67
67
 
68
+ ## Authentication (OAuth2 / OpenID Connect)
69
+
70
+ This app is a **resource server**: DaloyJS verifies and enforces access tokens,
71
+ it does **not** issue them. There is no built-in login UI, user database, or
72
+ OAuth2 authorization server (it is not an identity provider like Keycloak,
73
+ Auth0, or Duende IdentityServer). To add login, bring an OpenID Connect provider
74
+ — managed (Auth0, Okta, Clerk, Microsoft Entra ID, AWS Cognito) or self-hosted
75
+ open source (Keycloak, Zitadel, Ory, Logto) — and verify its JWTs with the
76
+ first-party `jwk()`, `bearerAuth()`, and `requireScopes()` helpers. Don't build
77
+ your own authorization server.
78
+
79
+ See [Auth architecture](https://daloyjs.dev/docs/auth/architecture) for the
80
+ recommended designs (API resource server and browser BFF).
81
+
68
82
  Read the docs at <https://daloyjs.dev/docs>.
@@ -18,7 +18,7 @@
18
18
  "audit": "pnpm audit --prod"
19
19
  },
20
20
  "dependencies": {
21
- "@daloyjs/core": "^0.37.0",
21
+ "@daloyjs/core": "^0.38.1",
22
22
  "zod": "^4.4.3"
23
23
  },
24
24
  "devDependencies": {
@@ -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.js";
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.js";
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 `"module": "NodeNext"` (ESM). Relative imports **must include a `.js` extension**, even when the source file is `.ts`:
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].js"; // resolves to the .ts source at typecheck, .js at runtime
27
+ import handler from "../api/[...path].ts";
28
28
  ```
29
29
 
30
- This is the official Node.js ESM convention TypeScript rewrites the specifier during typecheck, and the deployed output really is `.js`. Bare-specifier imports from packages (`@daloyjs/core`, `zod`, …) do not need an extension.
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 `"module": "NodeNext"` (ESM). Relative imports must include a `.js` extension, even when the source file is `.ts`:
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].js"; // ../api/[...path].ts on disk
65
+ import handler from "../api/[...path].ts";
66
66
  ```
67
67
 
68
- TypeScript resolves the `.js` specifier to the matching `.ts` file at typecheck, and the deployed output really is `.js`. This is the official Node ESM convention — not a typo.
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
 
@@ -77,3 +77,17 @@ TypeScript resolves the `.js` specifier to the matching `.ts` file at typecheck,
77
77
  <!-- daloy-minimal:strip-start docs -->
78
78
  - A Scalar API reference UI at `/docs`, plus live OpenAPI 3.1 specs at `/openapi.json` and `/openapi.yaml`.
79
79
  <!-- daloy-minimal:strip-end docs -->
80
+
81
+ ## Authentication (OAuth2 / OpenID Connect)
82
+
83
+ This app is a **resource server**: DaloyJS verifies and enforces access tokens,
84
+ it does **not** issue them. There is no built-in login UI, user database, or
85
+ OAuth2 authorization server (it is not an identity provider like Keycloak,
86
+ Auth0, or Duende IdentityServer). To add login, bring an OpenID Connect provider
87
+ — managed (Auth0, Okta, Clerk, Microsoft Entra ID, AWS Cognito) or self-hosted
88
+ open source (Keycloak, Zitadel, Ory, Logto) — and verify its JWTs with the
89
+ first-party `jwk()`, `bearerAuth()`, and `requireScopes()` helpers. Don't build
90
+ your own authorization server.
91
+
92
+ See [Auth architecture](https://daloyjs.dev/docs/auth/architecture) for the
93
+ recommended designs (API resource server and browser BFF).
@@ -11,7 +11,7 @@
11
11
  "audit": "pnpm audit --prod"
12
12
  },
13
13
  "dependencies": {
14
- "@daloyjs/core": "^0.37.0",
14
+ "@daloyjs/core": "^0.38.1",
15
15
  "zod": "^4.4.3"
16
16
  },
17
17
  "devDependencies": {
@@ -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].js";
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"));
@@ -12,7 +12,8 @@
12
12
  "forceConsistentCasingInFileNames": true,
13
13
  "resolveJsonModule": true,
14
14
  "isolatedModules": true,
15
- "noEmit": true
15
+ "noEmit": true,
16
+ "allowImportingTsExtensions": true
16
17
  },
17
18
  "include": ["api/**/*.ts", "tests/**/*.ts"]
18
19
  }