bosia 0.6.14 → 0.6.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bosia",
3
- "version": "0.6.14",
3
+ "version": "0.6.16",
4
4
  "type": "module",
5
5
  "description": "A fast, batteries-included fullstack framework — SSR · Svelte 5 Runes · Bun · ElysiaJS. File-based routing inspired by SvelteKit. No Node.js, no Vite, no adapters.",
6
6
  "keywords": [
@@ -1,5 +1,7 @@
1
- import { existsSync, readFileSync } from "fs";
2
- import { join } from "path";
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
2
+ import { join, dirname } from "path";
3
+
4
+ import { OUT_DIR } from "./paths.ts";
3
5
 
4
6
  // ─── Types ────────────────────────────────────────────────
5
7
 
@@ -70,13 +72,37 @@ function replaceStaticPlaceholders(template: string): string {
70
72
  return template;
71
73
  }
72
74
 
75
+ // ─── Persisted Segments (production runtime) ──────────────
76
+ // At build time we serialize the parsed segments to `${OUT_DIR}/app-html.json`
77
+ // so the production runtime can read them without needing `src/app.html` in
78
+ // the image. This lets minimal Docker images copy only `dist/`.
79
+
80
+ export function writeAppHtmlSegments(segments: AppHtmlSegments, outDir: string = OUT_DIR): string {
81
+ const target = join(outDir, "app-html.json");
82
+ mkdirSync(dirname(target), { recursive: true });
83
+ writeFileSync(target, JSON.stringify(segments));
84
+ return target;
85
+ }
86
+
87
+ function readPersistedSegments(cwd: string): AppHtmlSegments | undefined {
88
+ const persistedPath = join(cwd, OUT_DIR, "app-html.json");
89
+ if (!existsSync(persistedPath)) return undefined;
90
+ try {
91
+ return JSON.parse(readFileSync(persistedPath, "utf-8")) as AppHtmlSegments;
92
+ } catch {
93
+ return undefined;
94
+ }
95
+ }
96
+
73
97
  // ─── Cached Getter ────────────────────────────────────────
74
98
 
75
99
  export function getAppHtmlSegments(cwd: string = process.cwd()): AppHtmlSegments {
76
100
  if (cachedSegments !== undefined) {
77
101
  return cachedSegments;
78
102
  }
79
- cachedSegments = loadAppHtmlTemplate(cwd);
103
+ // Prefer persisted dist artifact (production runtime — no `src/` in image).
104
+ // Fall back to parsing `src/app.html` directly (dev mode, build step).
105
+ cachedSegments = readPersistedSegments(cwd) ?? loadAppHtmlTemplate(cwd);
80
106
  return cachedSegments;
81
107
  }
82
108
 
package/src/core/build.ts CHANGED
@@ -12,7 +12,7 @@ import { generateEnvModules } from "./envCodegen.ts";
12
12
  import { BOSIA_NODE_PATH, OUT_DIR, resolveBosiaBin } from "./paths.ts";
13
13
  import { loadPlugins } from "./config.ts";
14
14
  import type { BuildContext } from "./types/plugin.ts";
15
- import { loadAppHtmlTemplate } from "./appHtml.ts";
15
+ import { loadAppHtmlTemplate, writeAppHtmlSegments } from "./appHtml.ts";
16
16
 
17
17
  // Resolved from this file's location inside the bosia package
18
18
  const CORE_DIR = import.meta.dir;
@@ -250,6 +250,11 @@ console.log(`✅ Server entry: ${OUT_DIR}/server/${serverEntry}`);
250
250
  // 8b. Persist route manifest for runtime plugins (backend.after consumers like OpenAPI).
251
251
  writeFileSync(`${OUT_DIR}/route-manifest.json`, JSON.stringify(manifest, null, 2));
252
252
 
253
+ // 8c. Persist parsed app.html segments so the production runtime doesn't need
254
+ // `src/app.html` in the image. Renderer reads `${OUT_DIR}/app-html.json` first,
255
+ // falls back to parsing `src/app.html` for dev.
256
+ writeAppHtmlSegments(appHtml);
257
+
253
258
  // 9. Prerender static routes
254
259
  await prerenderStaticRoutes(manifest);
255
260
 
package/src/core/dev.ts CHANGED
@@ -241,7 +241,13 @@ const devServer = Bun.serve({
241
241
  // rather than the inner-app's host (localhost:APP_PORT).
242
242
  const reqUrl = new URL(req.url);
243
243
  const target = new URL(req.url);
244
- target.hostname = "localhost";
244
+ // 127.0.0.1 instead of "localhost" — under systemd `IPAddressAllow=localhost`
245
+ // the eBPF cgroup filter only permits packets to/from 127.0.0.0/8 + ::1.
246
+ // "localhost" resolves to both ::1 and 127.0.0.1; bun's fetch() picks IPv6
247
+ // first, but the inner Bun.serve() listens IPv4-only, so the v6 connect
248
+ // fails fast and (under bun 1.3) doesn't fall back to v4. Pinning to v4
249
+ // avoids the failure path entirely.
250
+ target.hostname = "127.0.0.1";
245
251
  target.port = String(APP_PORT);
246
252
 
247
253
  const forwardedHeaders = new Headers(req.headers);