@cosmicdrift/kumiko-server-runtime 0.334.0 → 0.335.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.
@@ -93,6 +93,7 @@ type ResolvedStylesheet = {
93
93
  export declare function assertRendererWebShellPresent(css: string, stylesheet: ResolvedStylesheet): void;
94
94
  export declare function discoverHtmlTemplate(cwd: string): string | undefined;
95
95
  export declare function runTailwindOnce(entry: string, cwd: string): Promise<string>;
96
+ export declare function isEntryOutputFor(outName: string, baseName: string): boolean;
96
97
  export declare function buildMissingTemplateError(manifest: BuildManifest, entry: ClientEntry): string;
97
98
  export declare function injectAssetTags(html: string, manifest: BuildManifest, entry: ClientEntry, buildInfo?: BuildInfo): string;
98
99
  export declare function computeBuildId(manifest: BuildManifest): string;
@@ -524,6 +524,15 @@ export async function runTailwindOnce(entry, cwd) {
524
524
  await rm(tmpDir, { recursive: true, force: true });
525
525
  return css;
526
526
  }
527
+ // Exact `<base>-<hash>.js` match: a plain prefix check would let
528
+ // `client-admin-legacy-<hash>.js` satisfy the `client-admin` entry. The hash is
529
+ // alphanumeric, so any further `-` in the remainder means another entry's base.
530
+ export function isEntryOutputFor(outName, baseName) {
531
+ const prefix = `${baseName}-`;
532
+ if (!outName.startsWith(prefix) || !outName.endsWith(".js"))
533
+ return false;
534
+ return /^[A-Za-z0-9]+$/.test(outName.slice(prefix.length, -".js".length));
535
+ }
527
536
  /** Multi-entry-build: ein Bun.build-Call mit allen entrypoints — shared
528
537
  * chunks werden dedupliziert, hashes deterministisch. Returns map
529
538
  * manifestKey → hashed-filename (basename, ohne /assets/-Prefix). */
@@ -565,10 +574,7 @@ async function buildClientBundles(entries, outDir) {
565
574
  const result = {};
566
575
  for (const entry of entries) {
567
576
  const baseName = (entry.sourceFile.split("/").pop() ?? "").replace(SOURCE_EXTENSION_PATTERN, "");
568
- const match = entryOutputs.find((o) => {
569
- const outName = o.path.split("/").pop() ?? "";
570
- return outName.startsWith(`${baseName}-`);
571
- });
577
+ const match = entryOutputs.find((o) => isEntryOutputFor(o.path.split("/").pop() ?? "", baseName));
572
578
  if (!match) {
573
579
  throw new Error(`[kumiko build] no entry-point output for "${entry.sourceFile}" (looked for "${baseName}-*.js")`);
574
580
  }
@@ -123,7 +123,7 @@ trustedProxyHops = 0) {
123
123
  etag: html.etag,
124
124
  cache: staticCachePolicy(pathname),
125
125
  headers: { "content-type": html.mime, ...extraHeaders },
126
- lastModified: new Date(html.mtimeMs),
126
+ lastModified: html.mtimeMs === undefined ? undefined : new Date(html.mtimeMs),
127
127
  });
128
128
  }
129
129
  // Injects resolved head metadata into an already-read HTML payload, right
@@ -158,7 +158,6 @@ trustedProxyHops = 0) {
158
158
  bytes: encoded.buffer,
159
159
  mime: html.mime,
160
160
  etag: computeStrongEtag(encoded),
161
- mtimeMs: html.mtimeMs,
162
161
  };
163
162
  }
164
163
  // hostDispatch konsultieren wenn gesetzt UND der Request auf den
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-server-runtime",
3
- "version": "0.334.0",
3
+ "version": "0.335.0",
4
4
  "description": "Production server-boot runtime for Kumiko apps: connections, schema-drift-gate, seeds, lifecycle, graceful shutdown. Symmetric to kumiko-dev-server's runDevApp, without dev/scaffold/codegen tooling.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -80,10 +80,10 @@
80
80
  }
81
81
  },
82
82
  "dependencies": {
83
- "@cosmicdrift/kumiko-bundled-features": "0.334.0",
84
- "@cosmicdrift/kumiko-framework": "0.334.0",
85
- "@cosmicdrift/kumiko-headless": "0.334.0",
86
- "@cosmicdrift/kumiko-renderer-web": "0.334.0",
83
+ "@cosmicdrift/kumiko-bundled-features": "0.335.0",
84
+ "@cosmicdrift/kumiko-framework": "0.335.0",
85
+ "@cosmicdrift/kumiko-headless": "0.335.0",
86
+ "@cosmicdrift/kumiko-renderer-web": "0.335.0",
87
87
  "bun-types": "^1.3.13",
88
88
  "ioredis": "^5.10.1",
89
89
  "temporal-polyfill": "^0.3.2"
package/src/changes.json CHANGED
@@ -1,4 +1,10 @@
1
1
  [
2
+ {
3
+ "version": "0.335.0",
4
+ "type": "fix",
5
+ "title": "Client bundle mapping matches exact entry names; page-head HTML is validated by ETag only",
6
+ "detail": "Multi-entry client builds map each Bun output to its entry by exact `<base>-<hash>.js` name, so `client-admin` and `client-admin-legacy` can no longer receive each other's bundle. Static HTML with injected page head no longer sends `Last-Modified`, so a crawler sending only `If-Modified-Since` gets the fresh metadata instead of a stale 304."
7
+ },
2
8
  {
3
9
  "version": "0.330.0",
4
10
  "type": "fix",