create-daloy 0.26.0 → 0.34.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.
- package/README.md +18 -5
- package/bin/create-daloy.mjs +169 -37
- package/package.json +4 -2
- package/sbom.cdx.json +56 -0
- package/sbom.spdx.json +42 -0
- package/templates/_ci/deno/SECURITY.md +5 -1
- package/templates/_ci/deno/_github/dependabot.yml +12 -1
- package/templates/_ci/deno/_github/workflows/container-scan.yml +158 -0
- package/templates/_ci/node/SECURITY.md +33 -3
- package/templates/_ci/node/_github/CODEOWNERS +1 -1
- package/templates/_ci/node/_github/dependabot.yml +12 -1
- package/templates/_ci/node/_github/workflows/container-scan.yml +177 -0
- package/templates/_ci/node/_github/workflows/vuln-scan.yml +89 -0
- package/templates/bun-basic/AGENTS.md +10 -0
- package/templates/bun-basic/README.md +10 -0
- package/templates/bun-basic/_Dockerfile +57 -0
- package/templates/bun-basic/_dockerignore +12 -0
- package/templates/bun-basic/package.json +1 -1
- package/templates/cloudflare-worker/_Dockerfile +56 -0
- package/templates/cloudflare-worker/_dockerignore +14 -0
- package/templates/cloudflare-worker/package.json +1 -1
- package/templates/cloudflare-worker/src/index.ts +17 -0
- package/templates/deno-basic/_Dockerfile +66 -0
- package/templates/deno-basic/_dockerignore +11 -0
- package/templates/deno-basic/deno.json +2 -2
- package/templates/node-basic/AGENTS.md +10 -0
- package/templates/node-basic/README.md +10 -0
- package/templates/node-basic/_Dockerfile +23 -10
- package/templates/node-basic/_dockerignore +1 -0
- package/templates/node-basic/package.json +1 -1
- package/templates/vercel-edge/AGENTS.md +10 -0
- package/templates/vercel-edge/README.md +10 -0
- package/templates/vercel-edge/_Dockerfile +55 -0
- package/templates/vercel-edge/_dockerignore +14 -0
- package/templates/vercel-edge/package.json +1 -1
- 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
|
|
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
|
-
#
|
|
10
|
-
# - `HEALTHCHECK` wired to `
|
|
11
|
-
#
|
|
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
|
-
|
|
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
|
|
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
|
|
36
|
+
FROM ${NODE_IMAGE} AS runner
|
|
25
37
|
WORKDIR /app
|
|
26
38
|
ENV NODE_ENV=production
|
|
27
|
-
# tini
|
|
28
|
-
|
|
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
|
|
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"]
|
|
@@ -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"]
|
|
@@ -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"
|