bosia 0.3.2 → 0.3.3

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.3.2",
3
+ "version": "0.3.3",
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
@@ -11,13 +11,13 @@ import {
11
11
  bunAdd,
12
12
  } from "./registry.ts";
13
13
 
14
- // ─── bosia add <component> ────────────────────────────────
14
+ // ─── bun x bosia@latest add <component> ──────────────────
15
15
  // Fetches a component from the GitHub registry (or local registry
16
16
  // with --local) and copies it into src/lib/components/<path>/.
17
17
  //
18
18
  // Path-based names:
19
- // bosia add button → src/lib/components/ui/button/
20
- // bosia add shop/cart → src/lib/components/shop/cart/
19
+ // bun x bosia@latest add button → src/lib/components/ui/button/
20
+ // bun x bosia@latest add shop/cart → src/lib/components/shop/cart/
21
21
 
22
22
  interface ComponentMeta {
23
23
  name: string;
@@ -48,7 +48,7 @@ export async function initAddRegistry(root: string | null) {
48
48
  export async function runAdd(name: string | undefined, flags: string[] = []) {
49
49
  if (!name) {
50
50
  console.error(
51
- "❌ Please provide a component name.\n Usage: bosia add <component> [--local]",
51
+ "❌ Please provide a component name.\n Usage: bun x bosia@latest add <component> [--local]",
52
52
  );
53
53
  process.exit(1);
54
54
  }
package/src/cli/create.ts CHANGED
@@ -5,7 +5,7 @@ import * as p from "@clack/prompts";
5
5
  import { installFeature, initFeatRegistry, resolveLocalRegistry } from "./feat.ts";
6
6
  import { initAddRegistry } from "./add.ts";
7
7
 
8
- // ─── bosia create <name> [--template <name>] ──────────────
8
+ // ─── bun x bosia@latest create <name> [--template <name>]
9
9
 
10
10
  const TEMPLATES_DIR = resolve(import.meta.dir, "../../templates");
11
11
  const BOSIA_PKG = JSON.parse(readFileSync(resolve(import.meta.dir, "../../package.json"), "utf-8"));
@@ -19,7 +19,9 @@ const TEMPLATE_DESCRIPTIONS: Record<string, string> = {
19
19
 
20
20
  export async function runCreate(name: string | undefined, args: string[] = []) {
21
21
  if (!name) {
22
- console.error("❌ Please provide a project name.\n Usage: bosia create my-app");
22
+ console.error(
23
+ "❌ Please provide a project name.\n Usage: bun x bosia@latest create my-app",
24
+ );
23
25
  process.exit(1);
24
26
  }
25
27
 
package/src/cli/feat.ts CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  bunAdd,
12
12
  } from "./registry.ts";
13
13
 
14
- // ─── bosia feat <feature> [--local] ──────────────────────
14
+ // ─── bun x bosia@latest feat <feature> [--local] ─────────
15
15
  // Fetches a feature scaffold from the GitHub registry (or local
16
16
  // registry with --local) and copies route/lib files, installs npm deps.
17
17
  // Supports nested feature dependencies (e.g. todo → drizzle).
@@ -34,7 +34,7 @@ interface FeatureMeta {
34
34
  name: string;
35
35
  description: string;
36
36
  features?: string[]; // other bosia features required
37
- components: string[]; // bosia components to install via `bosia add`
37
+ components: string[]; // bosia components to install via `bun x bosia@latest add`
38
38
  files: FileEntry[]; // file entries with per-file strategy
39
39
  npmDeps: Record<string, string>;
40
40
  npmDevDeps?: Record<string, string>;
@@ -50,7 +50,7 @@ const installedFeats = new Set<string>();
50
50
  export async function runFeat(name: string | undefined, flags: string[] = []) {
51
51
  if (!name) {
52
52
  console.error(
53
- "❌ Please provide a feature name.\n Usage: bosia feat <feature> [--local]",
53
+ "❌ Please provide a feature name.\n Usage: bun x bosia@latest feat <feature> [--local]",
54
54
  );
55
55
  process.exit(1);
56
56
  }
package/src/cli/index.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env bun
2
2
  // ─── Bosia CLI ────────────────────────────────────────────
3
- // bosia create <name> scaffold a new project
4
- // bosia dev start the development server
5
- // bosia build build for production
6
- // bosia start run the production server
7
- // bosia add <name> add a UI component from the registry
8
- // bosia feat <name> add a feature scaffold from the registry
3
+ // bun x bosia@latest create <name> scaffold a new project
4
+ // bun x bosia dev start the development server
5
+ // bun x bosia build build for production
6
+ // bun x bosia start run the production server
7
+ // bun x bosia@latest add <name> add a UI component from the registry
8
+ // bun x bosia@latest feat <name> add a feature scaffold from the registry
9
9
 
10
10
  const [, , command, ...args] = process.argv;
11
11
 
@@ -67,17 +67,17 @@ Commands:
67
67
  feat <feature> Add a feature scaffold from the registry [--local]
68
68
 
69
69
  Examples:
70
- bosia create my-app
71
- bosia create my-app --template todo
72
- bosia dev
73
- bosia build
74
- bosia start
75
- bosia test
76
- bosia test --watch
77
- bosia test --coverage
78
- bosia add button → src/lib/components/ui/button/
79
- bosia add shop/cart → src/lib/components/shop/cart/
80
- bosia feat login
70
+ bun x bosia@latest create my-app
71
+ bun x bosia@latest create my-app --template todo
72
+ bun x bosia dev
73
+ bun x bosia build
74
+ bun x bosia start
75
+ bun x bosia test
76
+ bun x bosia test --watch
77
+ bun x bosia test --coverage
78
+ bun x bosia@latest add button → src/lib/components/ui/button/
79
+ bun x bosia@latest add shop/cart → src/lib/components/shop/cart/
80
+ bun x bosia@latest feat login
81
81
  `);
82
82
  break;
83
83
  }
@@ -1,4 +1,5 @@
1
1
  import { join, dirname } from "path";
2
+ import { existsSync } from "fs";
2
3
 
3
4
  // ─── Bun Build Plugin ─────────────────────────────────────
4
5
  // Resolves:
@@ -9,11 +10,18 @@ import { join, dirname } from "path";
9
10
  let cachedTsconfigPaths: Record<string, string[]> | null = null;
10
11
  async function getTsconfigPaths() {
11
12
  if (cachedTsconfigPaths !== null) return cachedTsconfigPaths;
13
+ const tsconfigPath = join(process.cwd(), "tsconfig.json");
14
+ if (!existsSync(tsconfigPath)) {
15
+ cachedTsconfigPaths = {};
16
+ return cachedTsconfigPaths;
17
+ }
12
18
  try {
13
- const tsconfig = await Bun.file(join(process.cwd(), "tsconfig.json")).json();
19
+ const tsconfig = await Bun.file(tsconfigPath).json();
14
20
  cachedTsconfigPaths = tsconfig?.compilerOptions?.paths || {};
15
- } catch {
16
- cachedTsconfigPaths = {};
21
+ } catch (err) {
22
+ throw new Error(
23
+ `tsconfig.json at ${tsconfigPath} is invalid JSON: ${(err as Error).message}. Fix the file and re-run.`,
24
+ );
17
25
  }
18
26
  return cachedTsconfigPaths!;
19
27
  }
@@ -50,6 +50,8 @@ export function generateRouteTypes(manifest: RouteManifest): void {
50
50
  }
51
51
  }
52
52
 
53
+ if (manifest.errorPage && !dirs.has(".")) dirs.set(".", {});
54
+
53
55
  for (const [dir, info] of dirs) {
54
56
  // Path segments of the route dir (empty array for root ".")
55
57
  const segments = dir === "." ? [] : dir.split("/").filter(Boolean);
@@ -96,6 +98,12 @@ export function generateRouteTypes(manifest: RouteManifest): void {
96
98
  }
97
99
  lines.push(`export type PageProps = { data: PageData };`);
98
100
 
101
+ if (dir === "." && manifest.errorPage) {
102
+ lines.push(``);
103
+ lines.push(`export type PageError = { status: number; message: string };`);
104
+ lines.push(`export type ErrorProps = { error: PageError };`);
105
+ }
106
+
99
107
  // ActionData — union of all action return types, unwrapping ActionFailure
100
108
  if (info.pageServer) {
101
109
  lines.push(``);
@@ -144,12 +152,10 @@ export function ensureRootDirs(): void {
144
152
  let tsconfig: any;
145
153
  try {
146
154
  tsconfig = JSON.parse(readFileSync(tsconfigPath, "utf-8"));
147
- } catch {
148
- console.warn(
149
- "⚠️ Could not parse tsconfig.json add rootDirs manually:\n" +
150
- ' "rootDirs": [".", ".bosia/types"]',
155
+ } catch (err) {
156
+ throw new Error(
157
+ `tsconfig.json at ${tsconfigPath} is invalid JSON: ${(err as Error).message}. Fix the file and re-run.`,
151
158
  );
152
- return;
153
159
  }
154
160
 
155
161
  const rootDirs: string[] = tsconfig.compilerOptions?.rootDirs ?? [];
@@ -404,7 +404,7 @@ async function resolve(event: RequestEvent): Promise<Response> {
404
404
  { status: result.status },
405
405
  );
406
406
  }
407
- return renderPageWithFormData(
407
+ return await renderPageWithFormData(
408
408
  url,
409
409
  locals,
410
410
  request,
@@ -422,7 +422,7 @@ async function resolve(event: RequestEvent): Promise<Response> {
422
422
  data: result ?? null,
423
423
  });
424
424
  }
425
- return renderPageWithFormData(
425
+ return await renderPageWithFormData(
426
426
  url,
427
427
  locals,
428
428
  request,
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
- let { error }: { error: { status: number; message: string } } = $props();
2
+ import type { ErrorProps } from "./$types";
3
+ let { error }: ErrorProps = $props();
3
4
  </script>
4
5
 
5
6
  <svelte:head>
@@ -26,7 +26,7 @@
26
26
  {
27
27
  icon: "🧩",
28
28
  label: "Component registry",
29
- desc: "bosia add button — shadcn-style, code you own",
29
+ desc: "bun x bosia@latest add button — shadcn-style, code you own",
30
30
  },
31
31
  {
32
32
  icon: "✨",
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <ul class="space-y-2 text-foreground">
12
- {#each ["Bun runtime — fast builds, native TypeScript", "ElysiaJS — HTTP server with type-safe routing", "Svelte 5 Runes — fine-grained reactivity", "Isomorphic SSR with client hydration", "File-based routing (SvelteKit-compatible conventions)", "Nested layouts and route groups (public), (auth), (admin)", "Dynamic params [slug] and catch-all [...rest]", "Server loaders with parent() data threading", "Hooks — sequence() middleware for auth, logging, etc.", "Component registry — bosia add button", "Feature registry — bosia feat login"] as item}
12
+ {#each ["Bun runtime — fast builds, native TypeScript", "ElysiaJS — HTTP server with type-safe routing", "Svelte 5 Runes — fine-grained reactivity", "Isomorphic SSR with client hydration", "File-based routing (SvelteKit-compatible conventions)", "Nested layouts and route groups (public), (auth), (admin)", "Dynamic params [slug] and catch-all [...rest]", "Server loaders with parent() data threading", "Hooks — sequence() middleware for auth, logging, etc.", "Component registry — bun x bosia@latest add button", "Feature registry — bosia feat login"] as item}
13
13
  <li class="flex items-start gap-2">
14
14
  <span class="text-primary mt-0.5">✓</span>
15
15
  <span>{item}</span>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
- let { error }: { error: { status: number; message: string } } = $props();
2
+ import type { ErrorProps } from "./$types";
3
+ let { error }: ErrorProps = $props();
3
4
  </script>
4
5
 
5
6
  <svelte:head>
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
- let { error }: { error: { status: number; message: string } } = $props();
2
+ import type { ErrorProps } from "./$types";
3
+ let { error }: ErrorProps = $props();
3
4
  </script>
4
5
 
5
6
  <svelte:head>