bosia 0.5.0 → 0.5.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/package.json +1 -1
- package/src/cli/add.ts +8 -4
- package/src/cli/index.ts +10 -6
- package/src/core/dev.ts +37 -23
- package/src/core/server.ts +10 -1
- package/templates/default/bosia.config.ts +10 -0
- package/templates/demo/bosia.config.ts +10 -0
- package/templates/todo/bosia.config.ts +10 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bosia",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
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": [
|
package/src/cli/add.ts
CHANGED
|
@@ -47,10 +47,10 @@ export async function initAddRegistry(root: string | null) {
|
|
|
47
47
|
registryIndex = await loadIndex();
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export async function runAdd(
|
|
51
|
-
if (
|
|
50
|
+
export async function runAdd(names: string[], flags: string[] = []) {
|
|
51
|
+
if (names.length === 0) {
|
|
52
52
|
console.error(
|
|
53
|
-
"❌ Please provide a component name.\n Usage: bun x bosia@latest add <component
|
|
53
|
+
"❌ Please provide a component name.\n Usage: bun x bosia@latest add <component...> [-y] [--local]",
|
|
54
54
|
);
|
|
55
55
|
process.exit(1);
|
|
56
56
|
}
|
|
@@ -60,11 +60,15 @@ export async function runAdd(name: string | undefined, flags: string[] = []) {
|
|
|
60
60
|
console.log(`⬡ Using local registry: ${registryRoot}\n`);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
const skipPrompts = flags.includes("-y") || flags.includes("--yes");
|
|
64
|
+
|
|
63
65
|
// Load index once to resolve component paths
|
|
64
66
|
registryIndex = await loadIndex();
|
|
65
67
|
|
|
66
68
|
ensureUtils();
|
|
67
|
-
|
|
69
|
+
for (const name of names) {
|
|
70
|
+
await addComponent(name, true, { skipPrompts });
|
|
71
|
+
}
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
/**
|
package/src/cli/index.ts
CHANGED
|
@@ -37,18 +37,20 @@ async function main() {
|
|
|
37
37
|
break;
|
|
38
38
|
}
|
|
39
39
|
case "add": {
|
|
40
|
-
const positional = args.filter((a) => !a.startsWith("
|
|
41
|
-
const flags = args.filter((a) => a.startsWith("
|
|
40
|
+
const positional = args.filter((a) => !a.startsWith("-"));
|
|
41
|
+
const flags = args.filter((a) => a.startsWith("-"));
|
|
42
42
|
const sub = positional[0];
|
|
43
43
|
if (sub === "block") {
|
|
44
|
+
const blockFlags = args.filter((a) => a.startsWith("--"));
|
|
44
45
|
const { runAddBlock } = await import("./block.ts");
|
|
45
|
-
await runAddBlock(positional[1],
|
|
46
|
+
await runAddBlock(positional[1], blockFlags);
|
|
46
47
|
} else if (sub === "theme") {
|
|
48
|
+
const themeFlags = args.filter((a) => a.startsWith("--"));
|
|
47
49
|
const { runAddTheme } = await import("./theme.ts");
|
|
48
|
-
await runAddTheme(positional[1],
|
|
50
|
+
await runAddTheme(positional[1], themeFlags);
|
|
49
51
|
} else {
|
|
50
52
|
const { runAdd } = await import("./add.ts");
|
|
51
|
-
await runAdd(
|
|
53
|
+
await runAdd(positional, flags);
|
|
52
54
|
}
|
|
53
55
|
break;
|
|
54
56
|
}
|
|
@@ -72,7 +74,7 @@ Commands:
|
|
|
72
74
|
build Build for production
|
|
73
75
|
start Run the production server
|
|
74
76
|
test [args] Run tests with bun test (auto-loads .env.test, sets BOSIA_ENV=test)
|
|
75
|
-
add <component
|
|
77
|
+
add <component...> [-y] Add one or more UI components from the registry
|
|
76
78
|
add block <cat>/<name> Add a composed block from the registry
|
|
77
79
|
add theme <name> Add a theme (tokens.css) from the registry
|
|
78
80
|
feat <feature> Add a feature scaffold from the registry [--local]
|
|
@@ -87,6 +89,8 @@ Examples:
|
|
|
87
89
|
bun x bosia test --watch
|
|
88
90
|
bun x bosia test --coverage
|
|
89
91
|
bun x bosia@latest add button → src/lib/components/ui/button/
|
|
92
|
+
bun x bosia@latest add button card input → install multiple at once
|
|
93
|
+
bun x bosia@latest add -y button card → auto-confirm overwrites (CI / scripts)
|
|
90
94
|
bun x bosia@latest add shop/cart → src/lib/components/shop/cart/
|
|
91
95
|
bun x bosia@latest add block cards/feature-editorial
|
|
92
96
|
bun x bosia@latest add theme editorial
|
package/src/core/dev.ts
CHANGED
|
@@ -212,29 +212,43 @@ const devServer = Bun.serve({
|
|
|
212
212
|
// the app's CSRF origin check (gated behind TRUST_PROXY=true, also set in the
|
|
213
213
|
// app env above) reconstructs the public-facing origin from the dev proxy
|
|
214
214
|
// rather than the inner-app's host (localhost:APP_PORT).
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
215
|
+
const reqUrl = new URL(req.url);
|
|
216
|
+
const target = new URL(req.url);
|
|
217
|
+
target.hostname = "localhost";
|
|
218
|
+
target.port = String(APP_PORT);
|
|
219
|
+
|
|
220
|
+
const forwardedHeaders = new Headers(req.headers);
|
|
221
|
+
forwardedHeaders.set("x-forwarded-host", reqUrl.host);
|
|
222
|
+
forwardedHeaders.set("x-forwarded-proto", reqUrl.protocol.replace(":", ""));
|
|
223
|
+
|
|
224
|
+
// HMR-driven reloads can land on the proxy before the freshly-respawned
|
|
225
|
+
// inner has bound APP_PORT. Retry for a few seconds on idempotent HTML
|
|
226
|
+
// navigations so the browser doesn't get stuck rendering the 503 body.
|
|
227
|
+
const accept = req.headers.get("accept") ?? "";
|
|
228
|
+
const retryable =
|
|
229
|
+
(req.method === "GET" || req.method === "HEAD") && accept.includes("text/html");
|
|
230
|
+
const deadline = Date.now() + (retryable ? 10_000 : 0);
|
|
231
|
+
|
|
232
|
+
while (true) {
|
|
233
|
+
try {
|
|
234
|
+
return await fetch(
|
|
235
|
+
new Request(target.toString(), {
|
|
236
|
+
method: req.method,
|
|
237
|
+
headers: forwardedHeaders,
|
|
238
|
+
body: req.body,
|
|
239
|
+
redirect: "manual",
|
|
240
|
+
}),
|
|
241
|
+
);
|
|
242
|
+
} catch {
|
|
243
|
+
if (retryable && Date.now() < deadline) {
|
|
244
|
+
await Bun.sleep(250);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
return new Response("App server is starting...", {
|
|
248
|
+
status: 503,
|
|
249
|
+
headers: { "Content-Type": "text/plain", "Retry-After": "1" },
|
|
250
|
+
});
|
|
251
|
+
}
|
|
238
252
|
}
|
|
239
253
|
},
|
|
240
254
|
});
|
package/src/core/server.ts
CHANGED
|
@@ -563,12 +563,21 @@ async function resolve(event: RequestEvent): Promise<Response> {
|
|
|
563
563
|
|
|
564
564
|
// ─── Request Entry ────────────────────────────────────────
|
|
565
565
|
|
|
566
|
+
// Set DISABLE_X_FRAME_OPTIONS=true to omit `X-Frame-Options: SAMEORIGIN`.
|
|
567
|
+
// Useful when the app is intentionally embedded as an iframe by a different origin
|
|
568
|
+
// (preview/proxy hubs, design tools, etc.). Other security headers stay on.
|
|
569
|
+
const _xfoDisabled = process.env.DISABLE_X_FRAME_OPTIONS === "true";
|
|
570
|
+
|
|
566
571
|
const SECURITY_HEADERS: Record<string, string> = {
|
|
567
572
|
"X-Content-Type-Options": "nosniff",
|
|
568
|
-
"X-Frame-Options": "SAMEORIGIN",
|
|
573
|
+
...(_xfoDisabled ? {} : { "X-Frame-Options": "SAMEORIGIN" }),
|
|
569
574
|
"Referrer-Policy": "strict-origin-when-cross-origin",
|
|
570
575
|
};
|
|
571
576
|
|
|
577
|
+
if (_xfoDisabled) {
|
|
578
|
+
console.log("🪟 X-Frame-Options disabled (DISABLE_X_FRAME_OPTIONS=true)");
|
|
579
|
+
}
|
|
580
|
+
|
|
572
581
|
async function handleRequest(request: Request, url: URL): Promise<Response> {
|
|
573
582
|
// Reject new non-health requests during shutdown
|
|
574
583
|
if (shuttingDown && url.pathname !== "/_health") {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineConfig } from "bosia";
|
|
2
|
+
import { inspector } from "bosia/plugins/inspector";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
plugins: [
|
|
6
|
+
// Dev-only: Alt+click any element on the page to open its source in your editor.
|
|
7
|
+
// Change `editor` to "cursor" or "zed" if you don't use VS Code.
|
|
8
|
+
inspector({ editor: "code" }),
|
|
9
|
+
],
|
|
10
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineConfig } from "bosia";
|
|
2
|
+
import { inspector } from "bosia/plugins/inspector";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
plugins: [
|
|
6
|
+
// Dev-only: Alt+click any element on the page to open its source in your editor.
|
|
7
|
+
// Change `editor` to "cursor" or "zed" if you don't use VS Code.
|
|
8
|
+
inspector({ editor: "code" }),
|
|
9
|
+
],
|
|
10
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { defineConfig } from "bosia";
|
|
2
|
+
import { inspector } from "bosia/plugins/inspector";
|
|
3
|
+
|
|
4
|
+
export default defineConfig({
|
|
5
|
+
plugins: [
|
|
6
|
+
// Dev-only: Alt+click any element on the page to open its source in your editor.
|
|
7
|
+
// Change `editor` to "cursor" or "zed" if you don't use VS Code.
|
|
8
|
+
inspector({ editor: "code" }),
|
|
9
|
+
],
|
|
10
|
+
});
|