kilatjs 0.1.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.
- package/LICENSE +21 -0
- package/README.md +438 -0
- package/dist/adapters/htmx.d.ts +71 -0
- package/dist/adapters/react.d.ts +7 -0
- package/dist/cli.d.ts +2 -0
- package/dist/core/router.d.ts +36 -0
- package/dist/core/types.d.ts +74 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +1046 -0
- package/dist/server/server.d.ts +17 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 KilatJS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
# KilatJS
|
|
2
|
+
|
|
3
|
+
**A Bun-native, HTML-first framework that renders real pages, treats UI frameworks as renderers, and makes SEO the defaultβnot a feature.**
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="https://img.shields.io/badge/runtime-Bun-F9F1E1?style=flat-square&logo=bun" alt="Bun Runtime">
|
|
7
|
+
<img src="https://img.shields.io/badge/rendering-SSR%20Only-10B981?style=flat-square" alt="SSR Only">
|
|
8
|
+
<img src="https://img.shields.io/badge/SEO-Guaranteed-8B5CF6?style=flat-square" alt="SEO Guaranteed">
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## π― What is KilatJS?
|
|
14
|
+
|
|
15
|
+
KilatJS is a server-first web framework inspired by the simplicity of PHP and the power of modern component libraries. It rejects the complexity of SPAs, hydration, and client-side routing in favor of **real HTML rendered on the server**.
|
|
16
|
+
|
|
17
|
+
**π₯ Powered by Bun's Native APIs - No Abstractions, Pure Performance:**
|
|
18
|
+
- π **Bun.FileSystemRouter** - Zero-config file-based routing at native speed
|
|
19
|
+
- β‘ **Bun.serve()** - HTTP/2 server with built-in WebSocket support
|
|
20
|
+
- π§ **Bun.file()** - Streaming file operations with automatic MIME detection
|
|
21
|
+
- π¦ **Bun.build()** - Native TypeScript/JSX bundling (no Webpack/Vite needed)
|
|
22
|
+
- π **Bun.spawn()** - Process management for build tools and external commands
|
|
23
|
+
- πΎ **Bun.write()** - Optimized file writing with atomic operations
|
|
24
|
+
- π **Bun.glob()** - Pattern matching for static site generation
|
|
25
|
+
|
|
26
|
+
### One-Line Positioning
|
|
27
|
+
|
|
28
|
+
> **"Request β Load β Render HTML β Response. That's it."**
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## π₯ Why Bun Native?
|
|
33
|
+
|
|
34
|
+
KilatJS leverages Bun's runtime directly instead of abstracting it away:
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
// Direct Bun.FileSystemRouter usage
|
|
38
|
+
const router = new Bun.FileSystemRouter({
|
|
39
|
+
style: "nextjs",
|
|
40
|
+
dir: "./routes"
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Native Bun.serve() with streaming
|
|
44
|
+
export default {
|
|
45
|
+
port: 3000,
|
|
46
|
+
fetch: async (request) => {
|
|
47
|
+
// Zero-copy request handling
|
|
48
|
+
return new Response(Bun.file("./static/index.html"));
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// Built-in TypeScript compilation
|
|
53
|
+
const result = await Bun.build({
|
|
54
|
+
entrypoints: ["./src/index.tsx"],
|
|
55
|
+
outdir: "./dist",
|
|
56
|
+
target: "bun"
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Performance Benefits:**
|
|
61
|
+
- β‘ **3x faster** cold starts vs Node.js frameworks
|
|
62
|
+
- π **Native TypeScript** - no transpilation overhead
|
|
63
|
+
- πΎ **Zero-copy streaming** for static files
|
|
64
|
+
- π§ **Built-in bundling** eliminates build tool complexity
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## β
Core Principles
|
|
69
|
+
|
|
70
|
+
1. **HTML is the protocol** β Every response is complete, semantic HTML
|
|
71
|
+
2. **Server owns all truth** β No client-side state management nightmares
|
|
72
|
+
3. **Every meaningful change = HTTP request** β Forms, mutations, navigation
|
|
73
|
+
4. **UI frameworks render, never orchestrate** β React/Solid/Vue for templating only
|
|
74
|
+
5. **JavaScript is optional, not required** β Sites work without JS
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## β Strict Non-Goals
|
|
79
|
+
|
|
80
|
+
KilatJS intentionally avoids:
|
|
81
|
+
|
|
82
|
+
- β Client-Side Rendering (CSR)
|
|
83
|
+
- β Hydration / Islands architecture
|
|
84
|
+
- β Client-side routing
|
|
85
|
+
- β Framework hooks (`useLoaderData`, `useRoute`, etc.)
|
|
86
|
+
- β Middleware chains
|
|
87
|
+
- β Dependency injection
|
|
88
|
+
- β SPA build assumptions
|
|
89
|
+
- β Vite as a hard dependency
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## π Quick Start
|
|
94
|
+
|
|
95
|
+
### 1. Install dependencies
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
bun install
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 2. Run the example
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
bun run dev
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Visit [http://localhost:3000](http://localhost:3000) to see the example site.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## π Project Structure
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
kilatjs/
|
|
115
|
+
βββ src/
|
|
116
|
+
β βββ index.ts # Main entry point
|
|
117
|
+
β βββ core/
|
|
118
|
+
β β βββ router.ts # File-based router
|
|
119
|
+
β β βββ types.ts # TypeScript types
|
|
120
|
+
β βββ adapters/
|
|
121
|
+
β β βββ react.ts # React SSR adapter
|
|
122
|
+
β βββ server/
|
|
123
|
+
β βββ server.ts # Bun HTTP server
|
|
124
|
+
βββ example/
|
|
125
|
+
β βββ server.ts # Example server entry
|
|
126
|
+
β βββ build.ts # Static build script
|
|
127
|
+
β βββ styles.css # CSS styles
|
|
128
|
+
β βββ components/
|
|
129
|
+
β β βββ Layout.tsx # Shared layout
|
|
130
|
+
β βββ routes/
|
|
131
|
+
β βββ index.tsx # Home page
|
|
132
|
+
β βββ about.tsx # About page
|
|
133
|
+
β βββ contact.tsx # Contact form
|
|
134
|
+
β βββ contact/
|
|
135
|
+
β β βββ success.tsx
|
|
136
|
+
β βββ blog/
|
|
137
|
+
β βββ index.tsx # Blog listing
|
|
138
|
+
β βββ [slug].tsx # Dynamic blog posts
|
|
139
|
+
βββ README.md
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## π Route Contract
|
|
145
|
+
|
|
146
|
+
Each route file may export **at most**:
|
|
147
|
+
|
|
148
|
+
```tsx
|
|
149
|
+
// Rendering mode: "static" (build-time) or "ssr" (request-time)
|
|
150
|
+
export const mode = "ssr";
|
|
151
|
+
|
|
152
|
+
// UI framework: "react" | "solid" | "vue" (default: react)
|
|
153
|
+
export const ui = "react";
|
|
154
|
+
|
|
155
|
+
// SEO meta tags
|
|
156
|
+
export const meta = {
|
|
157
|
+
title: "Page Title",
|
|
158
|
+
description: "Page description for SEO",
|
|
159
|
+
robots: "index,follow",
|
|
160
|
+
ogTitle: "Open Graph Title",
|
|
161
|
+
ogDescription: "Open Graph description",
|
|
162
|
+
ogImage: "https://example.com/image.jpg"
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// For static generation of dynamic routes
|
|
166
|
+
export function getStaticPaths() {
|
|
167
|
+
return ["/blog/post-1", "/blog/post-2"];
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Server-only data loading
|
|
171
|
+
export async function load(ctx) {
|
|
172
|
+
const data = await fetchFromDatabase();
|
|
173
|
+
return { posts: data };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// HTTP action handlers
|
|
177
|
+
export async function POST(ctx) {
|
|
178
|
+
const formData = await ctx.request.formData();
|
|
179
|
+
// Process form...
|
|
180
|
+
return Response.redirect("/success", 302);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Pure render function
|
|
184
|
+
export default function Page({ data, params, state }) {
|
|
185
|
+
return <div>{data.posts.map(p => <h2>{p.title}</h2>)}</div>;
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## π Actions (PRG Pattern)
|
|
192
|
+
|
|
193
|
+
All meaningful state changes happen via HTTP requests:
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
// routes/contact.tsx
|
|
197
|
+
export async function POST({ request }) {
|
|
198
|
+
const formData = await request.formData();
|
|
199
|
+
const email = formData.get("email");
|
|
200
|
+
|
|
201
|
+
await saveToDatabase({ email });
|
|
202
|
+
|
|
203
|
+
// PRG: Post-Redirect-Get pattern
|
|
204
|
+
return Response.redirect("/contact/success", 302);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export default function ContactPage() {
|
|
208
|
+
return (
|
|
209
|
+
<form method="POST" action="/contact">
|
|
210
|
+
<input type="email" name="email" required />
|
|
211
|
+
<button type="submit">Subscribe</button>
|
|
212
|
+
</form>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
**No JavaScript required.** Forms work natively.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## π¨ Styling (Tailwind-Ready)
|
|
222
|
+
|
|
223
|
+
KilatJS supports Tailwind CSS via CLI (no Vite required):
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
# Generate CSS
|
|
227
|
+
npx tailwindcss -i ./input.css -o ./styles.css --watch
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Configure in your `kilat.config.ts`:
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
import { createKilat } from 'kilatjs';
|
|
234
|
+
|
|
235
|
+
createKilat({
|
|
236
|
+
routesDir: "./routes",
|
|
237
|
+
tailwind: {
|
|
238
|
+
enabled: true,
|
|
239
|
+
cssPath: "./styles.css"
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## π Rendering Modes
|
|
247
|
+
|
|
248
|
+
### Static Generation
|
|
249
|
+
|
|
250
|
+
- Build-time HTML
|
|
251
|
+
- Best for SEO & caching
|
|
252
|
+
- Requires explicit path enumeration for dynamic routes
|
|
253
|
+
|
|
254
|
+
```tsx
|
|
255
|
+
export const mode = "static";
|
|
256
|
+
|
|
257
|
+
export function getStaticPaths() {
|
|
258
|
+
return ["/blog/post-1", "/blog/post-2"];
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Server-Side Rendering (SSR)
|
|
263
|
+
|
|
264
|
+
- Request-time HTML
|
|
265
|
+
- PHP-style execution
|
|
266
|
+
- Infinite routes allowed
|
|
267
|
+
|
|
268
|
+
```tsx
|
|
269
|
+
export const mode = "ssr"; // or omit (default)
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## π Authentication
|
|
275
|
+
|
|
276
|
+
Identity is proven **per request** via cookies/headers:
|
|
277
|
+
|
|
278
|
+
```tsx
|
|
279
|
+
export async function load({ request }) {
|
|
280
|
+
const session = await getSession(request.headers.get("cookie"));
|
|
281
|
+
|
|
282
|
+
if (!session) {
|
|
283
|
+
throw Response.redirect("/login");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return { user: session.user };
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
- Never trust localStorage for auth
|
|
291
|
+
- Server validates every request
|
|
292
|
+
- Cookies are the source of truth
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## π Running Your App
|
|
297
|
+
|
|
298
|
+
### Development
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
// Named import
|
|
302
|
+
import { createKilat } from 'kilatjs';
|
|
303
|
+
|
|
304
|
+
// Or default import
|
|
305
|
+
import Kilat from 'kilatjs';
|
|
306
|
+
|
|
307
|
+
const server = createKilat({
|
|
308
|
+
routesDir: "./routes",
|
|
309
|
+
port: 3000,
|
|
310
|
+
dev: true,
|
|
311
|
+
tailwind: {
|
|
312
|
+
enabled: false,
|
|
313
|
+
cssPath: "./styles.css"
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
server.start();
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Static Build
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
import { buildStatic } from 'kilatjs';
|
|
324
|
+
|
|
325
|
+
buildStatic({
|
|
326
|
+
routesDir: "./routes",
|
|
327
|
+
outDir: "./dist"
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## π§© UI Framework Support
|
|
334
|
+
|
|
335
|
+
| Framework | Status | Notes |
|
|
336
|
+
|-----------|--------|-------|
|
|
337
|
+
| React | β
Default | Full SSR support |
|
|
338
|
+
| Solid | π§ Planned | Coming soon |
|
|
339
|
+
| Vue | π§ Planned | Coming soon |
|
|
340
|
+
|
|
341
|
+
**Rule:** One renderer per route. No mixing.
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## π― SEO Guarantee
|
|
346
|
+
|
|
347
|
+
> **If a route exists, it is SEO-friendly.**
|
|
348
|
+
|
|
349
|
+
Because:
|
|
350
|
+
- HTML is always complete
|
|
351
|
+
- `<head>` is server-rendered
|
|
352
|
+
- No JS required for content
|
|
353
|
+
- Meta tags are first-class
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## π Philosophy
|
|
358
|
+
|
|
359
|
+
KilatJS rejects modern web complexity:
|
|
360
|
+
|
|
361
|
+
| We Don't Do | We Do |
|
|
362
|
+
|-------------|-------|
|
|
363
|
+
| Client-side rendering | Server-rendered HTML |
|
|
364
|
+
| Hydration/Islands | Static markup |
|
|
365
|
+
| Client-side router | HTTP navigation |
|
|
366
|
+
| Framework hooks | Props from loader |
|
|
367
|
+
| State sync | HTTP mutations |
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## π οΈ API Reference
|
|
372
|
+
|
|
373
|
+
### `createKilat(config)`
|
|
374
|
+
|
|
375
|
+
Creates a Kilat server instance.
|
|
376
|
+
|
|
377
|
+
```ts
|
|
378
|
+
interface KilatConfig {
|
|
379
|
+
routesDir: string; // Path to routes directory
|
|
380
|
+
outDir: string; // Output for static builds
|
|
381
|
+
port?: number; // Server port (default: 3000)
|
|
382
|
+
hostname?: string; // Server hostname (default: "localhost")
|
|
383
|
+
dev?: boolean; // Development mode
|
|
384
|
+
publicDir?: string; // Static assets directory
|
|
385
|
+
tailwind?: {
|
|
386
|
+
enabled: boolean;
|
|
387
|
+
cssPath: string;
|
|
388
|
+
configPath?: string;
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### `RouteContext`
|
|
394
|
+
|
|
395
|
+
Passed to `load()` and action handlers:
|
|
396
|
+
|
|
397
|
+
```ts
|
|
398
|
+
interface RouteContext {
|
|
399
|
+
request: Request; // Web Request object
|
|
400
|
+
params: Record<string, string>; // URL parameters
|
|
401
|
+
query: URLSearchParams; // Query string
|
|
402
|
+
state: ServerGlobalState; // Request-scoped state
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### `PageProps`
|
|
407
|
+
|
|
408
|
+
Passed to page components:
|
|
409
|
+
|
|
410
|
+
```ts
|
|
411
|
+
interface PageProps {
|
|
412
|
+
data: any; // From load()
|
|
413
|
+
params: Record<string, string>; // URL parameters
|
|
414
|
+
state: ServerGlobalState; // Request-scoped state
|
|
415
|
+
}
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
## π License
|
|
421
|
+
|
|
422
|
+
MIT
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
## π€ Contributing
|
|
427
|
+
|
|
428
|
+
KilatJS is in early development. Contributions welcome!
|
|
429
|
+
|
|
430
|
+
1. Fork the repository
|
|
431
|
+
2. Create a feature branch
|
|
432
|
+
3. Submit a pull request
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
<p align="center">
|
|
437
|
+
<strong>Built with π for the real web using Bun's native APIs.</strong>
|
|
438
|
+
</p>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { PageProps, RouteMeta, KilatConfig } from "../core/types";
|
|
2
|
+
/**
|
|
3
|
+
* HTMX Adapter - For building HTMX-enhanced HTML pages
|
|
4
|
+
* Provides utilities for generating HTMX-compatible responses and partial updates
|
|
5
|
+
*/
|
|
6
|
+
export declare class HTMXAdapter {
|
|
7
|
+
/**
|
|
8
|
+
* Render a template function to HTML string
|
|
9
|
+
*/
|
|
10
|
+
static renderToString(template: (props: PageProps) => string | Promise<string>, props: PageProps): Promise<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Check if the request is an HTMX request
|
|
13
|
+
*/
|
|
14
|
+
static isHTMXRequest(request: Request): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Check if this is a boosted request (HTMX boost attribute)
|
|
17
|
+
*/
|
|
18
|
+
static isBoostedRequest(request: Request): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Get the current URL before the HTMX request was made
|
|
21
|
+
*/
|
|
22
|
+
static getCurrentUrl(request: Request): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Get the ID of the element that triggered the request
|
|
25
|
+
*/
|
|
26
|
+
static getTrigger(request: Request): string | null;
|
|
27
|
+
/**
|
|
28
|
+
* Get the name of the element that triggered the request
|
|
29
|
+
*/
|
|
30
|
+
static getTriggerName(request: Request): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Get the ID of the target element
|
|
33
|
+
*/
|
|
34
|
+
static getTarget(request: Request): string | null;
|
|
35
|
+
/**
|
|
36
|
+
* Create a response with HTMX-specific headers
|
|
37
|
+
*/
|
|
38
|
+
static createResponse(html: string, options?: HTMXResponseOptions): Response;
|
|
39
|
+
/**
|
|
40
|
+
* Create a response that signals client-side redirect
|
|
41
|
+
*/
|
|
42
|
+
static redirectResponse(url: string): Response;
|
|
43
|
+
/**
|
|
44
|
+
* Create a response that triggers a full page refresh
|
|
45
|
+
*/
|
|
46
|
+
static refreshResponse(): Response;
|
|
47
|
+
static createDocument(html: string, meta?: RouteMeta, config?: KilatConfig): string;
|
|
48
|
+
private static escapeHtml;
|
|
49
|
+
}
|
|
50
|
+
export interface HTMXResponseOptions {
|
|
51
|
+
/** CSS selector to retarget the response to */
|
|
52
|
+
retarget?: string;
|
|
53
|
+
/** Swap method: innerHTML, outerHTML, beforeend, afterend, etc */
|
|
54
|
+
reswap?: string;
|
|
55
|
+
/** JSON string or event name to trigger on client */
|
|
56
|
+
trigger?: string;
|
|
57
|
+
/** Event to trigger after content settles */
|
|
58
|
+
triggerAfterSettle?: string;
|
|
59
|
+
/** Event to trigger after swap */
|
|
60
|
+
triggerAfterSwap?: string;
|
|
61
|
+
/** URL to redirect client to */
|
|
62
|
+
redirect?: string;
|
|
63
|
+
/** Whether to trigger a full page refresh */
|
|
64
|
+
refresh?: boolean;
|
|
65
|
+
/** URL to push into browser history */
|
|
66
|
+
pushUrl?: string;
|
|
67
|
+
/** URL to replace in browser history */
|
|
68
|
+
replaceUrl?: string;
|
|
69
|
+
/** HTTP status code */
|
|
70
|
+
status?: number;
|
|
71
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { PageProps, RouteMeta, KilatConfig } from "../core/types";
|
|
3
|
+
export declare class ReactAdapter {
|
|
4
|
+
static renderToString(component: React.ComponentType<PageProps>, props: PageProps): Promise<string>;
|
|
5
|
+
static createDocument(html: string, meta?: RouteMeta, config?: KilatConfig): string;
|
|
6
|
+
private static escapeHtml;
|
|
7
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { RouteMatch, KilatConfig } from "./types";
|
|
2
|
+
export declare class Router {
|
|
3
|
+
private routes;
|
|
4
|
+
private config;
|
|
5
|
+
private staticPaths;
|
|
6
|
+
private serverId;
|
|
7
|
+
private fsRouter;
|
|
8
|
+
private routeCache;
|
|
9
|
+
private preloadedRoutes;
|
|
10
|
+
private routePatterns;
|
|
11
|
+
private apiRoutes;
|
|
12
|
+
private staticApiResponses;
|
|
13
|
+
private static readonly NOT_FOUND_RESPONSE;
|
|
14
|
+
private static readonly METHOD_NOT_ALLOWED_RESPONSE;
|
|
15
|
+
private static readonly INTERNAL_ERROR_RESPONSE;
|
|
16
|
+
private contextPool;
|
|
17
|
+
private poolIndex;
|
|
18
|
+
constructor(config: KilatConfig);
|
|
19
|
+
getRoutes(): Map<string, any>;
|
|
20
|
+
getStaticPaths(): Map<string, string[]>;
|
|
21
|
+
loadRoutes(): Promise<void>;
|
|
22
|
+
private preloadAllRoutes;
|
|
23
|
+
private scanAndPreloadRoutes;
|
|
24
|
+
private createRoutePattern;
|
|
25
|
+
private getRouteType;
|
|
26
|
+
matchRoute(path: string): RouteMatch | null;
|
|
27
|
+
private pathMatchesPattern;
|
|
28
|
+
handleRequest(request: Request): Promise<Response>;
|
|
29
|
+
private handleApiRouteFast;
|
|
30
|
+
private getContextFromPool;
|
|
31
|
+
private returnContextToPool;
|
|
32
|
+
private getMinimalApiContext;
|
|
33
|
+
private handleStaticFile;
|
|
34
|
+
private create404Response;
|
|
35
|
+
private renderPage;
|
|
36
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route rendering modes:
|
|
3
|
+
* - "static": Pre-built at build time (SSG) - for known, unchanging paths
|
|
4
|
+
* - "ssr": Server-rendered on each request - for dynamic content
|
|
5
|
+
* - "api": Pure server handler, no HTML rendering - for API endpoints
|
|
6
|
+
*/
|
|
7
|
+
export type RenderMode = "static" | "ssr" | "api";
|
|
8
|
+
export type UIFramework = "react" | "htmx";
|
|
9
|
+
/**
|
|
10
|
+
* Route type classification for build/runtime decisions:
|
|
11
|
+
* - "static": Routes without dynamic segments, built at compile time
|
|
12
|
+
* - "dynamic": Routes with [param] segments, rendered at runtime
|
|
13
|
+
* - "api": Routes under /api/*, server-only handlers
|
|
14
|
+
*/
|
|
15
|
+
export type RouteType = "static" | "dynamic" | "api";
|
|
16
|
+
export interface RouteMeta {
|
|
17
|
+
title?: string;
|
|
18
|
+
description?: string;
|
|
19
|
+
robots?: string;
|
|
20
|
+
canonical?: string;
|
|
21
|
+
ogTitle?: string;
|
|
22
|
+
ogDescription?: string;
|
|
23
|
+
ogImage?: string;
|
|
24
|
+
twitterCard?: "summary" | "summary_large_image";
|
|
25
|
+
[key: string]: any;
|
|
26
|
+
}
|
|
27
|
+
export interface RouteContext {
|
|
28
|
+
request: Request;
|
|
29
|
+
params: Record<string, string>;
|
|
30
|
+
query: URLSearchParams;
|
|
31
|
+
state: ServerGlobalState;
|
|
32
|
+
}
|
|
33
|
+
export interface ServerGlobalState {
|
|
34
|
+
[key: string]: any;
|
|
35
|
+
}
|
|
36
|
+
export interface RouteExports {
|
|
37
|
+
mode?: RenderMode;
|
|
38
|
+
ui?: UIFramework;
|
|
39
|
+
load?: (ctx: RouteContext) => Promise<any> | any;
|
|
40
|
+
meta?: RouteMeta;
|
|
41
|
+
getStaticPaths?: () => Promise<string[]> | string[];
|
|
42
|
+
POST?: (ctx: RouteContext) => Promise<Response> | Response;
|
|
43
|
+
PUT?: (ctx: RouteContext) => Promise<Response> | Response;
|
|
44
|
+
DELETE?: (ctx: RouteContext) => Promise<Response> | Response;
|
|
45
|
+
PATCH?: (ctx: RouteContext) => Promise<Response> | Response;
|
|
46
|
+
default: (props: PageProps) => any;
|
|
47
|
+
}
|
|
48
|
+
export interface PageProps {
|
|
49
|
+
data: any;
|
|
50
|
+
params: Record<string, string>;
|
|
51
|
+
state: ServerGlobalState;
|
|
52
|
+
}
|
|
53
|
+
export interface RouteMatch {
|
|
54
|
+
route: string;
|
|
55
|
+
params: Record<string, string>;
|
|
56
|
+
exports: RouteExports;
|
|
57
|
+
routeType: RouteType;
|
|
58
|
+
}
|
|
59
|
+
export interface TailwindConfig {
|
|
60
|
+
enabled: boolean;
|
|
61
|
+
inputPath?: string;
|
|
62
|
+
cssPath: string;
|
|
63
|
+
configPath?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface KilatConfig {
|
|
66
|
+
routesDir: string;
|
|
67
|
+
outDir: string;
|
|
68
|
+
port?: number;
|
|
69
|
+
hostname?: string;
|
|
70
|
+
dev?: boolean;
|
|
71
|
+
publicDir?: string;
|
|
72
|
+
tailwind?: TailwindConfig;
|
|
73
|
+
}
|
|
74
|
+
export type LoaderData<T extends (...args: any) => any> = Awaited<ReturnType<T>>;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export { Router } from "./core/router";
|
|
2
|
+
export { KilatServer } from "./server/server";
|
|
3
|
+
export { ReactAdapter } from "./adapters/react";
|
|
4
|
+
export { HTMXAdapter, type HTMXResponseOptions } from "./adapters/htmx";
|
|
5
|
+
export * from "./core/types";
|
|
6
|
+
import { KilatServer } from "./server/server";
|
|
7
|
+
import { KilatConfig } from "./core/types";
|
|
8
|
+
/**
|
|
9
|
+
* Default configuration for KilatJS
|
|
10
|
+
*/
|
|
11
|
+
export declare const defaultConfig: KilatConfig;
|
|
12
|
+
/**
|
|
13
|
+
* Create a Kilat instance with custom configuration
|
|
14
|
+
*/
|
|
15
|
+
export declare function createKilat(config?: Partial<KilatConfig>): KilatServer;
|
|
16
|
+
/**
|
|
17
|
+
* Start the development server
|
|
18
|
+
*/
|
|
19
|
+
export declare function startDevServer(config?: Partial<KilatConfig>): Promise<Bun.Server<undefined>>;
|
|
20
|
+
/**
|
|
21
|
+
* Build static site
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildStatic(config?: Partial<KilatConfig>): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Define a route loader with type inference
|
|
26
|
+
*/
|
|
27
|
+
export declare function defineLoader<T>(loader: (ctx: import("./core/types").RouteContext) => Promise<T> | T): (ctx: import("./core/types").RouteContext) => Promise<T> | T;
|
|
28
|
+
/**
|
|
29
|
+
* Define configuration with type inference
|
|
30
|
+
*/
|
|
31
|
+
export declare function defineConfig(config: Partial<KilatConfig>): Partial<KilatConfig>;
|
|
32
|
+
/**
|
|
33
|
+
* Define route meta with type inference
|
|
34
|
+
*/
|
|
35
|
+
export declare function defineMeta(meta: import("./core/types").RouteMeta): import("./core/types").RouteMeta;
|
|
36
|
+
declare const Kilat: {
|
|
37
|
+
createKilat: typeof createKilat;
|
|
38
|
+
startDevServer: typeof startDevServer;
|
|
39
|
+
buildStatic: typeof buildStatic;
|
|
40
|
+
defineConfig: typeof defineConfig;
|
|
41
|
+
defineLoader: typeof defineLoader;
|
|
42
|
+
defineMeta: typeof defineMeta;
|
|
43
|
+
defaultConfig: KilatConfig;
|
|
44
|
+
};
|
|
45
|
+
export default Kilat;
|