bosia 0.2.3 → 0.3.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.
Files changed (86) hide show
  1. package/README.md +39 -39
  2. package/package.json +56 -54
  3. package/src/ambient.d.ts +31 -0
  4. package/src/cli/add.ts +120 -114
  5. package/src/cli/build.ts +10 -10
  6. package/src/cli/create.ts +142 -137
  7. package/src/cli/dev.ts +8 -8
  8. package/src/cli/feat.ts +266 -258
  9. package/src/cli/index.ts +51 -42
  10. package/src/cli/registry.ts +136 -115
  11. package/src/cli/start.ts +17 -17
  12. package/src/cli/test.ts +25 -0
  13. package/src/core/build.ts +72 -56
  14. package/src/core/client/App.svelte +177 -156
  15. package/src/core/client/appState.svelte.ts +33 -31
  16. package/src/core/client/enhance.ts +83 -78
  17. package/src/core/client/hydrate.ts +95 -81
  18. package/src/core/client/prefetch.ts +101 -94
  19. package/src/core/client/router.svelte.ts +64 -51
  20. package/src/core/cookies.ts +70 -66
  21. package/src/core/cors.ts +44 -35
  22. package/src/core/csrf.ts +38 -38
  23. package/src/core/dedup.ts +17 -17
  24. package/src/core/dev.ts +165 -168
  25. package/src/core/env.ts +155 -148
  26. package/src/core/envCodegen.ts +73 -73
  27. package/src/core/errors.ts +48 -49
  28. package/src/core/hooks.ts +50 -50
  29. package/src/core/html.ts +184 -145
  30. package/src/core/matcher.ts +130 -121
  31. package/src/core/paths.ts +8 -10
  32. package/src/core/plugin.ts +113 -107
  33. package/src/core/prerender.ts +191 -122
  34. package/src/core/renderer.ts +359 -286
  35. package/src/core/routeFile.ts +140 -127
  36. package/src/core/routeTypes.ts +144 -83
  37. package/src/core/scanner.ts +125 -95
  38. package/src/core/server.ts +538 -424
  39. package/src/core/types.ts +25 -20
  40. package/src/lib/index.ts +8 -8
  41. package/src/lib/utils.ts +44 -30
  42. package/templates/default/.prettierignore +5 -0
  43. package/templates/default/.prettierrc.json +9 -0
  44. package/templates/default/README.md +5 -5
  45. package/templates/default/package.json +22 -18
  46. package/templates/default/src/app.css +80 -80
  47. package/templates/default/src/app.d.ts +3 -3
  48. package/templates/default/src/routes/+error.svelte +7 -10
  49. package/templates/default/src/routes/+layout.svelte +2 -2
  50. package/templates/default/src/routes/+page.svelte +31 -29
  51. package/templates/default/src/routes/about/+page.svelte +3 -3
  52. package/templates/default/tsconfig.json +20 -20
  53. package/templates/demo/.prettierignore +5 -0
  54. package/templates/demo/.prettierrc.json +9 -0
  55. package/templates/demo/README.md +9 -9
  56. package/templates/demo/package.json +22 -17
  57. package/templates/demo/src/app.css +80 -80
  58. package/templates/demo/src/app.d.ts +3 -3
  59. package/templates/demo/src/hooks.server.ts +9 -9
  60. package/templates/demo/src/routes/(public)/+layout.svelte +45 -23
  61. package/templates/demo/src/routes/(public)/+page.svelte +96 -67
  62. package/templates/demo/src/routes/(public)/about/+page.svelte +13 -25
  63. package/templates/demo/src/routes/(public)/all/[...catchall]/+page.svelte +24 -28
  64. package/templates/demo/src/routes/(public)/blog/+page.svelte +55 -46
  65. package/templates/demo/src/routes/(public)/blog/[slug]/+page.server.ts +36 -38
  66. package/templates/demo/src/routes/(public)/blog/[slug]/+page.svelte +60 -42
  67. package/templates/demo/src/routes/+error.svelte +10 -7
  68. package/templates/demo/src/routes/+layout.server.ts +4 -4
  69. package/templates/demo/src/routes/+layout.svelte +2 -2
  70. package/templates/demo/src/routes/actions-test/+page.server.ts +16 -16
  71. package/templates/demo/src/routes/actions-test/+page.svelte +49 -49
  72. package/templates/demo/src/routes/api/hello/+server.ts +25 -25
  73. package/templates/demo/tsconfig.json +20 -20
  74. package/templates/todo/.prettierignore +5 -0
  75. package/templates/todo/.prettierrc.json +9 -0
  76. package/templates/todo/README.md +9 -9
  77. package/templates/todo/package.json +22 -17
  78. package/templates/todo/src/app.css +80 -80
  79. package/templates/todo/src/app.d.ts +7 -7
  80. package/templates/todo/src/hooks.server.ts +9 -9
  81. package/templates/todo/src/routes/+error.svelte +10 -7
  82. package/templates/todo/src/routes/+layout.server.ts +4 -4
  83. package/templates/todo/src/routes/+layout.svelte +2 -2
  84. package/templates/todo/src/routes/+page.svelte +44 -44
  85. package/templates/todo/template.json +1 -1
  86. package/templates/todo/tsconfig.json +20 -20
@@ -1,60 +1,60 @@
1
1
  <script lang="ts">
2
- import type { PageData, ActionData } from './$types';
3
- let { data, form }: { data: PageData; form: ActionData } = $props();
2
+ import type { PageData, ActionData } from "./$types";
3
+ let { data, form }: { data: PageData; form: ActionData } = $props();
4
4
  </script>
5
5
 
6
6
  <div class="max-w-md mx-auto mt-10 p-6">
7
- <h1 class="text-2xl font-bold mb-4">{data.greeting}</h1>
7
+ <h1 class="text-2xl font-bold mb-4">{data.greeting}</h1>
8
8
 
9
- {#if form?.success}
10
- <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4">
11
- Welcome, {form.name} ({form.email})!
12
- </div>
13
- {/if}
9
+ {#if form?.success}
10
+ <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded mb-4">
11
+ Welcome, {form.name} ({form.email})!
12
+ </div>
13
+ {/if}
14
14
 
15
- {#if form?.cleared}
16
- <div class="bg-blue-100 border border-blue-400 text-blue-700 px-4 py-3 rounded mb-4">
17
- Form cleared.
18
- </div>
19
- {/if}
15
+ {#if form?.cleared}
16
+ <div class="bg-blue-100 border border-blue-400 text-blue-700 px-4 py-3 rounded mb-4">
17
+ Form cleared.
18
+ </div>
19
+ {/if}
20
20
 
21
- <form method="POST" class="space-y-4">
22
- <div>
23
- <label for="name" class="block text-sm font-medium">Name</label>
24
- <input
25
- id="name"
26
- name="name"
27
- type="text"
28
- value={form?.name ?? ''}
29
- class="mt-1 block w-full rounded border border-gray-300 px-3 py-2"
30
- />
31
- {#if form?.errors?.name}
32
- <p class="text-red-500 text-sm mt-1">{form.errors.name}</p>
33
- {/if}
34
- </div>
21
+ <form method="POST" class="space-y-4">
22
+ <div>
23
+ <label for="name" class="block text-sm font-medium">Name</label>
24
+ <input
25
+ id="name"
26
+ name="name"
27
+ type="text"
28
+ value={form?.name ?? ""}
29
+ class="mt-1 block w-full rounded border border-gray-300 px-3 py-2"
30
+ />
31
+ {#if form?.errors?.name}
32
+ <p class="text-red-500 text-sm mt-1">{form.errors.name}</p>
33
+ {/if}
34
+ </div>
35
35
 
36
- <div>
37
- <label for="email" class="block text-sm font-medium">Email</label>
38
- <input
39
- id="email"
40
- name="email"
41
- type="text"
42
- value={form?.email ?? ''}
43
- class="mt-1 block w-full rounded border border-gray-300 px-3 py-2"
44
- />
45
- {#if form?.errors?.email}
46
- <p class="text-red-500 text-sm mt-1">{form.errors.email}</p>
47
- {/if}
48
- </div>
36
+ <div>
37
+ <label for="email" class="block text-sm font-medium">Email</label>
38
+ <input
39
+ id="email"
40
+ name="email"
41
+ type="text"
42
+ value={form?.email ?? ""}
43
+ class="mt-1 block w-full rounded border border-gray-300 px-3 py-2"
44
+ />
45
+ {#if form?.errors?.email}
46
+ <p class="text-red-500 text-sm mt-1">{form.errors.email}</p>
47
+ {/if}
48
+ </div>
49
49
 
50
- <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
51
- Submit
52
- </button>
53
- </form>
50
+ <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">
51
+ Submit
52
+ </button>
53
+ </form>
54
54
 
55
- <form method="POST" action="?/reset" class="mt-4">
56
- <button type="submit" class="bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600">
57
- Reset (named action)
58
- </button>
59
- </form>
55
+ <form method="POST" action="?/reset" class="mt-4">
56
+ <button type="submit" class="bg-gray-500 text-white px-4 py-2 rounded hover:bg-gray-600">
57
+ Reset (named action)
58
+ </button>
59
+ </form>
60
60
  </div>
@@ -1,44 +1,44 @@
1
1
  import type { RequestEvent } from "bosia";
2
2
 
3
3
  export function GET({ params, locals }: RequestEvent) {
4
- return Response.json({
5
- method: "GET",
6
- message: "Hello from Bosia API!",
7
- params,
8
- locals: {
9
- requestTime: locals.requestTime ?? null,
10
- user: locals.user ?? null,
11
- },
12
- });
4
+ return Response.json({
5
+ method: "GET",
6
+ message: "Hello from Bosia API!",
7
+ params,
8
+ locals: {
9
+ requestTime: locals.requestTime ?? null,
10
+ user: locals.user ?? null,
11
+ },
12
+ });
13
13
  }
14
14
 
15
15
  export async function POST({ request, locals }: RequestEvent) {
16
- const body = await request.json().catch(() => ({}));
17
- return Response.json({ method: "POST", received: body, locals });
16
+ const body = await request.json().catch(() => ({}));
17
+ return Response.json({ method: "POST", received: body, locals });
18
18
  }
19
19
 
20
20
  export async function PUT({ request, locals }: RequestEvent) {
21
- const body = await request.json().catch(() => ({}));
22
- return Response.json({ method: "PUT", received: body, locals });
21
+ const body = await request.json().catch(() => ({}));
22
+ return Response.json({ method: "PUT", received: body, locals });
23
23
  }
24
24
 
25
25
  export async function PATCH({ request, locals }: RequestEvent) {
26
- const body = await request.json().catch(() => ({}));
27
- return Response.json({ method: "PATCH", received: body, locals });
26
+ const body = await request.json().catch(() => ({}));
27
+ return Response.json({ method: "PATCH", received: body, locals });
28
28
  }
29
29
 
30
30
  export function DELETE({ params, locals }: RequestEvent) {
31
- return Response.json({ method: "DELETE", deleted: true, params, locals });
31
+ return Response.json({ method: "DELETE", deleted: true, params, locals });
32
32
  }
33
33
 
34
34
  export function OPTIONS() {
35
- return new Response(null, {
36
- status: 204,
37
- headers: {
38
- Allow: "GET, POST, PUT, PATCH, DELETE, OPTIONS",
39
- "Access-Control-Allow-Origin": "*",
40
- "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
41
- "Access-Control-Allow-Headers": "Content-Type, Authorization",
42
- },
43
- });
35
+ return new Response(null, {
36
+ status: 204,
37
+ headers: {
38
+ Allow: "GET, POST, PUT, PATCH, DELETE, OPTIONS",
39
+ "Access-Control-Allow-Origin": "*",
40
+ "Access-Control-Allow-Methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
41
+ "Access-Control-Allow-Headers": "Content-Type, Authorization",
42
+ },
43
+ });
44
44
  }
@@ -1,22 +1,22 @@
1
1
  {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "strict": true,
7
- "allowJs": true,
8
- "skipLibCheck": true,
9
- "allowImportingTsExtensions": true,
10
- "noEmit": true,
11
- "verbatimModuleSyntax": true,
12
- "types": ["bun-types"],
13
- "lib": ["dom", "dom.iterable", "esnext"],
14
- "rootDirs": [".", ".bosia/types"],
15
- "paths": {
16
- "$lib": ["./src/lib"],
17
- "$lib/*": ["./src/lib/*"]
18
- }
19
- },
20
- "include": ["src/**/*"],
21
- "exclude": ["node_modules", "dist"]
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "allowJs": true,
8
+ "skipLibCheck": true,
9
+ "allowImportingTsExtensions": true,
10
+ "noEmit": true,
11
+ "verbatimModuleSyntax": true,
12
+ "types": ["bun-types"],
13
+ "lib": ["dom", "dom.iterable", "esnext"],
14
+ "rootDirs": [".", ".bosia/types"],
15
+ "paths": {
16
+ "$lib": ["./src/lib"],
17
+ "$lib/*": ["./src/lib/*"]
18
+ }
19
+ },
20
+ "include": ["src/**/*"],
21
+ "exclude": ["node_modules", "dist"]
22
22
  }
@@ -0,0 +1,5 @@
1
+ node_modules
2
+ dist
3
+ build
4
+ .bosia
5
+ bun.lock
@@ -0,0 +1,9 @@
1
+ {
2
+ "useTabs": true,
3
+ "tabWidth": 4,
4
+ "singleQuote": false,
5
+ "trailingComma": "all",
6
+ "printWidth": 100,
7
+ "plugins": ["prettier-plugin-svelte"],
8
+ "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
9
+ }
@@ -27,16 +27,16 @@ Visit [http://localhost:9000](http://localhost:9000) to see the app.
27
27
 
28
28
  ## Scripts
29
29
 
30
- | Command | Description |
31
- |---------|-------------|
32
- | `bun x bosia dev` | Start dev server with HMR |
33
- | `bun x bosia build` | Production build |
34
- | `bun x bosia start` | Start production server |
30
+ | Command | Description |
31
+ | --------------------- | -------------------------------------- |
32
+ | `bun x bosia dev` | Start dev server with HMR |
33
+ | `bun x bosia build` | Production build |
34
+ | `bun x bosia start` | Start production server |
35
35
  | `bun run db:generate` | Generate migration from schema changes |
36
- | `bun run db:migrate` | Apply pending migrations |
37
- | `bun run db:push` | Push schema directly (dev shortcut) |
38
- | `bun run db:studio` | Open Drizzle Studio GUI |
39
- | `bun run db:seed` | Run pending seed files |
36
+ | `bun run db:migrate` | Apply pending migrations |
37
+ | `bun run db:push` | Push schema directly (dev shortcut) |
38
+ | `bun run db:studio` | Open Drizzle Studio GUI |
39
+ | `bun run db:seed` | Run pending seed files |
40
40
 
41
41
  ## Project Structure
42
42
 
@@ -1,19 +1,24 @@
1
1
  {
2
- "name": "{{PROJECT_NAME}}",
3
- "private": true,
4
- "type": "module",
5
- "scripts": {
6
- "dev": "bosia dev",
7
- "build": "bosia build",
8
- "start": "bosia start"
9
- },
10
- "dependencies": {
11
- "bosia": "^{{BOSIA_VERSION}}",
12
- "svelte": "^5.20.0",
13
- "tailwind-merge": "^3.5.0"
14
- },
15
- "devDependencies": {
16
- "@types/bun": "latest",
17
- "typescript": "^5"
18
- }
2
+ "name": "{{PROJECT_NAME}}",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "bosia dev",
7
+ "build": "bosia build",
8
+ "start": "bosia start",
9
+ "check": "tsc --noEmit && prettier --check .",
10
+ "format": "prettier --write .",
11
+ "format:check": "prettier --check ."
12
+ },
13
+ "dependencies": {
14
+ "bosia": "^{{BOSIA_VERSION}}",
15
+ "svelte": "^5.20.0",
16
+ "tailwind-merge": "^3.5.0"
17
+ },
18
+ "devDependencies": {
19
+ "@types/bun": "latest",
20
+ "prettier": "^3.3.0",
21
+ "prettier-plugin-svelte": "^3.2.0",
22
+ "typescript": "^5"
23
+ }
19
24
  }
@@ -8,125 +8,125 @@
8
8
  */
9
9
 
10
10
  @theme {
11
- --color-background: hsl(var(--background));
12
- --color-foreground: hsl(var(--foreground));
11
+ --color-background: hsl(var(--background));
12
+ --color-foreground: hsl(var(--foreground));
13
13
 
14
- --color-card: hsl(var(--card));
15
- --color-card-foreground: hsl(var(--card-foreground));
14
+ --color-card: hsl(var(--card));
15
+ --color-card-foreground: hsl(var(--card-foreground));
16
16
 
17
- --color-popover: hsl(var(--popover));
18
- --color-popover-foreground: hsl(var(--popover-foreground));
17
+ --color-popover: hsl(var(--popover));
18
+ --color-popover-foreground: hsl(var(--popover-foreground));
19
19
 
20
- --color-primary: hsl(var(--primary));
21
- --color-primary-foreground: hsl(var(--primary-foreground));
20
+ --color-primary: hsl(var(--primary));
21
+ --color-primary-foreground: hsl(var(--primary-foreground));
22
22
 
23
- --color-secondary: hsl(var(--secondary));
24
- --color-secondary-foreground: hsl(var(--secondary-foreground));
23
+ --color-secondary: hsl(var(--secondary));
24
+ --color-secondary-foreground: hsl(var(--secondary-foreground));
25
25
 
26
- --color-muted: hsl(var(--muted));
27
- --color-muted-foreground: hsl(var(--muted-foreground));
26
+ --color-muted: hsl(var(--muted));
27
+ --color-muted-foreground: hsl(var(--muted-foreground));
28
28
 
29
- --color-accent: hsl(var(--accent));
30
- --color-accent-foreground: hsl(var(--accent-foreground));
29
+ --color-accent: hsl(var(--accent));
30
+ --color-accent-foreground: hsl(var(--accent-foreground));
31
31
 
32
- --color-destructive: hsl(var(--destructive));
33
- --color-destructive-foreground: hsl(var(--destructive-foreground));
32
+ --color-destructive: hsl(var(--destructive));
33
+ --color-destructive-foreground: hsl(var(--destructive-foreground));
34
34
 
35
- --color-border: hsl(var(--border));
36
- --color-input: hsl(var(--input));
37
- --color-ring: hsl(var(--ring));
35
+ --color-border: hsl(var(--border));
36
+ --color-input: hsl(var(--input));
37
+ --color-ring: hsl(var(--ring));
38
38
 
39
- --radius-sm: calc(var(--radius) - 4px);
40
- --radius-md: calc(var(--radius) - 2px);
41
- --radius-lg: var(--radius);
42
- --radius-xl: calc(var(--radius) + 4px);
39
+ --radius-sm: calc(var(--radius) - 4px);
40
+ --radius-md: calc(var(--radius) - 2px);
41
+ --radius-lg: var(--radius);
42
+ --radius-xl: calc(var(--radius) + 4px);
43
43
  }
44
44
 
45
45
  /* ─── Light Theme (Default) ─────────────────────────────── */
46
46
 
47
47
  :root {
48
- --background: 0 0% 100%;
49
- --foreground: 222.2 84% 4.9%;
48
+ --background: 0 0% 100%;
49
+ --foreground: 222.2 84% 4.9%;
50
50
 
51
- --card: 0 0% 100%;
52
- --card-foreground: 222.2 84% 4.9%;
51
+ --card: 0 0% 100%;
52
+ --card-foreground: 222.2 84% 4.9%;
53
53
 
54
- --popover: 0 0% 100%;
55
- --popover-foreground: 222.2 84% 4.9%;
54
+ --popover: 0 0% 100%;
55
+ --popover-foreground: 222.2 84% 4.9%;
56
56
 
57
- --primary: 222.2 47.4% 11.2%;
58
- --primary-foreground: 210 40% 98%;
57
+ --primary: 222.2 47.4% 11.2%;
58
+ --primary-foreground: 210 40% 98%;
59
59
 
60
- --secondary: 210 40% 96.1%;
61
- --secondary-foreground: 222.2 47.4% 11.2%;
60
+ --secondary: 210 40% 96.1%;
61
+ --secondary-foreground: 222.2 47.4% 11.2%;
62
62
 
63
- --muted: 210 40% 96.1%;
64
- --muted-foreground: 215.4 16.3% 46.9%;
63
+ --muted: 210 40% 96.1%;
64
+ --muted-foreground: 215.4 16.3% 46.9%;
65
65
 
66
- --accent: 210 40% 96.1%;
67
- --accent-foreground: 222.2 47.4% 11.2%;
66
+ --accent: 210 40% 96.1%;
67
+ --accent-foreground: 222.2 47.4% 11.2%;
68
68
 
69
- --destructive: 0 84.2% 60.2%;
70
- --destructive-foreground: 210 40% 98%;
69
+ --destructive: 0 84.2% 60.2%;
70
+ --destructive-foreground: 210 40% 98%;
71
71
 
72
- --border: 214.3 31.8% 91.4%;
73
- --input: 214.3 31.8% 91.4%;
74
- --ring: 222.2 84% 4.9%;
72
+ --border: 214.3 31.8% 91.4%;
73
+ --input: 214.3 31.8% 91.4%;
74
+ --ring: 222.2 84% 4.9%;
75
75
 
76
- --radius: 0.5rem;
76
+ --radius: 0.5rem;
77
77
  }
78
78
 
79
79
  /* ─── Dark Theme ─────────────────────────────────────────── */
80
80
 
81
81
  .dark {
82
- --background: 222.2 84% 4.9%;
83
- --foreground: 210 40% 98%;
82
+ --background: 222.2 84% 4.9%;
83
+ --foreground: 210 40% 98%;
84
84
 
85
- --card: 222.2 84% 4.9%;
86
- --card-foreground: 210 40% 98%;
85
+ --card: 222.2 84% 4.9%;
86
+ --card-foreground: 210 40% 98%;
87
87
 
88
- --popover: 222.2 84% 4.9%;
89
- --popover-foreground: 210 40% 98%;
88
+ --popover: 222.2 84% 4.9%;
89
+ --popover-foreground: 210 40% 98%;
90
90
 
91
- --primary: 210 40% 98%;
92
- --primary-foreground: 222.2 47.4% 11.2%;
91
+ --primary: 210 40% 98%;
92
+ --primary-foreground: 222.2 47.4% 11.2%;
93
93
 
94
- --secondary: 217.2 32.6% 17.5%;
95
- --secondary-foreground: 210 40% 98%;
94
+ --secondary: 217.2 32.6% 17.5%;
95
+ --secondary-foreground: 210 40% 98%;
96
96
 
97
- --muted: 217.2 32.6% 17.5%;
98
- --muted-foreground: 215 20.2% 65.1%;
97
+ --muted: 217.2 32.6% 17.5%;
98
+ --muted-foreground: 215 20.2% 65.1%;
99
99
 
100
- --accent: 217.2 32.6% 17.5%;
101
- --accent-foreground: 210 40% 98%;
100
+ --accent: 217.2 32.6% 17.5%;
101
+ --accent-foreground: 210 40% 98%;
102
102
 
103
- --destructive: 0 62.8% 30.6%;
104
- --destructive-foreground: 210 40% 98%;
103
+ --destructive: 0 62.8% 30.6%;
104
+ --destructive-foreground: 210 40% 98%;
105
105
 
106
- --border: 217.2 32.6% 17.5%;
107
- --input: 217.2 32.6% 17.5%;
108
- --ring: 212.7 26.8% 83.9%;
106
+ --border: 217.2 32.6% 17.5%;
107
+ --input: 217.2 32.6% 17.5%;
108
+ --ring: 212.7 26.8% 83.9%;
109
109
  }
110
110
 
111
111
  /* ─── Base Styles ────────────────────────────────────────── */
112
112
 
113
113
  @layer base {
114
- * {
115
- border-color: theme(--color-border);
116
- }
117
-
118
- body {
119
- background-color: theme(--color-background);
120
- color: theme(--color-foreground);
121
- font-family:
122
- "Inter",
123
- system-ui,
124
- -apple-system,
125
- BlinkMacSystemFont,
126
- "Segoe UI",
127
- Roboto,
128
- "Helvetica Neue",
129
- Arial,
130
- sans-serif;
131
- }
114
+ * {
115
+ border-color: theme(--color-border);
116
+ }
117
+
118
+ body {
119
+ background-color: theme(--color-background);
120
+ color: theme(--color-foreground);
121
+ font-family:
122
+ "Inter",
123
+ system-ui,
124
+ -apple-system,
125
+ BlinkMacSystemFont,
126
+ "Segoe UI",
127
+ Roboto,
128
+ "Helvetica Neue",
129
+ Arial,
130
+ sans-serif;
131
+ }
132
132
  }
@@ -1,14 +1,14 @@
1
1
  /// <reference types="svelte" />
2
2
 
3
3
  declare module "*.svelte" {
4
- import type { Component } from "svelte";
5
- const component: Component<Record<string, any>, Record<string, any>, any>;
6
- export default component;
4
+ import type { Component } from "svelte";
5
+ const component: Component<Record<string, any>, Record<string, any>, any>;
6
+ export default component;
7
7
  }
8
8
 
9
9
  declare namespace App {
10
- interface Locals {
11
- db: import("./features/drizzle").Database;
12
- requestTime: number;
13
- }
10
+ interface Locals {
11
+ db: import("./features/drizzle").Database;
12
+ requestTime: number;
13
+ }
14
14
  }
@@ -3,18 +3,18 @@ import type { Handle } from "bosia";
3
3
  import { db } from "./features/drizzle";
4
4
 
5
5
  const dbHandle: Handle = async ({ event, resolve }) => {
6
- event.locals.db = db;
7
- return resolve(event);
6
+ event.locals.db = db;
7
+ return resolve(event);
8
8
  };
9
9
 
10
10
  const loggingHandle: Handle = async ({ event, resolve }) => {
11
- const start = Date.now();
12
- event.locals.requestTime = start;
13
- const res = await resolve(event);
14
- const ms = Date.now() - start;
15
- console.log(`[${event.request.method}] ${event.url.pathname} ${res.status} (${ms}ms)`);
16
- res.headers.set("X-Response-Time", `${ms}ms`);
17
- return res;
11
+ const start = Date.now();
12
+ event.locals.requestTime = start;
13
+ const res = await resolve(event);
14
+ const ms = Date.now() - start;
15
+ console.log(`[${event.request.method}] ${event.url.pathname} ${res.status} (${ms}ms)`);
16
+ res.headers.set("X-Response-Time", `${ms}ms`);
17
+ return res;
18
18
  };
19
19
 
20
20
  export const handle = sequence(dbHandle, loggingHandle);
@@ -1,15 +1,18 @@
1
1
  <script lang="ts">
2
- let { error }: { error: { status: number; message: string } } = $props();
2
+ let { error }: { error: { status: number; message: string } } = $props();
3
3
  </script>
4
4
 
5
5
  <svelte:head>
6
- <title>{error.status} — {error.message}</title>
6
+ <title>{error.status} — {error.message}</title>
7
7
  </svelte:head>
8
8
 
9
9
  <div class="min-h-screen flex flex-col items-center justify-center gap-4 text-center px-4">
10
- <p class="text-8xl font-bold text-gray-200">{error.status}</p>
11
- <p class="text-2xl font-semibold text-gray-700">{error.message}</p>
12
- <a href="/" class="mt-4 px-5 py-2 rounded-lg bg-gray-900 text-white text-sm hover:bg-gray-700 transition-colors">
13
- Go home
14
- </a>
10
+ <p class="text-8xl font-bold text-gray-200">{error.status}</p>
11
+ <p class="text-2xl font-semibold text-gray-700">{error.message}</p>
12
+ <a
13
+ href="/"
14
+ class="mt-4 px-5 py-2 rounded-lg bg-gray-900 text-white text-sm hover:bg-gray-700 transition-colors"
15
+ >
16
+ Go home
17
+ </a>
15
18
  </div>
@@ -1,8 +1,8 @@
1
1
  import type { LoadEvent } from "bosia";
2
2
 
3
3
  export async function load({ locals }: LoadEvent) {
4
- return {
5
- appName: "{{PROJECT_NAME}}",
6
- requestTime: locals.requestTime as number | null ?? null,
7
- };
4
+ return {
5
+ appName: "{{PROJECT_NAME}}",
6
+ requestTime: (locals.requestTime as number | null) ?? null,
7
+ };
8
8
  }
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
- import "../app.css";
3
- let { children }: { children: any } = $props();
2
+ import "../app.css";
3
+ let { children }: { children: any } = $props();
4
4
  </script>
5
5
 
6
6
  {@render children()}