@cosmicdrift/kumiko-dev-server 0.337.1 → 0.338.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.
|
@@ -48,7 +48,12 @@ export type DevHostDispatchResult = {
|
|
|
48
48
|
readonly to: string;
|
|
49
49
|
readonly status?: 301 | 302;
|
|
50
50
|
} | {
|
|
51
|
+
/** Plain 404 by default. `file` serves a static page with status 404
|
|
52
|
+
* (like `static-html`), `entryName` serves that bundle's shell with 404;
|
|
53
|
+
* `file` wins when both are set. */
|
|
51
54
|
readonly kind: "not-found";
|
|
55
|
+
readonly entryName?: string;
|
|
56
|
+
readonly file?: string;
|
|
52
57
|
};
|
|
53
58
|
/** Picks an entry by inspecting the incoming request. Wird von
|
|
54
59
|
* Multi-Entry-Apps gesetzt; im Single-Entry-Mode irrelevant. */
|
|
@@ -723,7 +723,7 @@ export async function createKumikoServer(options) {
|
|
|
723
723
|
// resolvePageHead goes through the same headless resolveAndInjectPageHead
|
|
724
724
|
// that runProdApp uses, so dev and e2e exercise the one timeout and
|
|
725
725
|
// fallback path instead of a second copy of it (#3026).
|
|
726
|
-
const htmlResponse = async (entryName, req, socketAddress) => {
|
|
726
|
+
const htmlResponse = async (entryName, req, socketAddress, status = 200) => {
|
|
727
727
|
const template = htmlTemplates.get(entryName) ?? defaultTemplate;
|
|
728
728
|
const headers = new Headers();
|
|
729
729
|
headers.set("Content-Type", "text/html; charset=utf-8");
|
|
@@ -745,7 +745,23 @@ export async function createKumikoServer(options) {
|
|
|
745
745
|
systemQuery: buildDevSystemQuery(req, socketAddress),
|
|
746
746
|
});
|
|
747
747
|
}
|
|
748
|
-
return new Response(html, { headers });
|
|
748
|
+
return new Response(html, { status, headers });
|
|
749
|
+
};
|
|
750
|
+
// Raw file serve, no bundle injection — mirrors prod's `{ kind: "html", file }`.
|
|
751
|
+
const staticHtmlResponse = async (file, status) => {
|
|
752
|
+
let content;
|
|
753
|
+
try {
|
|
754
|
+
content = await readFile(file, "utf-8");
|
|
755
|
+
}
|
|
756
|
+
catch (error) {
|
|
757
|
+
if (error.code !== "ENOENT")
|
|
758
|
+
throw error;
|
|
759
|
+
return new Response(`hostDispatch: file not found: ${file}`, { status: 500 });
|
|
760
|
+
}
|
|
761
|
+
return new Response(content, {
|
|
762
|
+
status,
|
|
763
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
764
|
+
});
|
|
749
765
|
};
|
|
750
766
|
// --- Fetch handler (runtime-neutral) ---
|
|
751
767
|
// Bundle-Pfad-Lookup: für jede Entry serven wir
|
|
@@ -898,15 +914,15 @@ export async function createKumikoServer(options) {
|
|
|
898
914
|
});
|
|
899
915
|
}
|
|
900
916
|
if (dispatch.kind === "not-found") {
|
|
917
|
+
if (dispatch.file !== undefined)
|
|
918
|
+
return staticHtmlResponse(dispatch.file, 404);
|
|
919
|
+
if (dispatch.entryName !== undefined) {
|
|
920
|
+
return htmlResponse(dispatch.entryName, req, socketAddress, 404);
|
|
921
|
+
}
|
|
901
922
|
return new Response("Not Found", { status: 404 });
|
|
902
923
|
}
|
|
903
924
|
if (dispatch.kind === "static-html") {
|
|
904
|
-
|
|
905
|
-
// `{ kind: "html", file: ... }` static-html branch.
|
|
906
|
-
const file = await readFile(dispatch.file, "utf-8");
|
|
907
|
-
return new Response(file, {
|
|
908
|
-
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
909
|
-
});
|
|
925
|
+
return staticHtmlResponse(dispatch.file, 200);
|
|
910
926
|
}
|
|
911
927
|
return htmlResponse(dispatch.entryName, req, socketAddress);
|
|
912
928
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-dev-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.338.0",
|
|
4
4
|
"description": "Dev-tooling for Kumiko apps: local dev-server bootstrap (runDevApp), scaffolding, codegen. Its compose-stacks/env-schema subpaths are consumed at prod boot too — see @cosmicdrift/kumiko-server-runtime for the prod runner itself.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -64,11 +64,11 @@
|
|
|
64
64
|
"kumiko-upgrade": "./bin/kumiko-upgrade.ts"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@cosmicdrift/kumiko-bundled-features": "0.
|
|
68
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
69
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
70
|
-
"@cosmicdrift/kumiko-renderer-web": "0.
|
|
71
|
-
"@cosmicdrift/kumiko-server-runtime": "0.
|
|
67
|
+
"@cosmicdrift/kumiko-bundled-features": "0.338.0",
|
|
68
|
+
"@cosmicdrift/kumiko-framework": "0.338.0",
|
|
69
|
+
"@cosmicdrift/kumiko-headless": "0.338.0",
|
|
70
|
+
"@cosmicdrift/kumiko-renderer-web": "0.338.0",
|
|
71
|
+
"@cosmicdrift/kumiko-server-runtime": "0.338.0",
|
|
72
72
|
"bun-types": "^1.3.13",
|
|
73
73
|
"ts-morph": "^28.0.0",
|
|
74
74
|
"zod": "^4.4.3"
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.338.0",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "Scaffolded migrate step percent-encodes DB_PASSWORD",
|
|
6
|
+
"detail": "dev-server: the scaffolded `deploy/migrate-step.sh` percent-encodes `DB_PASSWORD` in `DATABASE_URL`, so passwords with `@`, `:`, `/`, `#`, `%` or non-ASCII characters no longer break the URL. Re-run `kumiko init-deploy` to pick it up; apps with a hand-written `urlencode` should take the new version, which also encodes bytes >= 0x80 correctly."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.338.0",
|
|
10
|
+
"type": "improvement",
|
|
11
|
+
"title": "dev hostDispatch not-found can serve a custom 404 page",
|
|
12
|
+
"detail": "`DevHostDispatchResult` `{ kind: \"not-found\" }` accepts `file` (served like `static-html`) or `entryName` (that entry's shell), both with status 404. A missing file answers 500 with `hostDispatch: file not found`. Without fields the plain \"Not Found\" 404 stays.",
|
|
13
|
+
"migration": "No code change needed."
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"version": "0.338.0",
|
|
17
|
+
"type": "improvement",
|
|
18
|
+
"title": "New package @cosmicdrift/kumiko-samples with the corpus sources",
|
|
19
|
+
"detail": "New package with the sample recipes, sample apps and bundled-features sources\n`@cosmicdrift/kumiko-samples` ships the sample recipes, sample apps and bundled-features sources in the repository layout. Tools such as the few-shot corpus build can run against a pinned version of it and get the same entry ids and source paths as in the monorepo."
|
|
20
|
+
},
|
|
2
21
|
{
|
|
3
22
|
"version": "0.337.1",
|
|
4
23
|
"type": "improvement",
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
#
|
|
3
3
|
# Production-Image for {{appName}}.
|
|
4
4
|
#
|
|
5
|
-
# Server-Bundle variant — the runtime image doesn't
|
|
6
|
-
#
|
|
5
|
+
# Server-Bundle variant — the runtime image doesn't carry the source tree
|
|
6
|
+
# or its node_modules any more, only:
|
|
7
7
|
#
|
|
8
8
|
# dist/ ← Client build (kumiko-build)
|
|
9
9
|
# dist-server/ ← Server bundle (bun build) + minimal package.json
|
|
10
10
|
# kumiko/migrations/ ← Checked-in SQL migrations applied by `kumiko schema apply`
|
|
11
11
|
#
|
|
12
|
-
# Build context: repository root (
|
|
12
|
+
# Build context: repository root (the full source tree is only used in the build stage).
|
|
13
13
|
|
|
14
14
|
ARG BUN_VERSION=1.4.0
|
|
15
15
|
{{#hasPrivateGhPackages}}
|
|
@@ -49,6 +49,21 @@ set -a
|
|
|
49
49
|
. ./.env
|
|
50
50
|
set +a
|
|
51
51
|
|
|
52
|
+
# Percent-encode so '@', ':', '/', '#', '%' in the password cannot change how
|
|
53
|
+
# the URL is parsed. LC_ALL=C makes the loop walk bytes, not characters;
|
|
54
|
+
# bash sign-extends bytes >= 0x80 in "'$c", hence the & 255.
|
|
55
|
+
urlencode() {
|
|
56
|
+
local LC_ALL=C s="$1" out="" c i byte
|
|
57
|
+
for ((i = 0; i < ${#s}; i++)); do
|
|
58
|
+
c="${s:i:1}"
|
|
59
|
+
case "$c" in
|
|
60
|
+
[A-Za-z0-9._~-]) out+="$c" ;;
|
|
61
|
+
*) printf -v byte '%d' "'$c"; printf -v c '%%%02X' $((byte & 255)); out+="$c" ;;
|
|
62
|
+
esac
|
|
63
|
+
done
|
|
64
|
+
printf '%s' "$out"
|
|
65
|
+
}
|
|
66
|
+
|
|
52
67
|
# DATABASE_URL assumes: db user = appName, db name = appName, host "db"
|
|
53
68
|
# (compose-service-name), port 5432. Adjust to your stack if different.
|
|
54
69
|
{{#customDbUser}}
|
|
@@ -60,7 +75,7 @@ set +a
|
|
|
60
75
|
# NAME (`-e DATABASE_URL`, no value) so the expanded password never appears
|
|
61
76
|
# in `docker run`'s argv — otherwise it would be visible in `ps auxe` for
|
|
62
77
|
# the duration of the migrate run.
|
|
63
|
-
export DATABASE_URL="postgresql://{{dbUser}}:$
|
|
78
|
+
export DATABASE_URL="postgresql://{{dbUser}}:$(urlencode "$DB_PASSWORD")@db:5432/{{appName}}"
|
|
64
79
|
docker run --rm \
|
|
65
80
|
--network "$STACK_NETWORK" \
|
|
66
81
|
-e DATABASE_URL \
|