bosbun 0.0.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 +163 -0
- package/package.json +56 -0
- package/src/cli/add.ts +83 -0
- package/src/cli/build.ts +16 -0
- package/src/cli/create.ts +54 -0
- package/src/cli/dev.ts +14 -0
- package/src/cli/feat.ts +80 -0
- package/src/cli/index.ts +75 -0
- package/src/cli/start.ts +28 -0
- package/src/core/build.ts +157 -0
- package/src/core/client/App.svelte +147 -0
- package/src/core/client/hydrate.ts +78 -0
- package/src/core/client/router.svelte.ts +46 -0
- package/src/core/cookies.ts +52 -0
- package/src/core/cors.ts +60 -0
- package/src/core/csrf.ts +65 -0
- package/src/core/dev.ts +193 -0
- package/src/core/env.ts +135 -0
- package/src/core/envCodegen.ts +94 -0
- package/src/core/errors.ts +23 -0
- package/src/core/hooks.ts +74 -0
- package/src/core/html.ts +170 -0
- package/src/core/matcher.ts +85 -0
- package/src/core/plugin.ts +59 -0
- package/src/core/prerender.ts +79 -0
- package/src/core/renderer.ts +222 -0
- package/src/core/routeFile.ts +88 -0
- package/src/core/routeTypes.ts +95 -0
- package/src/core/scanner.ts +99 -0
- package/src/core/server.ts +320 -0
- package/src/core/types.ts +37 -0
- package/src/lib/index.ts +19 -0
- package/src/lib/utils.ts +24 -0
- package/templates/default/.env.example +34 -0
- package/templates/default/README.md +102 -0
- package/templates/default/package.json +21 -0
- package/templates/default/public/.gitkeep +0 -0
- package/templates/default/src/app.css +132 -0
- package/templates/default/src/app.d.ts +7 -0
- package/templates/default/src/lib/.gitkeep +0 -0
- package/templates/default/src/routes/+error.svelte +18 -0
- package/templates/default/src/routes/+layout.svelte +6 -0
- package/templates/default/src/routes/+page.svelte +36 -0
- package/templates/default/src/routes/about/+page.server.ts +1 -0
- package/templates/default/src/routes/about/+page.svelte +8 -0
- package/templates/default/tsconfig.json +22 -0
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { clsx, type ClassValue } from "clsx";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
export function cn(...inputs: ClassValue[]) {
|
|
5
|
+
return twMerge(clsx(inputs));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function getServerTime() {
|
|
9
|
+
const now = new Date();
|
|
10
|
+
const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
11
|
+
|
|
12
|
+
// Get timezone offset in minutes and convert to ±HH:MM format
|
|
13
|
+
const offsetMinutes = -now.getTimezoneOffset();
|
|
14
|
+
const offsetHours = Math.floor(Math.abs(offsetMinutes) / 60);
|
|
15
|
+
const offsetMins = Math.abs(offsetMinutes) % 60;
|
|
16
|
+
const sign = offsetMinutes >= 0 ? '+' : '-';
|
|
17
|
+
const offsetStr = `${sign}${String(offsetHours).padStart(2, '0')}:${String(offsetMins).padStart(2, '0')}`;
|
|
18
|
+
|
|
19
|
+
// Convert UTC time to local time by adding the offset
|
|
20
|
+
const localTime = new Date(now.getTime() + offsetMinutes * 60 * 1000);
|
|
21
|
+
const timestamp = localTime.toISOString().slice(0, -1) + offsetStr;
|
|
22
|
+
|
|
23
|
+
return { timestamp, timezone: timeZone };
|
|
24
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# ─── Bunia Environment Variables ───────────────────────────────────────────────
|
|
2
|
+
#
|
|
3
|
+
# Copy this file to .env and fill in your values.
|
|
4
|
+
# .env.local overrides .env (gitignored — for local secrets).
|
|
5
|
+
# .env.development / .env.production for mode-specific values.
|
|
6
|
+
#
|
|
7
|
+
# Prefix convention:
|
|
8
|
+
#
|
|
9
|
+
# PUBLIC_STATIC_* Client + server, inlined at build time (e.g. app name)
|
|
10
|
+
# PUBLIC_* Client + server, injected at runtime via window.__BUNIA_ENV__
|
|
11
|
+
# STATIC_* Server only, inlined at build time
|
|
12
|
+
# (no prefix) Server only, read from process.env at runtime (secrets, DB creds)
|
|
13
|
+
#
|
|
14
|
+
# Import in your code:
|
|
15
|
+
# import { PUBLIC_STATIC_APP_NAME, DB_PASSWORD } from 'bunia:env';
|
|
16
|
+
#
|
|
17
|
+
# Framework vars (PORT, NODE_ENV, BODY_SIZE_LIMIT, CSRF_ALLOWED_ORIGINS) are
|
|
18
|
+
# NOT exposed via bunia:env — access them via process.env directly.
|
|
19
|
+
# ────────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
# Public build-time constant (safe to expose to client)
|
|
22
|
+
PUBLIC_STATIC_APP_NAME=My Bunia App
|
|
23
|
+
|
|
24
|
+
# Framework vars — access via process.env directly (not via bunia:env)
|
|
25
|
+
# PORT=9000
|
|
26
|
+
|
|
27
|
+
# Public runtime var (safe to expose to client, can change without rebuild)
|
|
28
|
+
# PUBLIC_API_URL=https://api.example.com
|
|
29
|
+
|
|
30
|
+
# Server-only build-time constant
|
|
31
|
+
# STATIC_DB_HOST=localhost
|
|
32
|
+
|
|
33
|
+
# Server-only runtime secret (never sent to client)
|
|
34
|
+
# DATABASE_URL=postgres://user:password@localhost:5432/mydb
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# {{PROJECT_NAME}}
|
|
2
|
+
|
|
3
|
+
A [Bunia](https://github.com/bosapi/bunia) project — SSR · Svelte 5 · Bun · ElysiaJS.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun run dev # start development server at http://localhost:9000
|
|
9
|
+
bun run build # build for production
|
|
10
|
+
bun run start # run the production server
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Project Structure
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
src/
|
|
17
|
+
├── app.css # Global styles and Tailwind design tokens
|
|
18
|
+
├── hooks.server.ts # Optional request middleware (auth, logging)
|
|
19
|
+
├── lib/ # Shared utilities — import via $lib
|
|
20
|
+
└── routes/ # Pages and API endpoints
|
|
21
|
+
├── +layout.svelte # Root layout
|
|
22
|
+
└── +page.svelte # Home page (/)
|
|
23
|
+
public/ # Static assets
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Routes
|
|
27
|
+
|
|
28
|
+
Add pages by creating `+page.svelte` files under `src/routes/`:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
src/routes/
|
|
32
|
+
├── +page.svelte # /
|
|
33
|
+
├── about/
|
|
34
|
+
│ └── +page.svelte # /about
|
|
35
|
+
└── blog/
|
|
36
|
+
├── +page.svelte # /blog
|
|
37
|
+
└── [slug]/
|
|
38
|
+
├── +page.server.ts # server loader
|
|
39
|
+
└── +page.svelte # /blog/:slug
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Server Loaders
|
|
43
|
+
|
|
44
|
+
Fetch data on the server before rendering:
|
|
45
|
+
|
|
46
|
+
```typescript
|
|
47
|
+
// src/routes/blog/[slug]/+page.server.ts
|
|
48
|
+
import type { LoadEvent } from "bunia";
|
|
49
|
+
|
|
50
|
+
export async function load({ params }: LoadEvent) {
|
|
51
|
+
return { post: await getPost(params.slug) };
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### API Endpoints
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// src/routes/api/hello/+server.ts
|
|
59
|
+
export function GET() {
|
|
60
|
+
return Response.json({ message: "hello" });
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Route Groups
|
|
65
|
+
|
|
66
|
+
Group routes under a shared layout without changing the URL:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
src/routes/
|
|
70
|
+
└── (app)/
|
|
71
|
+
├── +layout.svelte # shared layout for the group
|
|
72
|
+
└── dashboard/
|
|
73
|
+
└── +page.svelte # /dashboard
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Styling
|
|
77
|
+
|
|
78
|
+
`src/app.css` imports Tailwind v4 and defines shadcn-inspired design tokens. Use the semantic color classes anywhere:
|
|
79
|
+
|
|
80
|
+
```svelte
|
|
81
|
+
<div class="bg-background text-foreground">
|
|
82
|
+
<p class="text-muted-foreground">Muted text</p>
|
|
83
|
+
<button class="bg-primary text-primary-foreground">Click</button>
|
|
84
|
+
</div>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Dark mode is supported via the `.dark` class on any parent element.
|
|
88
|
+
|
|
89
|
+
## Utilities
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { cn } from "$lib/utils";
|
|
93
|
+
|
|
94
|
+
// Merges Tailwind classes safely
|
|
95
|
+
cn("px-4 py-2", isActive && "bg-primary")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Learn More
|
|
99
|
+
|
|
100
|
+
- [Bunia documentation](https://github.com/bosapi/bunia)
|
|
101
|
+
- [Svelte 5 docs](https://svelte.dev)
|
|
102
|
+
- [Tailwind CSS v4](https://tailwindcss.com)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"private": true,
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "bunia dev",
|
|
7
|
+
"build": "bunia build",
|
|
8
|
+
"start": "bunia start",
|
|
9
|
+
"check": "tsc --noEmit"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"bunia": "*",
|
|
13
|
+
"svelte": "^5.20.0",
|
|
14
|
+
"clsx": "^2.1.1",
|
|
15
|
+
"tailwind-merge": "^3.5.0"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/bun": "latest",
|
|
19
|
+
"typescript": "^5"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@source "../src";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* ─── shadcn-inspired Design Tokens ──────────────────────
|
|
6
|
+
* CSS custom properties for light & dark themes.
|
|
7
|
+
* Uses HSL values so Tailwind can apply opacity modifiers.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
@theme {
|
|
11
|
+
--color-background: hsl(var(--background));
|
|
12
|
+
--color-foreground: hsl(var(--foreground));
|
|
13
|
+
|
|
14
|
+
--color-card: hsl(var(--card));
|
|
15
|
+
--color-card-foreground: hsl(var(--card-foreground));
|
|
16
|
+
|
|
17
|
+
--color-popover: hsl(var(--popover));
|
|
18
|
+
--color-popover-foreground: hsl(var(--popover-foreground));
|
|
19
|
+
|
|
20
|
+
--color-primary: hsl(var(--primary));
|
|
21
|
+
--color-primary-foreground: hsl(var(--primary-foreground));
|
|
22
|
+
|
|
23
|
+
--color-secondary: hsl(var(--secondary));
|
|
24
|
+
--color-secondary-foreground: hsl(var(--secondary-foreground));
|
|
25
|
+
|
|
26
|
+
--color-muted: hsl(var(--muted));
|
|
27
|
+
--color-muted-foreground: hsl(var(--muted-foreground));
|
|
28
|
+
|
|
29
|
+
--color-accent: hsl(var(--accent));
|
|
30
|
+
--color-accent-foreground: hsl(var(--accent-foreground));
|
|
31
|
+
|
|
32
|
+
--color-destructive: hsl(var(--destructive));
|
|
33
|
+
--color-destructive-foreground: hsl(var(--destructive-foreground));
|
|
34
|
+
|
|
35
|
+
--color-border: hsl(var(--border));
|
|
36
|
+
--color-input: hsl(var(--input));
|
|
37
|
+
--color-ring: hsl(var(--ring));
|
|
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);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* ─── Light Theme (Default) ─────────────────────────────── */
|
|
46
|
+
|
|
47
|
+
:root {
|
|
48
|
+
--background: 0 0% 100%;
|
|
49
|
+
--foreground: 222.2 84% 4.9%;
|
|
50
|
+
|
|
51
|
+
--card: 0 0% 100%;
|
|
52
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
53
|
+
|
|
54
|
+
--popover: 0 0% 100%;
|
|
55
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
56
|
+
|
|
57
|
+
--primary: 222.2 47.4% 11.2%;
|
|
58
|
+
--primary-foreground: 210 40% 98%;
|
|
59
|
+
|
|
60
|
+
--secondary: 210 40% 96.1%;
|
|
61
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
62
|
+
|
|
63
|
+
--muted: 210 40% 96.1%;
|
|
64
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
65
|
+
|
|
66
|
+
--accent: 210 40% 96.1%;
|
|
67
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
68
|
+
|
|
69
|
+
--destructive: 0 84.2% 60.2%;
|
|
70
|
+
--destructive-foreground: 210 40% 98%;
|
|
71
|
+
|
|
72
|
+
--border: 214.3 31.8% 91.4%;
|
|
73
|
+
--input: 214.3 31.8% 91.4%;
|
|
74
|
+
--ring: 222.2 84% 4.9%;
|
|
75
|
+
|
|
76
|
+
--radius: 0.5rem;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* ─── Dark Theme ─────────────────────────────────────────── */
|
|
80
|
+
|
|
81
|
+
.dark {
|
|
82
|
+
--background: 222.2 84% 4.9%;
|
|
83
|
+
--foreground: 210 40% 98%;
|
|
84
|
+
|
|
85
|
+
--card: 222.2 84% 4.9%;
|
|
86
|
+
--card-foreground: 210 40% 98%;
|
|
87
|
+
|
|
88
|
+
--popover: 222.2 84% 4.9%;
|
|
89
|
+
--popover-foreground: 210 40% 98%;
|
|
90
|
+
|
|
91
|
+
--primary: 210 40% 98%;
|
|
92
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
93
|
+
|
|
94
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
95
|
+
--secondary-foreground: 210 40% 98%;
|
|
96
|
+
|
|
97
|
+
--muted: 217.2 32.6% 17.5%;
|
|
98
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
99
|
+
|
|
100
|
+
--accent: 217.2 32.6% 17.5%;
|
|
101
|
+
--accent-foreground: 210 40% 98%;
|
|
102
|
+
|
|
103
|
+
--destructive: 0 62.8% 30.6%;
|
|
104
|
+
--destructive-foreground: 210 40% 98%;
|
|
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%;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* ─── Base Styles ────────────────────────────────────────── */
|
|
112
|
+
|
|
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
|
+
}
|
|
132
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
let { data }: { data: { status: number; message: string } } = $props();
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<svelte:head>
|
|
6
|
+
<title>{data.status} — {data.message}</title>
|
|
7
|
+
</svelte:head>
|
|
8
|
+
|
|
9
|
+
<main class="flex min-h-screen flex-col items-center justify-center gap-4 text-center px-4">
|
|
10
|
+
<p class="text-8xl font-bold text-gray-200">{data.status}</p>
|
|
11
|
+
<p class="text-2xl font-semibold">{data.message}</p>
|
|
12
|
+
<a
|
|
13
|
+
href="/"
|
|
14
|
+
class="mt-4 rounded-md border px-4 py-2 text-sm hover:bg-muted transition-colors"
|
|
15
|
+
>
|
|
16
|
+
Go home
|
|
17
|
+
</a>
|
|
18
|
+
</main>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
const name = "{{PROJECT_NAME}}";
|
|
3
|
+
</script>
|
|
4
|
+
|
|
5
|
+
<main class="flex min-h-screen flex-col items-center justify-center gap-6 p-8">
|
|
6
|
+
<div class="flex flex-col items-center gap-3 text-center">
|
|
7
|
+
<p class="text-6xl">🐰</p>
|
|
8
|
+
<h1 class="text-4xl font-bold tracking-tight">{name}</h1>
|
|
9
|
+
<p class="text-muted-foreground text-lg">
|
|
10
|
+
A Bunia project — SSR + Svelte 5 + Bun + ElysiaJS
|
|
11
|
+
</p>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div class="mt-4 flex gap-3">
|
|
15
|
+
<a
|
|
16
|
+
href="https://github.com/bosapi/bunia"
|
|
17
|
+
target="_blank"
|
|
18
|
+
rel="noopener noreferrer"
|
|
19
|
+
class="bg-primary text-primary-foreground hover:bg-primary/90 rounded-md px-4 py-2 text-sm font-medium transition-colors"
|
|
20
|
+
>
|
|
21
|
+
Docs
|
|
22
|
+
</a>
|
|
23
|
+
<a
|
|
24
|
+
href="https://github.com/bosapi/bunia/tree/main/registry"
|
|
25
|
+
target="_blank"
|
|
26
|
+
rel="noopener noreferrer"
|
|
27
|
+
class="border-border bg-secondary text-secondary-foreground hover:bg-secondary/80 rounded-md border px-4 py-2 text-sm font-medium transition-colors"
|
|
28
|
+
>
|
|
29
|
+
Components
|
|
30
|
+
</a>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<p class="text-muted-foreground mt-6 text-sm">
|
|
34
|
+
Edit <code class="bg-muted rounded px-1 py-0.5 font-mono text-xs">src/routes/+page.svelte</code> to get started
|
|
35
|
+
</p>
|
|
36
|
+
</main>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const prerender = true;
|
|
@@ -0,0 +1,22 @@
|
|
|
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": [".", ".bunia/types"],
|
|
15
|
+
"paths": {
|
|
16
|
+
"$lib": ["./src/lib"],
|
|
17
|
+
"$lib/*": ["./src/lib/*"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"include": ["src/**/*"],
|
|
21
|
+
"exclude": ["node_modules", "dist"]
|
|
22
|
+
}
|