@cosmicdrift/kumiko-dev-server 0.340.0 → 0.342.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/dist/build-server-bundle.d.ts +1 -1
- package/dist/build-server-bundle.js +9 -8
- package/dist/codegen/watch.d.ts +5 -0
- package/dist/codegen/watch.js +16 -16
- package/dist/run-dev-app.js +1 -0
- package/dist/scaffold-app.js +16 -1
- package/dist/scaffold-deploy.d.ts +0 -5
- package/dist/scaffold-deploy.js +9 -4
- package/package.json +6 -6
- package/src/changes.json +17 -0
- package/templates/deploy/migrate-step.sh.template +1 -20
|
@@ -15,7 +15,7 @@ export type BuildServerBundleEntry = {
|
|
|
15
15
|
};
|
|
16
16
|
export type BuildServerBundleResult = {
|
|
17
17
|
readonly outDir: string;
|
|
18
|
-
/** Named entry files (server.js, plus kumiko.js and
|
|
18
|
+
/** Named entry files (server.js, plus kumiko.js, worker.js and bootstrap.js when present). */
|
|
19
19
|
readonly entries: readonly BuildServerBundleEntry[];
|
|
20
20
|
/** Geteilte Framework-Chunks (von splitting). */
|
|
21
21
|
readonly chunks: readonly BuildServerBundleEntry[];
|
|
@@ -10,11 +10,13 @@
|
|
|
10
10
|
// gefunden via walk-up bis bin/kumiko.ts)
|
|
11
11
|
// bin/worker.ts → dist-server/worker.js (optional, next to bin/main.ts:
|
|
12
12
|
// background worker as its own process from the same image)
|
|
13
|
+
// bin/bootstrap.ts → dist-server/bootstrap.js (optional, next to bin/main.ts:
|
|
14
|
+
// one-shot runBootstrap provisioning, run as a k8s Job)
|
|
13
15
|
// dist-server/package.json → runtime-deps mit gepinnten Versionen
|
|
14
16
|
//
|
|
15
17
|
// All entries are built in ONE Bun.build call with `splitting`: the framework
|
|
16
|
-
// lands once as shared chunk-*.js and server.js, kumiko.js
|
|
17
|
-
// thin entries importing it. Separate bundles would inline ~14 MB per entry.
|
|
18
|
+
// lands once as shared chunk-*.js and server.js, kumiko.js, worker.js and
|
|
19
|
+
// bootstrap.js are thin entries importing it. Separate bundles would inline ~14 MB per entry.
|
|
18
20
|
//
|
|
19
21
|
// Output:
|
|
20
22
|
//
|
|
@@ -22,6 +24,7 @@
|
|
|
22
24
|
// server.js ← App-Boot-Entry
|
|
23
25
|
// kumiko.js ← Migrate-CLI-Entry (wenn bin/kumiko.ts gefunden)
|
|
24
26
|
// worker.js ← worker entry (if bin/worker.ts sits next to main.ts)
|
|
27
|
+
// bootstrap.js ← provisioning entry (if bin/bootstrap.ts sits next to main.ts)
|
|
25
28
|
// chunk-*.js ← geteilte Framework-Chunks
|
|
26
29
|
// package.json ← runtime-deps mit gepinnten Versionen
|
|
27
30
|
//
|
|
@@ -107,12 +110,10 @@ export async function buildServerBundle(options = {}) {
|
|
|
107
110
|
await mkdir(outDir, { recursive: true });
|
|
108
111
|
// Ein Bun.build-Call mit allen Entries + splitting → das Framework wird
|
|
109
112
|
// einmal als shared chunk abgelegt statt pro Entry inlined.
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
...(existsSync(workerEntry) ? [workerEntry] : []),
|
|
115
|
-
];
|
|
113
|
+
const optionalSiblingEntries = ["worker.ts", "bootstrap.ts"]
|
|
114
|
+
.map((file) => join(dirname(serverEntry), file))
|
|
115
|
+
.filter((path) => existsSync(path));
|
|
116
|
+
const entrypoints = [serverEntry, ...(kumikoCli ? [kumikoCli] : []), ...optionalSiblingEntries];
|
|
116
117
|
const result = await Bun.build({
|
|
117
118
|
entrypoints,
|
|
118
119
|
outdir: outDir,
|
package/dist/codegen/watch.d.ts
CHANGED
|
@@ -25,6 +25,11 @@ export type WatchHandle = {
|
|
|
25
25
|
/** Beendet den Watcher. Idempotent — mehrfacher Aufruf ist no-op. */
|
|
26
26
|
readonly close: () => void;
|
|
27
27
|
};
|
|
28
|
+
/** Whether a change to `filename` (relative to `src/`, posix or windows
|
|
29
|
+
* separators) can affect codegen output: production .ts/.tsx sources
|
|
30
|
+
* outside the skipped dirs, excluding .d.ts (mostly written by codegen
|
|
31
|
+
* itself) and test files. */
|
|
32
|
+
export declare function isCodegenRelevantChange(filename: string): boolean;
|
|
28
33
|
/**
|
|
29
34
|
* Startet den Watcher. Beim Boot fährt einmalig `runCodegen` (sodass
|
|
30
35
|
* die generated Files sofort frisch sind), dann hängt sich an `fs.watch`
|
package/dist/codegen/watch.js
CHANGED
|
@@ -19,6 +19,20 @@ import { runCodegen } from "./run-codegen.js";
|
|
|
19
19
|
import { formatScanWarning } from "./scan-events.js";
|
|
20
20
|
const SKIP_SUBSTRINGS = ["/node_modules/", "/.kumiko/", "/dist/", "/dist-server/", "/__tests__/"];
|
|
21
21
|
const DEFAULT_DEBOUNCE_MS = 50;
|
|
22
|
+
/** Whether a change to `filename` (relative to `src/`, posix or windows
|
|
23
|
+
* separators) can affect codegen output: production .ts/.tsx sources
|
|
24
|
+
* outside the skipped dirs, excluding .d.ts (mostly written by codegen
|
|
25
|
+
* itself) and test files. */
|
|
26
|
+
export function isCodegenRelevantChange(filename) {
|
|
27
|
+
const normalised = `/${filename.replace(/\\/g, "/")}`;
|
|
28
|
+
if (SKIP_SUBSTRINGS.some((seg) => normalised.includes(seg)))
|
|
29
|
+
return false;
|
|
30
|
+
if (!normalised.endsWith(".ts") && !normalised.endsWith(".tsx"))
|
|
31
|
+
return false;
|
|
32
|
+
if (normalised.endsWith(".d.ts"))
|
|
33
|
+
return false;
|
|
34
|
+
return !normalised.endsWith(".test.ts") && !normalised.endsWith(".test.tsx");
|
|
35
|
+
}
|
|
22
36
|
/**
|
|
23
37
|
* Startet den Watcher. Beim Boot fährt einmalig `runCodegen` (sodass
|
|
24
38
|
* die generated Files sofort frisch sind), dann hängt sich an `fs.watch`
|
|
@@ -65,22 +79,8 @@ export function watchAndRegenerate(opts) {
|
|
|
65
79
|
// skip: watcher closed or no filename reported, nothing to act on
|
|
66
80
|
if (closed || !filename)
|
|
67
81
|
return;
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
const normalised = `/${filename.toString().replace(/\\/g, "/")}`;
|
|
71
|
-
// skip: path matches an excluded segment (node_modules/dist/etc.)
|
|
72
|
-
if (SKIP_SUBSTRINGS.some((seg) => normalised.includes(seg)))
|
|
73
|
-
return;
|
|
74
|
-
// skip: Nur .ts/.tsx interessieren — alles andere (CSS, MD, JSON) hat
|
|
75
|
-
// keinen Einfluss auf r.defineEvent-Calls.
|
|
76
|
-
if (!normalised.endsWith(".ts") && !normalised.endsWith(".tsx"))
|
|
77
|
-
return;
|
|
78
|
-
// skip: .d.ts ausgenommen — die kommen meistens vom codegen selbst.
|
|
79
|
-
if (normalised.endsWith(".d.ts"))
|
|
80
|
-
return;
|
|
81
|
-
// skip: .test.ts/.test.tsx ausgenommen — Tests definieren keine
|
|
82
|
-
// Production-Features.
|
|
83
|
-
if (normalised.endsWith(".test.ts") || normalised.endsWith(".test.tsx"))
|
|
82
|
+
// skip: change cannot affect r.defineEvent calls
|
|
83
|
+
if (!isCodegenRelevantChange(filename.toString()))
|
|
84
84
|
return;
|
|
85
85
|
if (timer)
|
|
86
86
|
clearTimeout(timer);
|
package/dist/run-dev-app.js
CHANGED
|
@@ -312,6 +312,7 @@ export async function runDevApp(options) {
|
|
|
312
312
|
tierResolverHolder.resolver = await plugin.build({
|
|
313
313
|
db: stack.db,
|
|
314
314
|
registry: stack.registry,
|
|
315
|
+
cacheSync: stack.cacheSync,
|
|
315
316
|
});
|
|
316
317
|
}
|
|
317
318
|
if (effectiveAuth && stack.registry.getExtensionUsages(EXT_SESSION_STORE).length > 0) {
|
package/dist/scaffold-app.js
CHANGED
|
@@ -37,6 +37,8 @@ export async function scaffoldApp(options) {
|
|
|
37
37
|
files.push("package.json");
|
|
38
38
|
write(join(destination, "tsconfig.json"), renderTsconfig());
|
|
39
39
|
files.push("tsconfig.json");
|
|
40
|
+
write(join(destination, "kumiko.json"), renderKumikoManifest());
|
|
41
|
+
files.push("kumiko.json");
|
|
40
42
|
write(join(destination, "biome.json"), renderBiomeJson());
|
|
41
43
|
files.push("biome.json");
|
|
42
44
|
if (testSetup === undefined) {
|
|
@@ -752,6 +754,16 @@ function renderKumikoSchema() {
|
|
|
752
754
|
"",
|
|
753
755
|
].join("\n");
|
|
754
756
|
}
|
|
757
|
+
// `kumiko check` fails a kind "app" without uiRoots, so a fresh app must declare them.
|
|
758
|
+
function renderKumikoManifest() {
|
|
759
|
+
return `${JSON.stringify({
|
|
760
|
+
kind: "app",
|
|
761
|
+
sourceRoots: ["src", "bin"],
|
|
762
|
+
testGlobs: ["src/**/*.{test,integration}.{ts,tsx}"],
|
|
763
|
+
uiRoots: ["src/features/*/web"],
|
|
764
|
+
excludes: ["**/node_modules/**", "**/dist/**"],
|
|
765
|
+
}, null, 2)}\n`;
|
|
766
|
+
}
|
|
755
767
|
function renderBinKumiko() {
|
|
756
768
|
return [
|
|
757
769
|
"#!/usr/bin/env bun",
|
|
@@ -761,8 +773,10 @@ function renderBinKumiko() {
|
|
|
761
773
|
"// consumer status|restart <name>` to recover a dead event consumer without",
|
|
762
774
|
"// ad-hoc SQL. kumiko-build bundles this file to dist-server/kumiko.js.",
|
|
763
775
|
"",
|
|
776
|
+
'import { frameworkCoreEnvSchema } from "@cosmicdrift/kumiko-dev-server/env-schema";',
|
|
764
777
|
'import { composeFeatures } from "@cosmicdrift/kumiko-server-runtime/compose-features";',
|
|
765
778
|
'import { runConsumerCli } from "@cosmicdrift/kumiko-framework/consumer-cli";',
|
|
779
|
+
'import { composeEnvSchema, kmsSlotsOf } from "@cosmicdrift/kumiko-framework/env";',
|
|
766
780
|
'import { runSchemaCli } from "@cosmicdrift/kumiko-framework/schema-cli";',
|
|
767
781
|
'import { APP_FEATURES, HAS_AUTH } from "../src/run-config";',
|
|
768
782
|
"",
|
|
@@ -772,7 +786,8 @@ function renderBinKumiko() {
|
|
|
772
786
|
"",
|
|
773
787
|
'if (cmd === "schema") {',
|
|
774
788
|
" const features = composeFeatures([...APP_FEATURES], { includeBundled: HAS_AUTH });",
|
|
775
|
-
"
|
|
789
|
+
" const kmsSlots = kmsSlotsOf(composeEnvSchema({ core: frameworkCoreEnvSchema, features }).schema);",
|
|
790
|
+
" process.exit(await runSchemaCli(rest, process.env.INIT_CWD ?? process.cwd(), out, { features, kmsSlots }));",
|
|
776
791
|
"}",
|
|
777
792
|
"",
|
|
778
793
|
'if (cmd === "consumer") {',
|
|
@@ -41,11 +41,6 @@ export type ScaffoldDeployDetected = {
|
|
|
41
41
|
* `package.json#kumiko.deploy.dbUser`, default = appName. The db name
|
|
42
42
|
* always stays appName regardless of this value. */
|
|
43
43
|
readonly dbUser: string;
|
|
44
|
-
/** How migrate-step.sh locates the compose `_stack` network — from
|
|
45
|
-
* `package.json#kumiko.deploy.stackNetwork`. "discover" (default):
|
|
46
|
-
* today's `docker network ls` heuristic. "directory": the exact name
|
|
47
|
-
* `$(basename "$PWD")_stack`, checked via `docker network inspect`. */
|
|
48
|
-
readonly stackNetwork: "discover" | "directory";
|
|
49
44
|
};
|
|
50
45
|
export type ScaffoldedFile = {
|
|
51
46
|
readonly path: string;
|
package/dist/scaffold-deploy.js
CHANGED
|
@@ -60,8 +60,6 @@ export function renderDeployFiles(options) {
|
|
|
60
60
|
hasPrivateGhPackages: detected.hasPrivateGhPackages,
|
|
61
61
|
installFromFullTree: detected.installFromFullTree,
|
|
62
62
|
installFromManifests: !detected.installFromFullTree,
|
|
63
|
-
stackNetworkDiscover: detected.stackNetwork === "discover",
|
|
64
|
-
stackNetworkDirectory: detected.stackNetwork === "directory",
|
|
65
63
|
customDbUser: detected.dbUser !== options.appName,
|
|
66
64
|
};
|
|
67
65
|
const dir = templatesDir();
|
|
@@ -140,7 +138,14 @@ const DB_USER_RE = /^[a-zA-Z0-9_][a-zA-Z0-9_-]{0,62}$/;
|
|
|
140
138
|
const kumikoDeployConfigSchema = z
|
|
141
139
|
.object({
|
|
142
140
|
dbUser: z.string().regex(DB_USER_RE).optional(),
|
|
143
|
-
|
|
141
|
+
// "directory" is the only behaviour left; the key stays valid so existing
|
|
142
|
+
// package.json files keep scaffolding.
|
|
143
|
+
stackNetwork: z
|
|
144
|
+
.string()
|
|
145
|
+
.refine((value) => value === "directory", {
|
|
146
|
+
message: 'the stackNetwork option was removed: migrate-step.sh always uses the exact "<dirname>_stack" network (COMPOSE_PROJECT_NAME or directory name). Delete the option or set it to "directory"',
|
|
147
|
+
})
|
|
148
|
+
.optional(),
|
|
144
149
|
})
|
|
145
150
|
.strict();
|
|
146
151
|
/** `package.json#kumiko.deploy` must be well-formed — silently falling back
|
|
@@ -175,7 +180,7 @@ function resolveDeployConfig(deployConfigRaw, appName) {
|
|
|
175
180
|
}
|
|
176
181
|
throw new Error(`scaffoldDeploy: invalid package.json#kumiko.deploy.dbUser — effective value "${dbUser}" (defaulted from appName) does not match ${DB_USER_RE}`);
|
|
177
182
|
}
|
|
178
|
-
return { dbUser
|
|
183
|
+
return { dbUser };
|
|
179
184
|
}
|
|
180
185
|
function detectOptionalSurfaces(sourceDir, appName) {
|
|
181
186
|
const hasSeeds = existsSync(join(sourceDir, "seeds"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-dev-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.342.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.342.0",
|
|
68
|
+
"@cosmicdrift/kumiko-framework": "0.342.0",
|
|
69
|
+
"@cosmicdrift/kumiko-headless": "0.342.0",
|
|
70
|
+
"@cosmicdrift/kumiko-renderer-web": "0.342.0",
|
|
71
|
+
"@cosmicdrift/kumiko-server-runtime": "0.342.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,21 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.341.0",
|
|
4
|
+
"type": "improvement",
|
|
5
|
+
"title": "buildServerBundle bundles bin/bootstrap.ts to dist-server/bootstrap.js when present"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"version": "0.341.0",
|
|
9
|
+
"type": "fix",
|
|
10
|
+
"title": "Codegen watcher change filter is a tested pure predicate"
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"version": "0.341.0",
|
|
14
|
+
"type": "breaking",
|
|
15
|
+
"title": "Deploy migrate-step.sh always uses the exact stack network",
|
|
16
|
+
"detail": "The discover variant (docker network ls | head -1) could pick another compose project's network on a shared host. The script now uses COMPOSE_PROJECT_NAME or the directory name plus _stack.",
|
|
17
|
+
"migration": "Remove package.json kumiko.deploy.stackNetwork (or set it to \"directory\"), then re-run scaffoldDeploy. If the deploy directory name differs from the compose project, set COMPOSE_PROJECT_NAME for migrate-step.sh."
|
|
18
|
+
},
|
|
2
19
|
{
|
|
3
20
|
"version": "0.340.0",
|
|
4
21
|
"type": "improvement",
|
|
@@ -10,29 +10,11 @@
|
|
|
10
10
|
# changes BEFORE the app container starts — runProdApp's boot gate would
|
|
11
11
|
# otherwise abort with SchemaDriftError.
|
|
12
12
|
#
|
|
13
|
-
{{#stackNetworkDiscover}}
|
|
14
|
-
# Network discovery: the _stack network is named `<dirname>_stack`
|
|
15
|
-
# (compose convention). We discover it via `docker network ls` instead
|
|
16
|
-
# of hard-coding.
|
|
17
|
-
{{/stackNetworkDiscover}}
|
|
18
|
-
{{#stackNetworkDirectory}}
|
|
19
13
|
# Network: the exact `<dirname>_stack` name of the compose project this
|
|
20
|
-
# script runs in
|
|
21
|
-
{{/stackNetworkDirectory}}
|
|
14
|
+
# script runs in — never another project's network on a shared host.
|
|
22
15
|
|
|
23
16
|
set -euo pipefail
|
|
24
17
|
|
|
25
|
-
{{#stackNetworkDiscover}}
|
|
26
|
-
# `|| true` keeps `set -e`/`pipefail` from aborting the script when `grep`
|
|
27
|
-
# finds no match (exit 1) — the empty-check below owns that case and prints
|
|
28
|
-
# the actionable hint instead of a bare pipefail abort.
|
|
29
|
-
STACK_NETWORK=$(docker network ls --format "{{.Name}}" | grep -E "_stack$" | head -1 || true)
|
|
30
|
-
if [ -z "$STACK_NETWORK" ]; then
|
|
31
|
-
echo "No _stack network found — compose project not running?" >&2
|
|
32
|
-
exit 1
|
|
33
|
-
fi
|
|
34
|
-
{{/stackNetworkDiscover}}
|
|
35
|
-
{{#stackNetworkDirectory}}
|
|
36
18
|
# Compose lowercases the project name and drops characters outside [a-z0-9_-].
|
|
37
19
|
COMPOSE_PROJECT="${COMPOSE_PROJECT_NAME:-$(basename "$PWD" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9_-')}"
|
|
38
20
|
STACK_NETWORK="${COMPOSE_PROJECT}_stack"
|
|
@@ -40,7 +22,6 @@ if ! docker network inspect "$STACK_NETWORK" >/dev/null 2>&1; then
|
|
|
40
22
|
echo "Stack network '$STACK_NETWORK' not found (derived from COMPOSE_PROJECT_NAME or the directory name '$(basename "$PWD")') — compose project not running?" >&2
|
|
41
23
|
exit 1
|
|
42
24
|
fi
|
|
43
|
-
{{/stackNetworkDirectory}}
|
|
44
25
|
|
|
45
26
|
# Import .env as bash env. `set -a` marks subsequent variable assignments
|
|
46
27
|
# as auto-export. Bash's built-in parser respects quotes/escapes like
|