@kuratchi/js 0.0.8 → 0.0.10

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 CHANGED
@@ -23,7 +23,7 @@ bun run dev
23
23
  | File | Purpose |
24
24
  |---|---|
25
25
  | `.kuratchi/routes.js` | Compiled routes, actions, RPC handlers, and render functions |
26
- | `.kuratchi/worker.js` | Stable wrangler entry - re-exports the fetch handler and all Durable Object classes |
26
+ | `.kuratchi/worker.js` | Stable wrangler entry - re-exports the fetch handler plus all Durable Object and Agent classes |
27
27
  | `.kuratchi/do/*.js` | Generated Durable Object RPC proxy modules for `$durable-objects/*` imports |
28
28
 
29
29
  Point wrangler at the entry and you're done. **No `src/index.ts` needed.**
@@ -46,6 +46,18 @@ src/routes/blog/[slug]/page.html → /blog/:slug
46
46
  src/routes/layout.html → shared layout wrapping all routes
47
47
  ```
48
48
 
49
+ ### Execution model
50
+
51
+ Kuratchi routes are server-first.
52
+
53
+ - `src/routes` defines server-rendered route modules.
54
+ - Top-level route `<script>` blocks run on the server.
55
+ - Template expressions, `if`, and `for` blocks render on the server.
56
+ - `src/server` is for private server-only modules and reusable backend logic.
57
+ - Reactive `$:` code is the browser-only escape hatch.
58
+
59
+ Route files are not client files. They are server-rendered routes that can opt into small browser-side reactive behavior when needed.
60
+
49
61
  ### Route file structure
50
62
 
51
63
  ```html
@@ -64,6 +76,7 @@ src/routes/layout.html → shared layout wrapping all routes
64
76
  ```
65
77
 
66
78
  The `$database/` alias resolves to `src/database/`. You can use any path alias configured in your tsconfig.
79
+ Private server logic should live in `src/server/` and be imported into routes explicitly.
67
80
 
68
81
  ### Layout file
69
82
 
@@ -161,9 +174,11 @@ Block form is also supported:
161
174
  ```
162
175
 
163
176
  Notes:
164
- - This reactivity runs in browser scripts rendered in the template markup, not in the top server route `<script>` load/action block.
177
+ - Route files are server-rendered by default. `$:` is the only browser-side execution primitive in a route template.
178
+ - This reactivity runs in browser scripts rendered in the template markup, not in the top server route `<script>` block.
165
179
  - Object/array `let` bindings are proxy-backed automatically when `$:` is used.
166
180
  - `$: name = expr` works; when replacing proxy-backed values, the compiler preserves reactivity under the hood.
181
+ - You should not need `if (browser)` style guards in normal Kuratchi route code. If browser checks become necessary outside `$:`, the boundary is likely in the wrong place.
167
182
 
168
183
  ## Form actions
169
184
 
@@ -196,7 +211,7 @@ export async function addItem(formData: FormData): Promise<void> {
196
211
 
197
212
  ### Redirect after action
198
213
 
199
- Call `redirect()` inside an action to send the user to a different URL after the POST:
214
+ Call `redirect()` inside an action or `load()` to immediately exit and send the user to a different URL. `throw redirect()` also works, but is redundant because `redirect()` already throws:
200
215
 
201
216
  ```ts
202
217
  import { redirect } from '@kuratchi/js';
@@ -360,6 +375,7 @@ For Durable Objects, RPC is file-driven and automatic.
360
375
  - Put handler logic in a `.do.ts` file.
361
376
  - Exported functions in that file become RPC methods.
362
377
  - Import RPC methods from `$durable-objects/<file-name-without-.do>`.
378
+ - RPC methods are still server-side code. They are exposed intentionally by the framework runtime, not because route files are client-side.
363
379
 
364
380
  ```html
365
381
  <script>
@@ -454,6 +470,44 @@ Declare it in `kuratchi.config.ts` and in `wrangler.jsonc`. The compiler exports
454
470
  ]
455
471
  }
456
472
  ```
473
+
474
+ ## Agents
475
+
476
+ Kuratchi treats `src/server/**/*.agent.ts` as a first-class Worker export convention.
477
+
478
+ - Any `.agent.ts` file under `src/server/` is scanned during build.
479
+ - The file must export a class with either `export class MyAgent` or `export default class MyAgent`.
480
+ - The compiler re-exports that class from `.kuratchi/worker.js`, so Wrangler can bind it directly.
481
+ - `.agent.ts` files are not route modules and are not converted into `$durable-objects/*` RPC proxies.
482
+
483
+ ```ts
484
+ // src/server/ai/session.agent.ts
485
+ import { Agent } from 'agents';
486
+
487
+ export class SessionAgent extends Agent {
488
+ async onRequest() {
489
+ return Response.json({ ok: true });
490
+ }
491
+ }
492
+ ```
493
+
494
+ ```jsonc
495
+ // wrangler.jsonc
496
+ {
497
+ "durable_objects": {
498
+ "bindings": [{ "name": "AI_SESSION", "class_name": "SessionAgent" }]
499
+ },
500
+ "migrations": [
501
+ { "tag": "v1", "new_sqlite_classes": ["SessionAgent"] }
502
+ ]
503
+ }
504
+ ```
505
+
506
+ Failure and edge behavior:
507
+
508
+ - If a `.agent.ts` file does not export a class, the build fails.
509
+ - Kuratchi only auto-discovers `.agent.ts` files under `src/server/`.
510
+ - You still need Wrangler Durable Object bindings and migrations because Agents run as Durable Objects.
457
511
  ## Runtime APIs
458
512
 
459
513
  These are available anywhere in server-side route code:
@@ -465,11 +519,29 @@ import {
465
519
  getLocals, // mutable locals bag for the current request
466
520
  getParams, // URL params ({ slug: 'foo' })
467
521
  getParam, // getParam('slug')
468
- redirect, // redirect('/path', 302)
522
+ RedirectError, // redirect signal thrown by redirect()\r\n redirect, // redirect('/path', 302)\r\n goto, // same as redirect()
469
523
  goto, // same as redirect — alias
470
524
  } from '@kuratchi/js';
471
525
  ```
472
526
 
527
+ ### Request helpers
528
+
529
+ For a batteries-included request layer, import pre-parsed request state from `@kuratchi/js/request`:
530
+
531
+ ```ts
532
+ import { url, pathname, searchParams, slug } from '@kuratchi/js/request';
533
+
534
+ const page = pathname;
535
+ const tab = searchParams.get('tab');
536
+ const postSlug = slug;
537
+ ```
538
+
539
+ - `url` is the parsed `URL` for the current request.
540
+ - `pathname` is the full path, like `/blog/hello-world`.
541
+ - `searchParams` is `url.searchParams` for the current request.
542
+ - `slug` is `params.slug` when the matched route defines a `slug` param.
543
+ - `headers`, `method`, and `params` are also exported from `@kuratchi/js/request`.
544
+ - Use `getRequest()` when you want the raw native `Request` object.
473
545
  ## Environment bindings
474
546
 
475
547
  Cloudflare env is server-only.
@@ -497,6 +569,24 @@ import { env } from 'cloudflare:workers';
497
569
  const result = await env.DB.prepare('SELECT 1').run();
498
570
  ```
499
571
 
572
+ ## Framework environment
573
+
574
+ Kuratchi also exposes a framework build-mode flag:
575
+
576
+ ```html
577
+ <script>
578
+ import { dev } from '@kuratchi/js/environment';
579
+ import { env } from 'cloudflare:workers';
580
+
581
+ const turnstileSiteKey = dev ? '' : (env.TURNSTILE_SITE_KEY || '');
582
+ </script>
583
+ ```
584
+
585
+ - `dev` is `true` for Kuratchi development builds
586
+ - `dev` is `false` for production builds
587
+ - `dev` is compile-time framework state, not a generic process env var
588
+ - `@kuratchi/js/environment` is intended for server route code, not client `$:` scripts
589
+
500
590
  ## `kuratchi.config.ts`
501
591
 
502
592
  Optional. Required only when using framework integrations or Durable Objects.
package/dist/cli.js CHANGED
@@ -123,11 +123,19 @@ async function startWranglerDev() {
123
123
  wranglerArgs.push('--port', String(port));
124
124
  console.log(`[kuratchi] Starting wrangler dev on port ${port}`);
125
125
  }
126
- const wrangler = spawn('npx', wranglerArgs, {
127
- cwd: projectDir,
128
- stdio: 'inherit',
129
- shell: process.platform === 'win32',
130
- });
126
+ // Use 'pipe' for stdin so wrangler doesn't detect stdin EOF and exit
127
+ // prematurely when launched via a script runner (e.g. `bun run dev`).
128
+ const isWin = process.platform === 'win32';
129
+ const wrangler = isWin
130
+ ? spawn('npx ' + wranglerArgs.join(' '), {
131
+ cwd: projectDir,
132
+ stdio: ['pipe', 'inherit', 'inherit'],
133
+ shell: true,
134
+ })
135
+ : spawn('npx', wranglerArgs, {
136
+ cwd: projectDir,
137
+ stdio: ['pipe', 'inherit', 'inherit'],
138
+ });
131
139
  const cleanup = () => {
132
140
  if (!wrangler.killed)
133
141
  wrangler.kill();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Compiler â€" scans a project's routes/ directory, parses .html files,
2
+ * Compiler " scans a project's routes/ directory, parses .html files,
3
3
  * and generates a single Worker entry point.
4
4
  */
5
5
  export { parseFile } from './parser.js';
@@ -27,9 +27,9 @@ export interface CompiledRoute {
27
27
  /**
28
28
  * Compile a project's src/routes/ into .kuratchi/routes.js
29
29
  *
30
- * The generated module exports { app } â€" an object with a fetch() method
30
+ * The generated module exports { app } " an object with a fetch() method
31
31
  * that handles routing, load functions, form actions, and rendering.
32
- * Returns the path to .kuratchi/worker.js the stable wrangler entry point that
32
+ * Returns the path to .kuratchi/worker.js the stable wrangler entry point that
33
33
  * re-exports everything from routes.js (default fetch handler + named DO class exports).
34
34
  * No src/index.ts is needed in user projects.
35
35
  */