bosia 0.5.3 → 0.5.4

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.5.3",
3
+ "version": "0.5.4",
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": [
@@ -121,8 +121,15 @@ export function createInspectorBunPlugin(opts: InspectorBunPluginOptions): BunPl
121
121
  });
122
122
 
123
123
  let js = result.js.code;
124
- if (result.css?.code && generate !== "server") {
125
- const uid = `${basename(args.path)}-${fnv(args.path)}-style.css`;
124
+ // Skip empty CSS — multiple +page.svelte routes with no <style> would
125
+ // otherwise each emit an empty CSS chunk, all hashing to the same
126
+ // content → Bun fails with "Multiple files share the same output path".
127
+ // Also strip dots from basename: Bun's `[name]-[hash].[ext]` chunk
128
+ // naming treats the first `.` as the extension boundary, so
129
+ // `+page.svelte-…` collapses to `[name]="+page"` for every route.
130
+ if (result.css?.code?.trim() && generate !== "server") {
131
+ const safeBase = basename(args.path).replace(/\./g, "_");
132
+ const uid = `${safeBase}-${fnv(args.path)}-style.css`;
126
133
  const virtualName = `${VIRTUAL_NS}:${uid}`;
127
134
  virtualCss.set(virtualName, result.css.code);
128
135
  js += `\nimport ${JSON.stringify(virtualName)};`;
@@ -691,6 +691,24 @@ if (BODY_SIZE_LIMIT === 0) {
691
691
  console.log(`📦 Body size limit: ${BODY_SIZE_LIMIT} bytes`);
692
692
  }
693
693
 
694
+ // ─── Idle Timeout ─────────────────────────────────────────
695
+ // Parsed once at startup from IDLE_TIMEOUT env var.
696
+ // Integer seconds; Bun caps it at 255. Default: 10 (Bun's default).
697
+ // Raise when API routes hold streaming responses with long gaps
698
+ // between chunks (e.g. AI tool calls that shell out and wait).
699
+
700
+ function parseIdleTimeout(value?: string): number {
701
+ if (!value) return 10;
702
+ const n = parseInt(value, 10);
703
+ if (!Number.isFinite(n) || n < 0) throw new Error(`Invalid IDLE_TIMEOUT: "${value}"`);
704
+ if (n > 255) throw new Error(`Invalid IDLE_TIMEOUT: "${value}" (max 255)`);
705
+ return n;
706
+ }
707
+
708
+ const IDLE_TIMEOUT = parseIdleTimeout(process.env.IDLE_TIMEOUT);
709
+
710
+ console.log(`⏱ Idle timeout: ${IDLE_TIMEOUT}s`);
711
+
694
712
  // ─── Graceful Shutdown State ──────────────────────────────
695
713
 
696
714
  let shuttingDown = false;
@@ -737,13 +755,13 @@ const PORT = process.env.PORT ? parseInt(process.env.PORT, 10) : isDev ? 9001 :
737
755
 
738
756
  // Elysia's chained generics drift when plugins add routes — track the app as a
739
757
  // loose `Elysia` so plugin-extended types stay assignable.
740
- let app: Elysia = new Elysia({ serve: { maxRequestBodySize: BODY_SIZE_LIMIT } }).onError(
741
- ({ error }) => {
742
- if (isDev) console.error("Uncaught server error:", error);
743
- else console.error("Uncaught server error:", (error as Error)?.message ?? error);
744
- return Response.json({ error: "Internal Server Error" }, { status: 500 });
745
- },
746
- ) as unknown as Elysia;
758
+ let app: Elysia = new Elysia({
759
+ serve: { maxRequestBodySize: BODY_SIZE_LIMIT, idleTimeout: IDLE_TIMEOUT },
760
+ }).onError(({ error }) => {
761
+ if (isDev) console.error("Uncaught server error:", error);
762
+ else console.error("Uncaught server error:", (error as Error)?.message ?? error);
763
+ return Response.json({ error: "Internal Server Error" }, { status: 500 });
764
+ }) as unknown as Elysia;
747
765
 
748
766
  // Plugins.backend.before — runs before framework middleware/routes.
749
767
  // Plugin-registered routes here BYPASS the framework (CSRF, hooks, etc.).
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "useTabs": true,
3
- "tabWidth": 4,
3
+ "tabWidth": 2,
4
4
  "singleQuote": false,
5
5
  "trailingComma": "all",
6
6
  "printWidth": 100,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "useTabs": true,
3
- "tabWidth": 4,
3
+ "tabWidth": 2,
4
4
  "singleQuote": false,
5
5
  "trailingComma": "all",
6
6
  "printWidth": 100,
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "useTabs": true,
3
- "tabWidth": 4,
3
+ "tabWidth": 2,
4
4
  "singleQuote": false,
5
5
  "trailingComma": "all",
6
6
  "printWidth": 100,