bosia 0.2.3 → 0.3.1
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/README.md +39 -39
- package/package.json +56 -54
- package/src/ambient.d.ts +31 -0
- package/src/cli/add.ts +120 -114
- package/src/cli/build.ts +10 -10
- package/src/cli/create.ts +142 -137
- package/src/cli/dev.ts +7 -9
- package/src/cli/feat.ts +266 -258
- package/src/cli/index.ts +51 -42
- package/src/cli/registry.ts +136 -115
- package/src/cli/start.ts +17 -17
- package/src/cli/test.ts +25 -0
- package/src/core/build.ts +72 -56
- package/src/core/client/App.svelte +177 -156
- package/src/core/client/appState.svelte.ts +33 -31
- package/src/core/client/enhance.ts +83 -78
- package/src/core/client/hydrate.ts +95 -81
- package/src/core/client/prefetch.ts +101 -94
- package/src/core/client/router.svelte.ts +64 -51
- package/src/core/cookies.ts +70 -66
- package/src/core/cors.ts +44 -35
- package/src/core/csrf.ts +38 -38
- package/src/core/dedup.ts +17 -17
- package/src/core/dev.ts +196 -168
- package/src/core/env.ts +160 -148
- package/src/core/envCodegen.ts +73 -73
- package/src/core/errors.ts +48 -49
- package/src/core/hooks.ts +50 -50
- package/src/core/html.ts +184 -145
- package/src/core/matcher.ts +130 -121
- package/src/core/paths.ts +8 -10
- package/src/core/plugin.ts +113 -107
- package/src/core/prerender.ts +191 -122
- package/src/core/renderer.ts +359 -286
- package/src/core/routeFile.ts +140 -127
- package/src/core/routeTypes.ts +144 -83
- package/src/core/scanner.ts +125 -95
- package/src/core/server.ts +538 -424
- package/src/core/types.ts +25 -20
- package/src/lib/index.ts +8 -8
- package/src/lib/utils.ts +44 -30
- package/templates/default/.prettierignore +5 -0
- package/templates/default/.prettierrc.json +9 -0
- package/templates/default/README.md +5 -5
- package/templates/default/package.json +22 -18
- package/templates/default/src/app.css +80 -80
- package/templates/default/src/app.d.ts +3 -3
- package/templates/default/src/routes/+error.svelte +7 -10
- package/templates/default/src/routes/+layout.svelte +2 -2
- package/templates/default/src/routes/+page.svelte +30 -32
- package/templates/default/src/routes/about/+page.svelte +3 -3
- package/templates/default/tsconfig.json +20 -20
- package/templates/demo/.prettierignore +5 -0
- package/templates/demo/.prettierrc.json +9 -0
- package/templates/demo/README.md +9 -9
- package/templates/demo/package.json +22 -17
- package/templates/demo/src/app.css +80 -80
- package/templates/demo/src/app.d.ts +3 -3
- package/templates/demo/src/hooks.server.ts +9 -9
- package/templates/demo/src/routes/(public)/+layout.svelte +45 -23
- package/templates/demo/src/routes/(public)/+page.svelte +96 -67
- package/templates/demo/src/routes/(public)/about/+page.svelte +13 -25
- package/templates/demo/src/routes/(public)/all/[...catchall]/+page.svelte +24 -28
- package/templates/demo/src/routes/(public)/blog/+page.svelte +55 -46
- package/templates/demo/src/routes/(public)/blog/[slug]/+page.server.ts +36 -38
- package/templates/demo/src/routes/(public)/blog/[slug]/+page.svelte +60 -42
- package/templates/demo/src/routes/+error.svelte +10 -7
- package/templates/demo/src/routes/+layout.server.ts +4 -4
- package/templates/demo/src/routes/+layout.svelte +2 -2
- package/templates/demo/src/routes/actions-test/+page.server.ts +16 -16
- package/templates/demo/src/routes/actions-test/+page.svelte +49 -49
- package/templates/demo/src/routes/api/hello/+server.ts +25 -25
- package/templates/demo/tsconfig.json +20 -20
- package/templates/todo/.prettierignore +5 -0
- package/templates/todo/.prettierrc.json +9 -0
- package/templates/todo/README.md +9 -9
- package/templates/todo/package.json +22 -17
- package/templates/todo/src/app.css +80 -80
- package/templates/todo/src/app.d.ts +7 -7
- package/templates/todo/src/hooks.server.ts +9 -9
- package/templates/todo/src/routes/+error.svelte +10 -7
- package/templates/todo/src/routes/+layout.server.ts +4 -4
- package/templates/todo/src/routes/+layout.svelte +2 -2
- package/templates/todo/src/routes/+page.svelte +44 -44
- package/templates/todo/template.json +1 -1
- package/templates/todo/tsconfig.json +20 -20
|
@@ -1,60 +1,60 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
7
|
+
<h1 class="text-2xl font-bold mb-4">{data.greeting}</h1>
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
17
|
-
|
|
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
|
-
|
|
22
|
-
|
|
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
|
-
|
|
27
|
-
|
|
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
|
-
|
|
31
|
+
return Response.json({ method: "DELETE", deleted: true, params, locals });
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export function OPTIONS() {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
}
|
package/templates/todo/README.md
CHANGED
|
@@ -27,16 +27,16 @@ Visit [http://localhost:9000](http://localhost:9000) to see the app.
|
|
|
27
27
|
|
|
28
28
|
## Scripts
|
|
29
29
|
|
|
30
|
-
| Command
|
|
31
|
-
|
|
32
|
-
| `bun x bosia dev`
|
|
33
|
-
| `bun x bosia build`
|
|
34
|
-
| `bun x bosia start`
|
|
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`
|
|
37
|
-
| `bun run db:push`
|
|
38
|
-
| `bun run db:studio`
|
|
39
|
-
| `bun run db:seed`
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
12
|
-
|
|
11
|
+
--color-background: hsl(var(--background));
|
|
12
|
+
--color-foreground: hsl(var(--foreground));
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
--color-card: hsl(var(--card));
|
|
15
|
+
--color-card-foreground: hsl(var(--card-foreground));
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
--color-popover: hsl(var(--popover));
|
|
18
|
+
--color-popover-foreground: hsl(var(--popover-foreground));
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
--color-primary: hsl(var(--primary));
|
|
21
|
+
--color-primary-foreground: hsl(var(--primary-foreground));
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
--color-secondary: hsl(var(--secondary));
|
|
24
|
+
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
--color-muted: hsl(var(--muted));
|
|
27
|
+
--color-muted-foreground: hsl(var(--muted-foreground));
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
--color-accent: hsl(var(--accent));
|
|
30
|
+
--color-accent-foreground: hsl(var(--accent-foreground));
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
--color-destructive: hsl(var(--destructive));
|
|
33
|
+
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
--color-border: hsl(var(--border));
|
|
36
|
+
--color-input: hsl(var(--input));
|
|
37
|
+
--color-ring: hsl(var(--ring));
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
49
|
-
|
|
48
|
+
--background: 0 0% 100%;
|
|
49
|
+
--foreground: 222.2 84% 4.9%;
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
--card: 0 0% 100%;
|
|
52
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
--popover: 0 0% 100%;
|
|
55
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
--primary: 222.2 47.4% 11.2%;
|
|
58
|
+
--primary-foreground: 210 40% 98%;
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
--secondary: 210 40% 96.1%;
|
|
61
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
--muted: 210 40% 96.1%;
|
|
64
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
--accent: 210 40% 96.1%;
|
|
67
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
--destructive: 0 84.2% 60.2%;
|
|
70
|
+
--destructive-foreground: 210 40% 98%;
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
76
|
+
--radius: 0.5rem;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/* ─── Dark Theme ─────────────────────────────────────────── */
|
|
80
80
|
|
|
81
81
|
.dark {
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
--background: 222.2 84% 4.9%;
|
|
83
|
+
--foreground: 210 40% 98%;
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
--card: 222.2 84% 4.9%;
|
|
86
|
+
--card-foreground: 210 40% 98%;
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
--popover: 222.2 84% 4.9%;
|
|
89
|
+
--popover-foreground: 210 40% 98%;
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
--primary: 210 40% 98%;
|
|
92
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
93
93
|
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
95
|
+
--secondary-foreground: 210 40% 98%;
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
--muted: 217.2 32.6% 17.5%;
|
|
98
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
--accent: 217.2 32.6% 17.5%;
|
|
101
|
+
--accent-foreground: 210 40% 98%;
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
--destructive: 0 62.8% 30.6%;
|
|
104
|
+
--destructive-foreground: 210 40% 98%;
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
7
|
-
|
|
6
|
+
event.locals.db = db;
|
|
7
|
+
return resolve(event);
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
const loggingHandle: Handle = async ({ event, resolve }) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
2
|
+
let { error }: { error: { status: number; message: string } } = $props();
|
|
3
3
|
</script>
|
|
4
4
|
|
|
5
5
|
<svelte:head>
|
|
6
|
-
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
return {
|
|
5
|
+
appName: "Bosia Todo",
|
|
6
|
+
requestTime: (locals.requestTime as number | null) ?? null,
|
|
7
|
+
};
|
|
8
8
|
}
|