create-daloy 0.24.0 → 0.34.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.
Files changed (35) hide show
  1. package/README.md +18 -5
  2. package/bin/create-daloy.mjs +130 -37
  3. package/package.json +5 -3
  4. package/sbom.cdx.json +56 -0
  5. package/sbom.spdx.json +42 -0
  6. package/templates/_ci/deno/SECURITY.md +5 -1
  7. package/templates/_ci/deno/_github/dependabot.yml +12 -1
  8. package/templates/_ci/deno/_github/workflows/container-scan.yml +158 -0
  9. package/templates/_ci/node/SECURITY.md +33 -3
  10. package/templates/_ci/node/_github/CODEOWNERS +1 -1
  11. package/templates/_ci/node/_github/dependabot.yml +12 -1
  12. package/templates/_ci/node/_github/workflows/container-scan.yml +177 -0
  13. package/templates/_ci/node/_github/workflows/vuln-scan.yml +89 -0
  14. package/templates/bun-basic/AGENTS.md +10 -0
  15. package/templates/bun-basic/README.md +10 -0
  16. package/templates/bun-basic/_Dockerfile +57 -0
  17. package/templates/bun-basic/_dockerignore +11 -0
  18. package/templates/bun-basic/package.json +1 -1
  19. package/templates/cloudflare-worker/_Dockerfile +56 -0
  20. package/templates/cloudflare-worker/_dockerignore +13 -0
  21. package/templates/cloudflare-worker/package.json +1 -1
  22. package/templates/cloudflare-worker/src/index.ts +17 -0
  23. package/templates/deno-basic/_Dockerfile +66 -0
  24. package/templates/deno-basic/_dockerignore +10 -0
  25. package/templates/deno-basic/deno.json +2 -2
  26. package/templates/node-basic/AGENTS.md +10 -0
  27. package/templates/node-basic/README.md +10 -0
  28. package/templates/node-basic/_Dockerfile +23 -10
  29. package/templates/node-basic/package.json +1 -1
  30. package/templates/vercel-edge/AGENTS.md +10 -0
  31. package/templates/vercel-edge/README.md +10 -0
  32. package/templates/vercel-edge/_Dockerfile +55 -0
  33. package/templates/vercel-edge/_dockerignore +13 -0
  34. package/templates/vercel-edge/package.json +1 -1
  35. package/templates/_ci/node/_github/workflows/release.yml +0 -125
@@ -1,19 +1,31 @@
1
1
  # syntax=docker/dockerfile:1.7
2
- # Container-first defaults for a DaloyJS app (Wave 6 item 4).
2
+ # Container-first defaults for a DaloyJS app.
3
3
  #
4
4
  # Hardening shipped out of the box:
5
5
  # - Non-root runtime user (uid 1001).
6
6
  # - Read-only root filesystem at runtime (use `--read-only` or set
7
7
  # `readOnlyRootFilesystem: true` in your orchestrator).
8
8
  # - `STOPSIGNAL SIGTERM` so the framework's graceful-shutdown drain
9
- # (Wave 4) fires on container stop.
10
- # - `HEALTHCHECK` wired to `app.healthcheck()` / `app.readinesscheck()`
11
- # (mount the routes via `app.healthcheck()` / `app.readinesscheck()`).
9
+ # fires on container stop.
10
+ # - `HEALTHCHECK` wired to the `/healthz` route registered in
11
+ # `src/build-app.ts`.
12
12
  # - `tini` as PID 1 for proper signal forwarding and zombie reaping.
13
+ # - Minimal runner surface: no `curl` / no extra OS packages. The
14
+ # healthcheck uses BusyBox `wget` already in `node:*-alpine`.
15
+ # - Base image is consumed through the `NODE_IMAGE` ARG so you can
16
+ # pin to an immutable digest (recommended for production):
17
+ # docker build --build-arg \
18
+ # NODE_IMAGE=node:24-alpine@sha256:<digest> .
19
+ # Dependabot's `docker` ecosystem (see `.github/dependabot.yml`)
20
+ # keeps the digest fresh. The companion `container-scan.yml`
21
+ # workflow lints this file with hadolint and scans the built
22
+ # image with Trivy on every PR.
13
23
 
14
- ARG NODE_VERSION=24-alpine
24
+ # Override at build time to pin a specific digest:
25
+ # NODE_IMAGE=node:24-alpine@sha256:<digest>
26
+ ARG NODE_IMAGE=node:24-alpine
15
27
 
16
- FROM node:${NODE_VERSION} AS builder
28
+ FROM ${NODE_IMAGE} AS builder
17
29
  WORKDIR /app
18
30
  COPY package.json pnpm-lock.yaml* ./
19
31
  RUN corepack enable && corepack prepare pnpm@latest --activate && \
@@ -21,11 +33,12 @@ RUN corepack enable && corepack prepare pnpm@latest --activate && \
21
33
  COPY . .
22
34
  RUN pnpm build
23
35
 
24
- FROM node:${NODE_VERSION} AS runner
36
+ FROM ${NODE_IMAGE} AS runner
25
37
  WORKDIR /app
26
38
  ENV NODE_ENV=production
27
- # tini for clean signal handling at PID 1.
28
- RUN apk add --no-cache tini curl && \
39
+ # tini only no curl, no extra packages. BusyBox `wget` (already in
40
+ # alpine) is enough for the HEALTHCHECK below.
41
+ RUN apk add --no-cache tini && \
29
42
  addgroup -S app -g 1001 && \
30
43
  adduser -S app -G app -u 1001
31
44
  COPY --from=builder --chown=app:app /app/dist ./dist
@@ -35,6 +48,6 @@ USER app
35
48
  EXPOSE 3000
36
49
  STOPSIGNAL SIGTERM
37
50
  HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
38
- CMD curl -fsS http://127.0.0.1:3000/readyz || exit 1
51
+ CMD wget -q -O /dev/null --spider http://127.0.0.1:3000/healthz || exit 1
39
52
  ENTRYPOINT ["/sbin/tini", "--"]
40
53
  CMD ["node", "dist/index.js"]
@@ -18,7 +18,7 @@
18
18
  "audit": "pnpm audit --prod"
19
19
  },
20
20
  "dependencies": {
21
- "@daloyjs/core": "^0.30.0",
21
+ "@daloyjs/core": "^0.34.0",
22
22
  "zod": "^4.4.3"
23
23
  },
24
24
  "devDependencies": {
@@ -19,6 +19,16 @@ A [DaloyJS](https://daloyjs.dev) REST API deployed to **Vercel Edge**. **Contrac
19
19
  - `vercel.json` — Vercel build/runtime configuration.
20
20
  - `tests/` — test files.
21
21
 
22
+ ## Imports
23
+
24
+ This project uses TypeScript with `"module": "NodeNext"` (ESM). Relative imports **must include a `.js` extension**, even when the source file is `.ts`:
25
+
26
+ ```ts
27
+ import handler from "../api/[...path].js"; // resolves to the .ts source at typecheck, .js at runtime
28
+ ```
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.
31
+
22
32
  ## Core rules
23
33
 
24
34
  1. The route definition is the contract. Method, path, request schemas, and response schemas live in one place — `app.route({...})`.
@@ -57,6 +57,16 @@ export default toFetchHandler(app);
57
57
 
58
58
  That catch-all API route lets DaloyJS own routing while Vercel handles the runtime.
59
59
 
60
+ ## Imports
61
+
62
+ This project uses TypeScript with `"module": "NodeNext"` (ESM). Relative imports must include a `.js` extension, even when the source file is `.ts`:
63
+
64
+ ```ts
65
+ import handler from "../api/[...path].js"; // ../api/[...path].ts on disk
66
+ ```
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.
69
+
60
70
  ## What's included
61
71
 
62
72
  - `@daloyjs/core/vercel` with starter security middleware: `secureHeaders` and `requestId`.
@@ -0,0 +1,55 @@
1
+ # syntax=docker/dockerfile:1.7
2
+ # Containerized local-dev / CI environment for a DaloyJS Vercel Edge API.
3
+ #
4
+ # Production deploys go through `vercel deploy` to Vercel's managed
5
+ # Edge runtime — **this Dockerfile is not a production runtime**. Ship
6
+ # the function to Vercel; use this image for:
7
+ # - Reproducible local dev (devcontainers, GitHub Codespaces).
8
+ # - CI smoke tests that exercise the handler against `vercel dev`
9
+ # without installing Node/pnpm on the runner.
10
+ # - Self-hosted review apps when migrating to the `node-basic`
11
+ # template later.
12
+ #
13
+ # Hardening shipped out of the box:
14
+ # - Non-root runtime user (uid 1001).
15
+ # - Read-only-root-filesystem friendly: writes are confined to the
16
+ # working dir; mount `/tmp` as tmpfs (`--read-only --tmpfs /tmp`).
17
+ # - `STOPSIGNAL SIGTERM` so `vercel dev` exits cleanly.
18
+ # - Minimal runner surface: no `curl`, no extra OS packages.
19
+ # BusyBox `wget` powers the HEALTHCHECK.
20
+ # - `tini` as PID 1 for proper signal forwarding and zombie reaping
21
+ # (important because `vercel dev` spawns child processes).
22
+ # - `pnpm install --frozen-lockfile --ignore-scripts` matches the
23
+ # supply-chain defaults in `.npmrc` (no lifecycle scripts run).
24
+ # - Base image is consumed through the `NODE_IMAGE` ARG so builds
25
+ # can pin to an immutable digest:
26
+ # docker build --build-arg \
27
+ # NODE_IMAGE=node:24-alpine@sha256:<digest> .
28
+
29
+ # Override at build time to pin a specific digest.
30
+ ARG NODE_IMAGE=node:24-alpine
31
+
32
+ FROM ${NODE_IMAGE} AS builder
33
+ WORKDIR /app
34
+ COPY package.json pnpm-lock.yaml* ./
35
+ RUN corepack enable && corepack prepare pnpm@latest --activate && \
36
+ pnpm install --frozen-lockfile --ignore-scripts
37
+ COPY . .
38
+
39
+ FROM ${NODE_IMAGE} AS runner
40
+ WORKDIR /app
41
+ ENV NODE_ENV=development
42
+ # tini only — no curl, no extra packages.
43
+ RUN apk add --no-cache tini && \
44
+ addgroup -S app -g 1001 && \
45
+ adduser -S app -G app -u 1001
46
+ COPY --from=builder --chown=app:app /app /app
47
+ USER app
48
+ EXPOSE 3000
49
+ STOPSIGNAL SIGTERM
50
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
51
+ CMD wget -q -O /dev/null --spider http://127.0.0.1:3000/healthz || exit 1
52
+ ENTRYPOINT ["/sbin/tini", "--"]
53
+ # `vercel dev` binds the dev server. Listen on all interfaces so the
54
+ # container is reachable from the host network.
55
+ CMD ["./node_modules/.bin/vercel", "dev", "--listen", "0.0.0.0:3000"]
@@ -0,0 +1,13 @@
1
+ node_modules
2
+ .vercel
3
+ dist
4
+ coverage
5
+ .git
6
+ .github
7
+ .vscode
8
+ *.log
9
+ .env
10
+ .env.*
11
+ !.env.example
12
+ generated
13
+ otherdocs
@@ -10,7 +10,7 @@
10
10
  "test": "node --import tsx/esm --test tests/**/*.test.ts"
11
11
  },
12
12
  "dependencies": {
13
- "@daloyjs/core": "^0.30.0",
13
+ "@daloyjs/core": "^0.34.0",
14
14
  "zod": "^4.4.3"
15
15
  },
16
16
  "devDependencies": {
@@ -1,125 +0,0 @@
1
- # Hardened npm publish skeleton generated by create-daloy --with-ci.
2
- #
3
- # Publishing is disabled until you set the repository variable
4
- # NPM_PUBLISH_ENABLED=true, remove "private": true from package.json, and
5
- # configure npm trusted publishing for this repository/environment.
6
- name: Publish
7
-
8
- on:
9
- push:
10
- tags:
11
- - "v*"
12
- workflow_dispatch:
13
-
14
- permissions: {}
15
-
16
- concurrency:
17
- group: publish-${{ github.ref }}
18
- cancel-in-progress: false
19
-
20
- jobs:
21
- verify:
22
- name: Verify before publish
23
- runs-on: ubuntu-latest
24
- timeout-minutes: 20
25
- permissions:
26
- contents: read
27
- steps:
28
- - name: Harden runner
29
- uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
30
- with:
31
- egress-policy: audit
32
- disable-sudo: true
33
-
34
- - name: Checkout
35
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
36
- with:
37
- persist-credentials: false
38
- show-progress: false
39
-
40
- __SETUP_PACKAGE_MANAGER_STEP__
41
-
42
- - name: Set up Node.js
43
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
44
- with:
45
- node-version: 24
46
-
47
- __SETUP_BUN_RUNTIME_STEP__
48
-
49
- - name: Install dependencies
50
- run: __INSTALL_COMMAND__
51
- env:
52
- npm_config_ignore_scripts: "true"
53
-
54
- - name: Verify lockfile sources
55
- run: __VERIFY_LOCKFILE_COMMAND__
56
-
57
- - name: Typecheck
58
- run: __TYPECHECK_COMMAND__
59
-
60
- - name: Test
61
- run: __TEST_COMMAND__
62
-
63
- __BUILD_STEP__
64
-
65
- publish-npm:
66
- name: Publish npm package
67
- needs: verify
68
- if: vars.NPM_PUBLISH_ENABLED == 'true'
69
- runs-on: ubuntu-latest
70
- timeout-minutes: 15
71
- environment:
72
- name: ${{ vars.NPM_PUBLISH_ENVIRONMENT || 'npm-publish' }}
73
- url: https://www.npmjs.com/package/${{ github.event.repository.name }}
74
- permissions:
75
- contents: read
76
- id-token: write
77
-
78
- steps:
79
- - name: Harden runner
80
- uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2
81
- with:
82
- egress-policy: block
83
- allowed-endpoints: >
84
- api.github.com:443
85
- github.com:443
86
- objects.githubusercontent.com:443
87
- registry.npmjs.org:443
88
- fulcio.sigstore.dev:443
89
- rekor.sigstore.dev:443
90
- tuf-repo-cdn.sigstore.dev:443
91
- disable-sudo: true
92
-
93
- - name: Checkout
94
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
95
- with:
96
- persist-credentials: false
97
- show-progress: false
98
-
99
- __SETUP_PACKAGE_MANAGER_STEP__
100
-
101
- - name: Set up Node.js
102
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
103
- with:
104
- node-version: 24
105
- registry-url: "https://registry.npmjs.org"
106
-
107
- __SETUP_BUN_RUNTIME_STEP__
108
-
109
- - name: Install dependencies
110
- run: __INSTALL_COMMAND__
111
- env:
112
- npm_config_ignore_scripts: "true"
113
-
114
- - name: Refuse private package publish
115
- run: |
116
- node -e "const pkg = require('./package.json'); if (pkg.private) { console.error('package.json is private; remove private:true before enabling npm publish'); process.exit(1); }"
117
-
118
- __TAG_VERSION_CHECK_STEP__
119
-
120
- __BUILD_STEP__
121
-
122
- - name: Publish to npm with provenance
123
- run: npm publish --access public --provenance
124
- env:
125
- NPM_CONFIG_PROVENANCE: "true"