@cosmicdrift/kumiko-dev-server 0.329.0 → 0.330.2
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 +17 -0
- package/bin/kumiko-build.ts +3 -2
- package/bin/kumiko-dev.ts +1 -1
- package/bin/kumiko-init-deploy.ts +1 -1
- package/bin/kumiko-schema-check.ts +4 -1
- package/dist/build-server-bundle.d.ts +31 -0
- package/dist/build-server-bundle.js +282 -0
- package/dist/build.d.ts +2 -0
- package/dist/build.js +5 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +9 -0
- package/dist/codegen/index.d.ts +4 -0
- package/dist/codegen/index.js +4 -0
- package/dist/codegen/render.d.ts +55 -0
- package/dist/codegen/render.js +273 -0
- package/dist/codegen/run-codegen.d.ts +20 -0
- package/dist/codegen/run-codegen.js +219 -0
- package/dist/codegen/scan-events.d.ts +76 -0
- package/dist/codegen/scan-events.js +447 -0
- package/dist/codegen/watch.d.ts +33 -0
- package/dist/codegen/watch.js +112 -0
- package/dist/compose-stacks.d.ts +60 -0
- package/dist/compose-stacks.js +127 -0
- package/dist/crash-tracker.d.ts +17 -0
- package/dist/crash-tracker.js +37 -0
- package/dist/create-kumiko-server.d.ts +195 -0
- package/dist/create-kumiko-server.js +1040 -0
- package/dist/env-schema.d.ts +15 -0
- package/dist/env-schema.js +60 -0
- package/dist/few-shot-corpus.d.ts +72 -0
- package/dist/few-shot-corpus.js +262 -0
- package/dist/framework-version.d.ts +1 -0
- package/dist/framework-version.js +31 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +33 -0
- package/dist/init-deploy-cli.d.ts +10 -0
- package/dist/init-deploy-cli.js +111 -0
- package/dist/kebab.d.ts +1 -0
- package/{src/kebab.ts → dist/kebab.js} +2 -3
- package/dist/run-dev-app.d.ts +174 -0
- package/dist/run-dev-app.js +403 -0
- package/dist/scaffold-app-feature.d.ts +16 -0
- package/dist/scaffold-app-feature.js +240 -0
- package/dist/scaffold-app.d.ts +45 -0
- package/dist/scaffold-app.js +852 -0
- package/dist/scaffold-demo-tasks.d.ts +8 -0
- package/{src/scaffold-demo-tasks.ts → dist/scaffold-demo-tasks.js} +69 -98
- package/dist/scaffold-deploy.d.ts +92 -0
- package/dist/scaffold-deploy.js +254 -0
- package/dist/scaffold-feature.d.ts +26 -0
- package/dist/scaffold-feature.js +163 -0
- package/dist/schema-apply.d.ts +11 -0
- package/dist/schema-apply.js +95 -0
- package/dist/schema-check-core.d.ts +2 -0
- package/{src/schema-check-core.ts → dist/schema-check-core.js} +8 -10
- package/dist/schema-tables-auth-mode.d.ts +2 -0
- package/{src/schema-tables-auth-mode.ts → dist/schema-tables-auth-mode.js} +2 -10
- package/dist/schema-tables-minimal.d.ts +2 -0
- package/{src/schema-tables-minimal.ts → dist/schema-tables-minimal.js} +2 -11
- package/dist/setup-test-stack-from-features.d.ts +11 -0
- package/dist/setup-test-stack-from-features.js +42 -0
- package/dist/welcome-banner.d.ts +15 -0
- package/dist/welcome-banner.js +27 -0
- package/package.json +71 -24
- package/src/changes.json +6 -0
- package/src/__tests__/build-prod-bundle.integration.test.ts +0 -282
- package/src/__tests__/build-server-bundle.test.ts +0 -228
- package/src/__tests__/classify-change.test.ts +0 -87
- package/src/__tests__/compose-stacks.test.ts +0 -273
- package/src/__tests__/config-resolver-default.integration.test.ts +0 -165
- package/src/__tests__/crash-tracker.test.ts +0 -89
- package/src/__tests__/create-kumiko-server-errors.test.ts +0 -54
- package/src/__tests__/create-kumiko-server-options.test.ts +0 -33
- package/src/__tests__/create-kumiko-server.integration.test.ts +0 -1007
- package/src/__tests__/discover-format.test.ts +0 -32
- package/src/__tests__/env-schema.integration.test.ts +0 -248
- package/src/__tests__/env-schema.test.ts +0 -132
- package/src/__tests__/few-shot-corpus.test.ts +0 -316
- package/src/__tests__/framework-version.test.ts +0 -45
- package/src/__tests__/init-deploy-cli.test.ts +0 -113
- package/src/__tests__/kumiko-schema-check.test.ts +0 -56
- package/src/__tests__/merge-extra-context.test.ts +0 -67
- package/src/__tests__/resolve-stylesheet.test.ts +0 -132
- package/src/__tests__/run-dev-app-boot-validation.test.ts +0 -38
- package/src/__tests__/run-dev-app.integration.test.ts +0 -290
- package/src/__tests__/runtime-classification.test.ts +0 -26
- package/src/__tests__/saas-identity-wire.integration.test.ts +0 -427
- package/src/__tests__/scaffold-app-feature.test.ts +0 -216
- package/src/__tests__/scaffold-app.test.ts +0 -630
- package/src/__tests__/scaffold-demo-tasks.test.ts +0 -47
- package/src/__tests__/scaffold-deploy.test.ts +0 -464
- package/src/__tests__/scaffold-dev-cycle.integration.test.ts +0 -109
- package/src/__tests__/scaffold-feature.test.ts +0 -143
- package/src/__tests__/schema-apply.integration.test.ts +0 -191
- package/src/__tests__/setup-test-stack-from-features.integration.test.ts +0 -30
- package/src/__tests__/setup-test-stack-job-run-logger.integration.test.ts +0 -72
- package/src/__tests__/walkthrough.integration.test.ts +0 -140
- package/src/__tests__/welcome-banner.test.ts +0 -42
- package/src/build-server-bundle.ts +0 -346
- package/src/build.ts +0 -28
- package/src/codegen/__tests__/render-codegen.test.ts +0 -100
- package/src/codegen/__tests__/run-codegen.test.ts +0 -665
- package/src/codegen/__tests__/strict-mode-diagnostics.test.ts +0 -347
- package/src/codegen/__tests__/watch.test.ts +0 -222
- package/src/codegen/index.ts +0 -19
- package/src/codegen/render.ts +0 -305
- package/src/codegen/run-codegen.ts +0 -278
- package/src/codegen/scan-events.ts +0 -565
- package/src/codegen/watch.ts +0 -140
- package/src/compose-stacks.ts +0 -193
- package/src/crash-tracker.ts +0 -56
- package/src/create-kumiko-server.ts +0 -1397
- package/src/env-schema.ts +0 -72
- package/src/few-shot-corpus.ts +0 -370
- package/src/framework-version.ts +0 -39
- package/src/index.ts +0 -105
- package/src/init-deploy-cli.ts +0 -148
- package/src/run-dev-app.ts +0 -694
- package/src/scaffold-app-feature.ts +0 -283
- package/src/scaffold-app.ts +0 -1033
- package/src/scaffold-deploy.ts +0 -393
- package/src/scaffold-feature.ts +0 -226
- package/src/schema-apply.ts +0 -123
- package/src/setup-test-stack-from-features.ts +0 -80
- package/src/welcome-banner.ts +0 -43
|
@@ -1,346 +0,0 @@
|
|
|
1
|
-
// buildServerBundle — Production-Server-Bundle für Kumiko-Apps. Pendant zu
|
|
2
|
-
// buildProdBundle (Client). Convention-Driven Discovery liest bin/main.ts
|
|
3
|
-
// (+ optional <repo>/bin/kumiko.ts) und produziert ein runtime-self-contained
|
|
4
|
-
// dist-server/ aus dem ein Bun-Alpine-Container ohne Monorepo bootet.
|
|
5
|
-
//
|
|
6
|
-
// Convention:
|
|
7
|
-
//
|
|
8
|
-
// bin/main.ts → dist-server/server.js (App-Boot, ruft runProdApp)
|
|
9
|
-
// <repo>/bin/kumiko.ts → dist-server/kumiko.js (Migrate-CLI: `schema apply`,
|
|
10
|
-
// gefunden via walk-up bis bin/kumiko.ts)
|
|
11
|
-
// dist-server/package.json → runtime-deps mit gepinnten Versionen
|
|
12
|
-
//
|
|
13
|
-
// Beide Entries werden in EINEM Bun.build-Call mit `splitting` gebaut: das
|
|
14
|
-
// Framework landet als geteilte chunk-*.js, server.js + kumiko.js sind schlanke
|
|
15
|
-
// Entries die sie importieren — statt das Framework pro Entry neu zu inlinen
|
|
16
|
-
// (vorher ~14 MB × N separate Bundles).
|
|
17
|
-
//
|
|
18
|
-
// Output:
|
|
19
|
-
//
|
|
20
|
-
// dist-server/
|
|
21
|
-
// server.js ← App-Boot-Entry
|
|
22
|
-
// kumiko.js ← Migrate-CLI-Entry (wenn bin/kumiko.ts gefunden)
|
|
23
|
-
// chunk-*.js ← geteilte Framework-Chunks
|
|
24
|
-
// package.json ← runtime-deps mit gepinnten Versionen
|
|
25
|
-
//
|
|
26
|
-
// Externals — Pakete die NICHT ins Bundle gebakt werden, sondern via
|
|
27
|
-
// `bun install` im Runtime-Container nachgeholt werden:
|
|
28
|
-
//
|
|
29
|
-
// RUNTIME_EXTERNALS — wird zur Laufzeit gebraucht (native bindings,
|
|
30
|
-
// worker-threads, dynamic-require). Landet in
|
|
31
|
-
// dist-server/package.json#dependencies.
|
|
32
|
-
//
|
|
33
|
-
// BUILD_ONLY_EXTERNALS — referenziert nur transitiv im Framework, vom
|
|
34
|
-
// App-Code aber nie. Tree-Shake wirft sie aus dem
|
|
35
|
-
// Bundle, der external-Marker schaltet nur das
|
|
36
|
-
// resolution-during-build ab. NICHT in runtime-deps.
|
|
37
|
-
|
|
38
|
-
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
39
|
-
import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
40
|
-
import { dirname, join, resolve } from "node:path";
|
|
41
|
-
import { parseJsonOrThrow, parseJsonSafe } from "@cosmicdrift/kumiko-framework/utils";
|
|
42
|
-
|
|
43
|
-
const hasBun = typeof (globalThis as { Bun?: unknown }).Bun !== "undefined";
|
|
44
|
-
|
|
45
|
-
// Pakete die das Bundle zur Laufzeit weiter referenziert (`from "<pkg>"` nach
|
|
46
|
-
// Tree-Shake). Native bindings (argon2), worker-thread-Loader (bullmq,
|
|
47
|
-
// ioredis), dynamic-require (postgres, temporal-polyfill) — alles was unter
|
|
48
|
-
// Bun-bundling bricht. (drizzle-kit/drizzle-orm sind raus: der Migrate-Pfad
|
|
49
|
-
// nutzt jetzt den framework-eigenen runMigrationsFromDir, kein drizzle-kit.)
|
|
50
|
-
// meilisearch: deliberately here, not in BUILD_ONLY_EXTERNALS below — apps
|
|
51
|
-
// that import createMeilisearchAdapter (kumiko-framework/search/meilisearch)
|
|
52
|
-
// reference the package at runtime (no native binding, plain HTTP client,
|
|
53
|
-
// but a real runtime import). Found 2026-07-19: money-horse prod crash
|
|
54
|
-
// "Cannot find package 'meilisearch'" because it used to sit in
|
|
55
|
-
// BUILD_ONLY_EXTERNALS instead.
|
|
56
|
-
const RUNTIME_EXTERNALS = [
|
|
57
|
-
"@node-rs/argon2",
|
|
58
|
-
"sharp",
|
|
59
|
-
"bullmq",
|
|
60
|
-
"ioredis",
|
|
61
|
-
"postgres",
|
|
62
|
-
"temporal-polyfill",
|
|
63
|
-
"pino",
|
|
64
|
-
"pino-pretty",
|
|
65
|
-
"meilisearch",
|
|
66
|
-
] as const;
|
|
67
|
-
|
|
68
|
-
// Pakete die nur im Build-Stack erscheinen (transitive Imports im Framework),
|
|
69
|
-
// aber vom App-Code nicht referenziert werden. Ohne external-Markierung
|
|
70
|
-
// scheitert bun build an dynamic-imports. Tree-Shake wirft sie eh aus dem
|
|
71
|
-
// Bundle — der Marker schaltet nur das resolution-during-build ab. NICHT in
|
|
72
|
-
// runtime-deps.
|
|
73
|
-
const BUILD_ONLY_EXTERNALS = [
|
|
74
|
-
"@planetscale/database",
|
|
75
|
-
"@libsql/client",
|
|
76
|
-
"better-sqlite3",
|
|
77
|
-
"@neondatabase/serverless",
|
|
78
|
-
"@vercel/postgres",
|
|
79
|
-
"mysql2",
|
|
80
|
-
// ink (kumiko-tui) hat react-devtools-core als dev-only transitive import.
|
|
81
|
-
"react-devtools-core",
|
|
82
|
-
] as const;
|
|
83
|
-
|
|
84
|
-
export type BuildServerBundleOptions = {
|
|
85
|
-
/** App-Root. Default: process.cwd(). */
|
|
86
|
-
readonly cwd?: string;
|
|
87
|
-
/** Output-Folder relativ zu cwd. Default: "dist-server". */
|
|
88
|
-
readonly outDir?: string;
|
|
89
|
-
/** Zusätzliche Pakete die zur Laufzeit installiert sein müssen
|
|
90
|
-
* (beyond RUNTIME_EXTERNALS). App-spezifisch — Default leer. */
|
|
91
|
-
readonly extraRuntimeExternals?: readonly string[];
|
|
92
|
-
/** Zusätzliche Build-only-Externals. App-spezifisch — Default leer. */
|
|
93
|
-
readonly extraBuildOnlyExternals?: readonly string[];
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
export type BuildServerBundleEntry = {
|
|
97
|
-
readonly file: string;
|
|
98
|
-
readonly sizeBytes: number;
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
export type BuildServerBundleResult = {
|
|
102
|
-
readonly outDir: string;
|
|
103
|
-
/** Benannte Entry-Files (server.js, ggf. kumiko.js). */
|
|
104
|
-
readonly entries: readonly BuildServerBundleEntry[];
|
|
105
|
-
/** Geteilte Framework-Chunks (von splitting). */
|
|
106
|
-
readonly chunks: readonly BuildServerBundleEntry[];
|
|
107
|
-
/** Gesamt-Größe aller Outputs (entries + chunks) in Bytes. */
|
|
108
|
-
readonly totalBytes: number;
|
|
109
|
-
readonly runtimeDeps: Readonly<Record<string, string>>;
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
// Bun benennt Entries nach Source-Basename (bin/main.ts → main.js). server.js
|
|
113
|
-
// ist die Runtime-Convention; der Entry wird von nichts importiert (nur die
|
|
114
|
-
// chunks werden referenziert, per relativem Pfad), darum ist der Rename sicher.
|
|
115
|
-
const ENTRY_RENAMES: Readonly<Record<string, string>> = { "main.js": "server.js" };
|
|
116
|
-
|
|
117
|
-
export async function buildServerBundle(
|
|
118
|
-
options: BuildServerBundleOptions = {},
|
|
119
|
-
): Promise<BuildServerBundleResult> {
|
|
120
|
-
if (!hasBun) {
|
|
121
|
-
throw new Error("buildServerBundle requires Bun runtime (Bun.build is missing).");
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const cwd = options.cwd ?? process.cwd();
|
|
125
|
-
const outDir = resolve(cwd, options.outDir ?? "dist-server");
|
|
126
|
-
|
|
127
|
-
const serverEntry = discoverServerEntry(cwd);
|
|
128
|
-
if (!serverEntry) {
|
|
129
|
-
throw new Error(
|
|
130
|
-
`[buildServerBundle] Kein bin/main.ts in ${cwd}.\n Convention: bin/main.ts ist der Server-Bootstrap.`,
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const repoRoot = findRepoRoot(cwd);
|
|
135
|
-
const kumikoCli = repoRoot ? join(repoRoot, "bin/kumiko.ts") : undefined;
|
|
136
|
-
if (kumikoCli && !existsSync(kumikoCli)) {
|
|
137
|
-
throw new Error(
|
|
138
|
-
`[buildServerBundle] Repo-Root erkannt (${repoRoot}), aber bin/kumiko.ts fehlt — kann Migrate-CLI nicht bündeln.`,
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const externals = [
|
|
143
|
-
...RUNTIME_EXTERNALS,
|
|
144
|
-
...BUILD_ONLY_EXTERNALS,
|
|
145
|
-
...(options.extraRuntimeExternals ?? []),
|
|
146
|
-
...(options.extraBuildOnlyExternals ?? []),
|
|
147
|
-
];
|
|
148
|
-
|
|
149
|
-
await rm(outDir, { recursive: true, force: true });
|
|
150
|
-
await mkdir(outDir, { recursive: true });
|
|
151
|
-
|
|
152
|
-
// Ein Bun.build-Call mit allen Entries + splitting → das Framework wird
|
|
153
|
-
// einmal als shared chunk abgelegt statt pro Entry inlined.
|
|
154
|
-
const entrypoints = kumikoCli ? [serverEntry, kumikoCli] : [serverEntry];
|
|
155
|
-
const result = await Bun.build({
|
|
156
|
-
entrypoints,
|
|
157
|
-
outdir: outDir,
|
|
158
|
-
target: "bun",
|
|
159
|
-
external: externals as string[],
|
|
160
|
-
splitting: true,
|
|
161
|
-
sourcemap: "none",
|
|
162
|
-
naming: { entry: "[name].js", chunk: "chunk-[hash].js" },
|
|
163
|
-
minify: false,
|
|
164
|
-
});
|
|
165
|
-
if (!result.success) {
|
|
166
|
-
const logs = result.logs.map(String).join("\n");
|
|
167
|
-
throw new Error(`[buildServerBundle] build FAILED:\n${logs}`);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Größe von Disk lesen, nicht aus out.size — letzteres ist für gesplittete
|
|
171
|
-
// Entry-Points unzuverlässig (meldet teils ~0 für den Entry-Stub).
|
|
172
|
-
const entries: BuildServerBundleEntry[] = [];
|
|
173
|
-
const chunks: BuildServerBundleEntry[] = [];
|
|
174
|
-
for (const out of result.outputs) {
|
|
175
|
-
const base = out.path.split("/").pop() ?? out.path;
|
|
176
|
-
if (out.kind === "entry-point") {
|
|
177
|
-
const desired = ENTRY_RENAMES[base] ?? base;
|
|
178
|
-
if (desired !== base) {
|
|
179
|
-
await rename(join(outDir, base), join(outDir, desired));
|
|
180
|
-
}
|
|
181
|
-
entries.push({ file: desired, sizeBytes: statSync(join(outDir, desired)).size });
|
|
182
|
-
} else if (out.kind === "chunk") {
|
|
183
|
-
chunks.push({ file: base, sizeBytes: statSync(join(outDir, base)).size });
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
entries.sort((a, b) => a.file.localeCompare(b.file));
|
|
187
|
-
const totalBytes = [...entries, ...chunks].reduce((sum, e) => sum + e.sizeBytes, 0);
|
|
188
|
-
|
|
189
|
-
const runtimeDeps = await resolveRuntimeDepsVersions(cwd, repoRoot, [
|
|
190
|
-
...RUNTIME_EXTERNALS,
|
|
191
|
-
...(options.extraRuntimeExternals ?? []),
|
|
192
|
-
]);
|
|
193
|
-
|
|
194
|
-
const runtimePkg = {
|
|
195
|
-
name: derivePkgName(cwd),
|
|
196
|
-
private: true,
|
|
197
|
-
type: "module",
|
|
198
|
-
scripts: { start: "bun run server.js" },
|
|
199
|
-
dependencies: runtimeDeps,
|
|
200
|
-
};
|
|
201
|
-
await writeFile(join(outDir, "package.json"), `${JSON.stringify(runtimePkg, null, 2)}\n`);
|
|
202
|
-
|
|
203
|
-
return { outDir, entries, chunks, totalBytes, runtimeDeps };
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export function discoverServerEntry(cwd: string): string | undefined {
|
|
207
|
-
const tsEntry = join(cwd, "bin/main.ts");
|
|
208
|
-
if (existsSync(tsEntry)) return tsEntry;
|
|
209
|
-
const jsEntry = join(cwd, "bin/main.js");
|
|
210
|
-
if (existsSync(jsEntry)) return jsEntry;
|
|
211
|
-
return undefined;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Walking up vom App-cwd bis ein Verzeichnis mit `bin/kumiko.ts` gefunden wird.
|
|
215
|
-
// Failsafe: nach 8 Levels aufgeben — nichts gefunden, kein Repo-Root, dann
|
|
216
|
-
// liefert die Funktion undefined und der Caller skippt das CLI-Bundle.
|
|
217
|
-
function findRepoRoot(start: string): string | undefined {
|
|
218
|
-
let cur = start;
|
|
219
|
-
for (let i = 0; i < 8; i++) {
|
|
220
|
-
if (existsSync(join(cur, "bin/kumiko.ts"))) return cur;
|
|
221
|
-
const parent = dirname(cur);
|
|
222
|
-
if (parent === cur) return undefined;
|
|
223
|
-
cur = parent;
|
|
224
|
-
}
|
|
225
|
-
return undefined;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/** Read `package.json#kumiko.extraRuntimeExternals` for kumiko-build (#1484).
|
|
229
|
-
* Invalid / missing shapes → empty list (CLI stays convention-driven). */
|
|
230
|
-
export function readExtraRuntimeExternals(cwd: string): readonly string[] {
|
|
231
|
-
const pkgJson = join(cwd, "package.json");
|
|
232
|
-
if (!existsSync(pkgJson)) return [];
|
|
233
|
-
let raw: string;
|
|
234
|
-
try {
|
|
235
|
-
raw = readFileSync(pkgJson, "utf-8");
|
|
236
|
-
} catch {
|
|
237
|
-
return [];
|
|
238
|
-
}
|
|
239
|
-
const parsed = parseJsonSafe<{
|
|
240
|
-
kumiko?: { extraRuntimeExternals?: unknown };
|
|
241
|
-
}>(raw, {});
|
|
242
|
-
const list = parsed.kumiko?.extraRuntimeExternals;
|
|
243
|
-
if (!Array.isArray(list)) return [];
|
|
244
|
-
return list.filter((x): x is string => typeof x === "string" && x.trim().length > 0);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Versionen für RUNTIME_EXTERNALS auflösen: erst aus den installierten
|
|
248
|
-
// node_modules/@cosmicdrift/*-Packages (relativ zu cwd — funktioniert für
|
|
249
|
-
// jede Consumer-App), dann als Zusatz aus packages/framework + bundled-
|
|
250
|
-
// features (Workspace-Checkout des Frameworks selbst). Fallback auf "*"
|
|
251
|
-
// wenn keine Quelle den Namen kennt.
|
|
252
|
-
async function resolveRuntimeDepsVersions(
|
|
253
|
-
cwd: string,
|
|
254
|
-
repoRoot: string | undefined,
|
|
255
|
-
packages: readonly string[],
|
|
256
|
-
): Promise<Record<string, string>> {
|
|
257
|
-
const out: Record<string, string> = {};
|
|
258
|
-
|
|
259
|
-
const pinSources = [
|
|
260
|
-
...(repoRoot
|
|
261
|
-
? [
|
|
262
|
-
join(repoRoot, "packages/framework/package.json"),
|
|
263
|
-
join(repoRoot, "packages/bundled-features/package.json"),
|
|
264
|
-
]
|
|
265
|
-
: []),
|
|
266
|
-
// node_modules applied last among framework sources so installed versions
|
|
267
|
-
// win over the repo-root fallback (#1217).
|
|
268
|
-
join(cwd, "node_modules/@cosmicdrift/kumiko-framework/package.json"),
|
|
269
|
-
join(cwd, "node_modules/@cosmicdrift/kumiko-bundled-features/package.json"),
|
|
270
|
-
];
|
|
271
|
-
const allDeps: Record<string, string> = {};
|
|
272
|
-
for (const path of pinSources) {
|
|
273
|
-
if (!existsSync(path)) continue;
|
|
274
|
-
const raw = await readFile(path, "utf-8");
|
|
275
|
-
const parsed = parseJsonOrThrow<{
|
|
276
|
-
dependencies?: Record<string, string>;
|
|
277
|
-
optionalDependencies?: Record<string, string>;
|
|
278
|
-
}>(raw, path);
|
|
279
|
-
Object.assign(allDeps, parsed.dependencies ?? {}, parsed.optionalDependencies ?? {});
|
|
280
|
-
}
|
|
281
|
-
// App package.json fills gaps only — pins extraRuntimeExternals without
|
|
282
|
-
// overriding framework-native pins the app may also list (#1484 / review).
|
|
283
|
-
const appPkg = join(cwd, "package.json");
|
|
284
|
-
if (existsSync(appPkg)) {
|
|
285
|
-
const raw = await readFile(appPkg, "utf-8");
|
|
286
|
-
const parsed = parseJsonOrThrow<{
|
|
287
|
-
dependencies?: Record<string, string>;
|
|
288
|
-
optionalDependencies?: Record<string, string>;
|
|
289
|
-
}>(raw, appPkg);
|
|
290
|
-
for (const [name, ver] of Object.entries({
|
|
291
|
-
...(parsed.dependencies ?? {}),
|
|
292
|
-
...(parsed.optionalDependencies ?? {}),
|
|
293
|
-
})) {
|
|
294
|
-
if (allDeps[name] === undefined) allDeps[name] = ver;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
for (const pkg of packages) {
|
|
298
|
-
out[pkg] = allDeps[pkg] ?? "*";
|
|
299
|
-
}
|
|
300
|
-
return out;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
function derivePkgName(cwd: string): string {
|
|
304
|
-
const pkgJson = join(cwd, "package.json");
|
|
305
|
-
if (!existsSync(pkgJson)) return "kumiko-app-runtime";
|
|
306
|
-
// existsSync/readFileSync race (deleted between the two calls) or a
|
|
307
|
-
// permission error must fall back like a missing file, not crash the
|
|
308
|
-
// build — read here too, not just the JSON.parse below.
|
|
309
|
-
let raw: string;
|
|
310
|
-
try {
|
|
311
|
-
raw = readFileSync(pkgJson, "utf-8");
|
|
312
|
-
} catch {
|
|
313
|
-
return "kumiko-app-runtime";
|
|
314
|
-
}
|
|
315
|
-
const parsed = parseJsonSafe<{ name?: string }>(raw, {});
|
|
316
|
-
return parsed.name ? `${parsed.name}-runtime` : "kumiko-app-runtime";
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
export function formatServerBuildResult(
|
|
320
|
-
result: BuildServerBundleResult,
|
|
321
|
-
durationMs: number,
|
|
322
|
-
): string {
|
|
323
|
-
const cyan = "\x1b[36m";
|
|
324
|
-
const dim = "\x1b[2m";
|
|
325
|
-
const green = "\x1b[32m";
|
|
326
|
-
const reset = "\x1b[0m";
|
|
327
|
-
// @wrapper-known semantic-alias
|
|
328
|
-
const mb = (bytes: number): string => (bytes / 1024 / 1024).toFixed(2);
|
|
329
|
-
const lines: string[] = [];
|
|
330
|
-
lines.push("");
|
|
331
|
-
lines.push(` ${green}✓${reset} server bundle ${dim}(${durationMs}ms)${reset}`);
|
|
332
|
-
for (const entry of result.entries) {
|
|
333
|
-
lines.push(` ${cyan}→${reset} ${entry.file} ${mb(entry.sizeBytes)} MB`);
|
|
334
|
-
}
|
|
335
|
-
if (result.chunks.length > 0) {
|
|
336
|
-
const chunkBytes = result.chunks.reduce((sum, c) => sum + c.sizeBytes, 0);
|
|
337
|
-
lines.push(
|
|
338
|
-
` ${cyan}→${reset} ${result.chunks.length} shared chunk(s) ${mb(chunkBytes)} MB`,
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
const depCount = Object.keys(result.runtimeDeps).length;
|
|
342
|
-
lines.push(
|
|
343
|
-
` ${dim}total: ${mb(result.totalBytes)} MB · runtime-deps: ${depCount} packages${reset}`,
|
|
344
|
-
);
|
|
345
|
-
return lines.join("\n");
|
|
346
|
-
}
|
package/src/build.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// Build-Toolchain Public-API. Eigener Sub-Path-Export `@cosmicdrift/kumiko-dev-server/build`
|
|
2
|
-
// damit der Main-Barrel kein Bun-Toolchain-Bundle in Production-Reads zieht
|
|
3
|
-
// (z.B. wenn drizzle-kit die App-Config unter Node lädt).
|
|
4
|
-
|
|
5
|
-
export {
|
|
6
|
-
ASSETS_DIR,
|
|
7
|
-
type BuildManifest,
|
|
8
|
-
type BuildProdBundleOptions,
|
|
9
|
-
type BuildResult,
|
|
10
|
-
buildProdBundle,
|
|
11
|
-
type ClientEntry,
|
|
12
|
-
type ClientEntryDeclaration,
|
|
13
|
-
discoverHtmlTemplate,
|
|
14
|
-
formatBuildResult,
|
|
15
|
-
injectAssetTags,
|
|
16
|
-
readClientEntriesConfig,
|
|
17
|
-
resolveClientEntries,
|
|
18
|
-
} from "@cosmicdrift/kumiko-server-runtime/build-prod-bundle";
|
|
19
|
-
|
|
20
|
-
export {
|
|
21
|
-
type BuildServerBundleEntry,
|
|
22
|
-
type BuildServerBundleOptions,
|
|
23
|
-
type BuildServerBundleResult,
|
|
24
|
-
buildServerBundle,
|
|
25
|
-
discoverServerEntry,
|
|
26
|
-
formatServerBuildResult,
|
|
27
|
-
readExtraRuntimeExternals,
|
|
28
|
-
} from "./build-server-bundle";
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { mkdirSync, mkdtempSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import {
|
|
6
|
-
renderDefineFile,
|
|
7
|
-
renderInlineSchemasFile,
|
|
8
|
-
renderTypesAugmentation,
|
|
9
|
-
renderWriteHandlerTypes,
|
|
10
|
-
} from "../render";
|
|
11
|
-
import type { ScannedEvent } from "../scan-events";
|
|
12
|
-
|
|
13
|
-
describe("renderTypesAugmentation", () => {
|
|
14
|
-
test("emits empty augmentation when no events", () => {
|
|
15
|
-
const out = renderTypesAugmentation([], "/tmp/app/.kumiko");
|
|
16
|
-
expect(out).toContain("interface KumikoEventTypeMap");
|
|
17
|
-
expect(out).toContain("no r.defineEvent calls discovered yet");
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
describe("renderInlineSchemasFile", () => {
|
|
22
|
-
test("returns undefined when no inline schemas", () => {
|
|
23
|
-
expect(renderInlineSchemasFile([], "/tmp/app")).toBeUndefined();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("uses app-root-relative paths in source comments", () => {
|
|
27
|
-
const appRoot = mkdtempSync(join(tmpdir(), "kumiko-codegen-"));
|
|
28
|
-
const featurePath = join(appRoot, "src", "feature.ts");
|
|
29
|
-
mkdirSync(join(appRoot, "src"), { recursive: true });
|
|
30
|
-
writeFileSync(featurePath, "// stub", "utf-8");
|
|
31
|
-
const events: ScannedEvent[] = [
|
|
32
|
-
{
|
|
33
|
-
qualifiedName: "inventory:event:product-archived",
|
|
34
|
-
schemaSource: {
|
|
35
|
-
kind: "inline",
|
|
36
|
-
schemaSource: "z.object({ reason: z.string() })",
|
|
37
|
-
generatedConstName: "_kg_inventory__productArchived",
|
|
38
|
-
},
|
|
39
|
-
featureFilePath: featurePath,
|
|
40
|
-
source: { file: featurePath, line: 92 },
|
|
41
|
-
},
|
|
42
|
-
];
|
|
43
|
-
const out = renderInlineSchemasFile(events, appRoot);
|
|
44
|
-
expect(out).toContain("// inventory:event:product-archived — from src/feature.ts:92");
|
|
45
|
-
expect(out).not.toContain(appRoot);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test("falls back to the bare filename when a feature file is outside the app root", () => {
|
|
49
|
-
// A bundled-feature file lives in node_modules, outside the app root —
|
|
50
|
-
// relative() would emit `../../..`. The comment falls back to basename.
|
|
51
|
-
const appRoot = join(tmpdir(), "kumiko-codegen-app");
|
|
52
|
-
const featurePath = join(tmpdir(), "node_modules", "pkg", "dist", "feature.ts");
|
|
53
|
-
const events: ScannedEvent[] = [
|
|
54
|
-
{
|
|
55
|
-
qualifiedName: "bundled:event:thing-happened",
|
|
56
|
-
schemaSource: {
|
|
57
|
-
kind: "inline",
|
|
58
|
-
schemaSource: "z.object({ id: z.string() })",
|
|
59
|
-
generatedConstName: "_kg_bundled__thingHappened",
|
|
60
|
-
},
|
|
61
|
-
featureFilePath: featurePath,
|
|
62
|
-
source: { file: featurePath, line: 7 },
|
|
63
|
-
},
|
|
64
|
-
];
|
|
65
|
-
const out = renderInlineSchemasFile(events, appRoot);
|
|
66
|
-
expect(out).toContain("// bundled:event:thing-happened — from feature.ts:7");
|
|
67
|
-
expect(out).not.toContain("..");
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
describe("renderDefineFile", () => {
|
|
72
|
-
test("emits defineWriteHandler wrapper with type reference", () => {
|
|
73
|
-
const out = renderDefineFile();
|
|
74
|
-
expect(out).toContain("defineWriteHandler");
|
|
75
|
-
expect(out).toContain("types.generated.d.ts");
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("emits createTypedDispatcher when handler QNs provided", () => {
|
|
79
|
-
const out = renderDefineFile(["tenant:write:create", "tenant:write:update"]);
|
|
80
|
-
expect(out).toContain("export type TypedDispatcher");
|
|
81
|
-
expect(out).toContain("export function createTypedDispatcher");
|
|
82
|
-
expect(out).toContain('import type { WriteHandlerQn } from "./types.generated"');
|
|
83
|
-
expect(out).toContain("export type { WriteHandlerQn };");
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe("renderWriteHandlerTypes", () => {
|
|
88
|
-
test("emits union type lines", () => {
|
|
89
|
-
const out = renderWriteHandlerTypes(["tenant:write:create"]);
|
|
90
|
-
expect(out).toContain("export type WriteHandlerQn =");
|
|
91
|
-
expect(out).toContain('| "tenant:write:create"');
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test("output does not depend on input order", () => {
|
|
95
|
-
const out = renderWriteHandlerTypes(["a:write:x", "b:write:y"]);
|
|
96
|
-
|
|
97
|
-
expect(renderWriteHandlerTypes(["b:write:y", "a:write:x"])).toBe(out);
|
|
98
|
-
expect(out.indexOf('| "a:write:x"')).toBeLessThan(out.indexOf('| "b:write:y"'));
|
|
99
|
-
});
|
|
100
|
-
});
|