@kuratchi/js 0.0.1 → 0.0.3

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/dist/create.js CHANGED
@@ -14,10 +14,10 @@ function getFrameworkPackageName() {
14
14
  try {
15
15
  const raw = fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8');
16
16
  const parsed = JSON.parse(raw);
17
- return parsed.name || 'KuratchiJS';
17
+ return parsed.name || '@kuratchi/js';
18
18
  }
19
19
  catch {
20
- return 'KuratchiJS';
20
+ return '@kuratchi/js';
21
21
  }
22
22
  }
23
23
  // ── Prompt Helpers ──────────────────────────────────────────
@@ -43,6 +43,7 @@ function confirm(question, defaultYes = true) {
43
43
  }
44
44
  export async function create(projectName, flags = []) {
45
45
  const autoYes = flags.includes('--yes') || flags.includes('-y');
46
+ const forceDO = flags.includes('--do');
46
47
  console.log('\nâš¡ Create a new KuratchiJS project\n');
47
48
  // Project name
48
49
  const name = projectName || (autoYes ? 'my-kuratchi-app' : await ask('Project name', 'my-kuratchi-app'));
@@ -59,14 +60,20 @@ export async function create(projectName, flags = []) {
59
60
  // Feature selection
60
61
  const ui = autoYes ? true : await confirm('Include @kuratchi/ui theme?');
61
62
  const orm = autoYes ? true : await confirm('Include @kuratchi/orm with D1?');
62
- const auth = autoYes ? true : (orm ? await confirm('Include @kuratchi/auth (credentials login)?') : false);
63
- if (auth && !orm) {
63
+ const enableDO = forceDO || (autoYes ? false : await confirm('Include Durable Objects (SQLite-backed DO)?', false));
64
+ const effectiveOrm = orm || enableDO;
65
+ const auth = autoYes ? true : (effectiveOrm ? await confirm('Include @kuratchi/auth (credentials login)?') : false);
66
+ if (enableDO && !orm) {
67
+ console.log(' ℹ DO uses @kuratchi/orm internally — enabling ORM.');
68
+ }
69
+ if (auth && !effectiveOrm) {
64
70
  console.log(' ℹ Auth requires ORM — enabling ORM automatically');
65
71
  }
66
72
  console.log();
67
73
  console.log(` Project: ${name}`);
68
74
  console.log(` UI: ${ui ? '✓' : '—'}`);
69
- console.log(` ORM: ${orm ? '✓' : '—'}`);
75
+ console.log(` D1 ORM: ${orm ? '✓' : '—'}`);
76
+ console.log(` DO: ${enableDO ? '✓' : '—'}`);
70
77
  console.log(` Auth: ${auth ? '✓' : '—'}`);
71
78
  console.log();
72
79
  if (!autoYes) {
@@ -82,7 +89,7 @@ export async function create(projectName, flags = []) {
82
89
  const monorepoRoot = detectMonorepo(targetDir);
83
90
  const isMonorepo = !!monorepoRoot;
84
91
  // Scaffold files
85
- const opts = { name, ui, orm, auth, monorepo: isMonorepo, monorepoRoot, projectDir: targetDir };
92
+ const opts = { name, ui, orm, do: enableDO, auth, monorepo: isMonorepo, monorepoRoot, projectDir: targetDir };
86
93
  scaffold(targetDir, opts);
87
94
  // ── Post-scaffold setup ─────────────────────────────────────
88
95
  console.log();
@@ -118,7 +125,7 @@ export async function create(projectName, flags = []) {
118
125
  // 4. Build routes
119
126
  step('Building routes...');
120
127
  if (isMonorepo && monorepoRoot) {
121
- const cliPath = path.join(monorepoRoot, 'packages', 'KuratchiJS', 'src', 'cli.ts');
128
+ const cliPath = path.join(monorepoRoot, 'packages', 'kuratchi-js', 'src', 'cli.ts');
122
129
  if (fs.existsSync(cliPath)) {
123
130
  run(`bun run --bun ${cliPath} build`, targetDir);
124
131
  }
@@ -156,7 +163,7 @@ function detectMonorepo(targetDir) {
156
163
  // Walk up from target to find a workspace root with packages/kuratchi-js
157
164
  let dir = path.dirname(targetDir);
158
165
  for (let i = 0; i < 5; i++) {
159
- if (fs.existsSync(path.join(dir, 'packages', 'KuratchiJS', 'package.json'))) {
166
+ if (fs.existsSync(path.join(dir, 'packages', 'kuratchi-js', 'package.json'))) {
160
167
  return dir;
161
168
  }
162
169
  const parent = path.dirname(dir);
@@ -175,14 +182,21 @@ function patchWranglerDbId(dir, dbId) {
175
182
  // ── Scaffold ────────────────────────────────────────────────
176
183
  function scaffold(dir, opts) {
177
184
  const { name, ui, orm, auth } = opts;
185
+ const enableDO = opts.do;
178
186
  // Create directory structure
179
187
  const dirs = [
180
188
  '',
181
189
  'src',
182
190
  'src/routes',
183
191
  ];
192
+ if (orm || enableDO) {
193
+ dirs.push('src/schemas');
194
+ }
184
195
  if (orm) {
185
- dirs.push('src/database', 'src/schemas');
196
+ dirs.push('src/database');
197
+ }
198
+ if (enableDO) {
199
+ dirs.push('src/server', 'src/routes/notes');
186
200
  }
187
201
  if (auth) {
188
202
  dirs.push('src/routes/auth', 'src/routes/auth/login', 'src/routes/auth/signup', 'src/routes/admin');
@@ -196,7 +210,6 @@ function scaffold(dir, opts) {
196
210
  write(dir, 'kuratchi.config.ts', genConfig(opts));
197
211
  write(dir, 'tsconfig.json', genTsConfig());
198
212
  write(dir, '.gitignore', genGitIgnore());
199
- write(dir, 'src/index.ts', genWorkerEntry(opts));
200
213
  write(dir, 'src/routes/layout.html', genLayout(opts));
201
214
  write(dir, 'src/routes/page.html', genLandingPage(opts));
202
215
  if (orm) {
@@ -204,6 +217,12 @@ function scaffold(dir, opts) {
204
217
  write(dir, 'src/database/items.ts', genItemsCrud());
205
218
  write(dir, 'src/routes/items/page.html', genItemsPage());
206
219
  }
220
+ if (enableDO) {
221
+ write(dir, 'src/schemas/notes.ts', genNotesSchema());
222
+ write(dir, 'src/server/notes.do.ts', genNotesDoHandler());
223
+ write(dir, 'src/database/notes.ts', genNotesDb());
224
+ write(dir, 'src/routes/notes/page.html', genNotesPage());
225
+ }
207
226
  if (auth) {
208
227
  write(dir, '.dev.vars', genDevVars());
209
228
  write(dir, 'src/database/auth.ts', genAuthFunctions());
@@ -235,7 +254,7 @@ function genPackageJson(opts) {
235
254
  let devScript = 'kuratchi dev';
236
255
  let buildScript = 'kuratchi build';
237
256
  if (opts.monorepo && opts.monorepoRoot) {
238
- const cliAbs = path.join(opts.monorepoRoot, 'packages', 'KuratchiJS', 'src', 'cli.ts');
257
+ const cliAbs = path.join(opts.monorepoRoot, 'packages', 'kuratchi-js', 'src', 'cli.ts');
239
258
  const relCli = path.relative(opts.projectDir, cliAbs).replace(/\\/g, '/');
240
259
  devScript = `bun run --bun ${relCli} dev`;
241
260
  buildScript = `bun run --bun ${relCli} build`;
@@ -259,7 +278,7 @@ function genPackageJson(opts) {
259
278
  function genWrangler(opts) {
260
279
  const config = {
261
280
  name: opts.name,
262
- main: 'src/index.ts',
281
+ main: '.kuratchi/worker.js',
263
282
  compatibility_date: new Date().toISOString().split('T')[0],
264
283
  compatibility_flags: ['nodejs_compat'],
265
284
  };
@@ -272,6 +291,14 @@ function genWrangler(opts) {
272
291
  },
273
292
  ];
274
293
  }
294
+ if (opts.do) {
295
+ config.durable_objects = {
296
+ bindings: [{ name: 'NOTES_DO', class_name: 'NotesDO' }],
297
+ };
298
+ config.migrations = [
299
+ { tag: 'v1', new_sqlite_classes: ['NotesDO'] },
300
+ ];
301
+ }
275
302
  return JSON.stringify(config, null, 2) + '\n';
276
303
  }
277
304
  function genConfig(opts) {
@@ -280,7 +307,7 @@ function genConfig(opts) {
280
307
  if (opts.ui) {
281
308
  lines.push(`import { kuratchiUiConfig } from '@kuratchi/ui/adapter';`);
282
309
  }
283
- if (opts.orm) {
310
+ if (opts.orm || opts.do) {
284
311
  lines.push(`import { kuratchiOrmConfig } from '@kuratchi/orm/adapter';`);
285
312
  }
286
313
  if (opts.auth) {
@@ -289,6 +316,9 @@ function genConfig(opts) {
289
316
  if (opts.orm) {
290
317
  lines.push(`import { appSchema } from './src/schemas/app';`);
291
318
  }
319
+ if (opts.do) {
320
+ lines.push(`import { notesSchema } from './src/schemas/notes';`);
321
+ }
292
322
  lines.push('');
293
323
  lines.push('export default defineConfig({');
294
324
  // UI
@@ -297,14 +327,23 @@ function genConfig(opts) {
297
327
  lines.push(" theme: 'default',");
298
328
  lines.push(' }),');
299
329
  }
300
- // ORM
301
- if (opts.orm) {
330
+ // ORM (D1 + DO databases combined into a single kuratchiOrmConfig call)
331
+ if (opts.orm || opts.do) {
302
332
  lines.push(' orm: kuratchiOrmConfig({');
303
333
  lines.push(' databases: {');
304
- lines.push(' DB: { schema: appSchema },');
334
+ if (opts.orm)
335
+ lines.push(" DB: { schema: appSchema },");
336
+ if (opts.do)
337
+ lines.push(" NOTES_DO: { schema: notesSchema, type: 'do' },");
305
338
  lines.push(' }');
306
339
  lines.push(' }),');
307
340
  }
341
+ // Durable Objects
342
+ if (opts.do) {
343
+ lines.push(' durableObjects: {');
344
+ lines.push(" NOTES_DO: { className: 'NotesDO' },");
345
+ lines.push(' },');
346
+ }
308
347
  // Auth
309
348
  if (opts.auth) {
310
349
  lines.push(' auth: kuratchiAuthConfig({');
@@ -341,13 +380,112 @@ worker-configuration.d.ts
341
380
  dist/
342
381
  `;
343
382
  }
344
- function genWorkerEntry(opts) {
345
- return `export { default } from "../.kuratchi/routes.js";\n`;
383
+ // ── Durable Object templates ──────────────────────────────────────────────────
384
+ function genNotesSchema() {
385
+ return `import type { SchemaDsl } from '@kuratchi/orm';
386
+
387
+ export const notesSchema: SchemaDsl = {
388
+ name: 'notes',
389
+ version: 1,
390
+ tables: {
391
+ notes: {
392
+ id: 'integer primary key',
393
+ title: 'text not null',
394
+ created_at: 'text not null default now',
395
+ },
396
+ },
397
+ };
398
+
399
+ export interface Note {
400
+ id: number;
401
+ title: string;
402
+ created_at: string;
403
+ }
404
+ `;
405
+ }
406
+ function genNotesDoHandler() {
407
+ return `import { kuratchiDO } from '${FRAMEWORK_PACKAGE_NAME}';
408
+ import type { Note } from '../schemas/notes';
409
+
410
+ export default class NotesDO extends kuratchiDO {
411
+ static binding = 'NOTES_DO';
412
+
413
+ async getNotes(): Promise<Note[]> {
414
+ return (await this.db.notes.orderBy({ created_at: 'desc' }).many()).data ?? [];
415
+ }
416
+
417
+ async addNote(title: string): Promise<void> {
418
+ await this.db.notes.insert({ title });
419
+ }
420
+
421
+ async deleteNote(id: number): Promise<void> {
422
+ await this.db.notes.delete({ id });
423
+ }
424
+ }
425
+ `;
426
+ }
427
+ function genNotesDb() {
428
+ return `import { env } from 'cloudflare:workers';
429
+ import type { Note } from '../schemas/notes';
430
+
431
+ function getStub() {
432
+ return (env as any).NOTES_DO.get((env as any).NOTES_DO.idFromName('global'));
433
+ }
434
+
435
+ export async function getNotes(): Promise<Note[]> {
436
+ return getStub().getNotes();
437
+ }
438
+
439
+ export async function addNote(formData: FormData): Promise<void> {
440
+ const title = String(formData.get('title') || '').trim();
441
+ if (!title) throw new Error('Note is required');
442
+ await getStub().addNote(title);
443
+ }
444
+
445
+ export async function deleteNote(id: number): Promise<void> {
446
+ await getStub().deleteNote(Number(id));
447
+ }
448
+ `;
449
+ }
450
+ function genNotesPage() {
451
+ return `<script>
452
+ import { getNotes, addNote, deleteNote } from '$database/notes';
453
+
454
+ const notes = await getNotes();
455
+ </script>
456
+
457
+ <header>
458
+ <div>
459
+ <h1>Notes</h1>
460
+ <p>Backed by a Cloudflare Durable Object with SQLite storage</p>
461
+ </div>
462
+ </header>
463
+
464
+ <form action={addNote} method="POST">
465
+ <input type="text" name="title" placeholder="New note..." required />
466
+ <button type="submit">Add</button>
467
+ </form>
468
+
469
+ if (notes.length === 0) {
470
+ <p style="opacity: 0.6">No notes yet.</p>
471
+ } else {
472
+ <section>
473
+ for (const note of notes) {
474
+ <article>
475
+ <span>{note.title}</span>
476
+ <button data-action="deleteNote" data-args={JSON.stringify([note.id])}>Remove</button>
477
+ </article>
478
+ }
479
+ </section>
480
+ }
481
+ `;
346
482
  }
347
483
  function genLayout(opts) {
348
484
  const navLinks = [' <a href="/">Home</a>'];
349
485
  if (opts.orm)
350
486
  navLinks.push(' <a href="/items">Items</a>');
487
+ if (opts.do)
488
+ navLinks.push(' <a href="/notes">Notes (DO)</a>');
351
489
  if (opts.auth)
352
490
  navLinks.push(' <a href="/admin">Admin</a>');
353
491
  return `<!DOCTYPE html>
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  /**
2
- * KuratchiJS — Public API
2
+ * KuratchiJS - Public API
3
3
  *
4
4
  * A thin, Cloudflare Workers-native web framework with Svelte-inspired syntax.
5
5
  */
6
6
  export { createApp } from './runtime/app.js';
7
7
  export { defineConfig } from './runtime/config.js';
8
- export { getEnv, getCtx, getRequest, getLocals, getParams, getParam, redirect, goto, setBreadcrumbs, getBreadcrumbs, breadcrumbsHome, breadcrumbsPrev, breadcrumbsNext, breadcrumbsCurrent, buildDefaultBreadcrumbs, } from './runtime/context.js';
8
+ export { defineRuntime } from './runtime/runtime.js';
9
+ export { getCtx, getRequest, getLocals, getParams, getParam, redirect, goto, setBreadcrumbs, getBreadcrumbs, breadcrumbsHome, breadcrumbsPrev, breadcrumbsNext, breadcrumbsCurrent, buildDefaultBreadcrumbs, } from './runtime/context.js';
9
10
  export { kuratchiDO, doRpc } from './runtime/do.js';
10
11
  export { extractSubdomainSlug, extractSlugFromPrefix, matchContainerViewPath, rewriteProxyLocationHeader, buildContainerRequest, createContainerEnvVars, startContainer, proxyToContainer, handleContainerRouting, forwardJsonPostToContainerDO, matchSiteViewPath, buildSiteContainerRequest, createWpContainerEnvVars, startSiteContainer, proxyToSiteContainer, } from './runtime/containers.js';
11
- export type { AppConfig, kuratchiConfig, DatabaseConfig, AuthConfig, RouteContext, RouteModule } from './runtime/types.js';
12
+ export type { AppConfig, kuratchiConfig, DatabaseConfig, AuthConfig, RouteContext, RouteModule, RuntimeContext, RuntimeDefinition, RuntimeStep, RuntimeNext, RuntimeErrorResult, } from './runtime/types.js';
12
13
  export type { RpcOf } from './runtime/do.js';
13
14
  export { compile } from './compiler/index.js';
package/dist/index.js CHANGED
@@ -1,12 +1,13 @@
1
1
  /**
2
- * KuratchiJS — Public API
2
+ * KuratchiJS - Public API
3
3
  *
4
4
  * A thin, Cloudflare Workers-native web framework with Svelte-inspired syntax.
5
5
  */
6
6
  // Runtime
7
7
  export { createApp } from './runtime/app.js';
8
8
  export { defineConfig } from './runtime/config.js';
9
- export { getEnv, getCtx, getRequest, getLocals, getParams, getParam, redirect, goto, setBreadcrumbs, getBreadcrumbs, breadcrumbsHome, breadcrumbsPrev, breadcrumbsNext, breadcrumbsCurrent, buildDefaultBreadcrumbs, } from './runtime/context.js';
9
+ export { defineRuntime } from './runtime/runtime.js';
10
+ export { getCtx, getRequest, getLocals, getParams, getParam, redirect, goto, setBreadcrumbs, getBreadcrumbs, breadcrumbsHome, breadcrumbsPrev, breadcrumbsNext, breadcrumbsCurrent, buildDefaultBreadcrumbs, } from './runtime/context.js';
10
11
  export { kuratchiDO, doRpc } from './runtime/do.js';
11
12
  export { extractSubdomainSlug, extractSlugFromPrefix, matchContainerViewPath, rewriteProxyLocationHeader, buildContainerRequest, createContainerEnvVars, startContainer, proxyToContainer, handleContainerRouting, forwardJsonPostToContainerDO,
12
13
  // Compatibility aliases
@@ -14,13 +14,6 @@ export interface BreadcrumbItem {
14
14
  }
15
15
  /** Called by the framework at the start of each request */
16
16
  export declare function __setRequestContext(ctx: any, request: Request): void;
17
- /**
18
- * @deprecated Use `import { env } from 'cloudflare:workers'` instead.
19
- * Kept for backward compatibility — delegates to the native env import.
20
- */
21
- export declare function getEnv<T = any>(): T;
22
- /** @internal — called by compiler to stash env ref for getEnv() compat */
23
- export declare function __setEnvCompat(env: any): void;
24
17
  /** Get the execution context (waitUntil, passThroughOnException) */
25
18
  export declare function getCtx(): ExecutionContext;
26
19
  /** Get the current request */
@@ -22,17 +22,6 @@ export function __setRequestContext(ctx, request) {
22
22
  get locals() { return __locals; },
23
23
  };
24
24
  }
25
- /**
26
- * @deprecated Use `import { env } from 'cloudflare:workers'` instead.
27
- * Kept for backward compatibility — delegates to the native env import.
28
- */
29
- export function getEnv() {
30
- return globalThis.__cloudflare_env__;
31
- }
32
- /** @internal — called by compiler to stash env ref for getEnv() compat */
33
- export function __setEnvCompat(env) {
34
- globalThis.__cloudflare_env__ = env;
35
- }
36
25
  /** Get the execution context (waitUntil, passThroughOnException) */
37
26
  export function getCtx() {
38
27
  if (!__ctx)
@@ -1,8 +1,9 @@
1
1
  export { createApp } from './app.js';
2
2
  export { defineConfig } from './config.js';
3
+ export { defineRuntime } from './runtime.js';
3
4
  export { Router, filePathToPattern } from './router.js';
4
- export { getEnv, getCtx, getRequest, getLocals, getParams, getParam, redirect, goto, setBreadcrumbs, getBreadcrumbs, breadcrumbsHome, breadcrumbsPrev, breadcrumbsNext, breadcrumbsCurrent, buildDefaultBreadcrumbs, } from './context.js';
5
+ export { getCtx, getRequest, getLocals, getParams, getParam, redirect, goto, setBreadcrumbs, getBreadcrumbs, breadcrumbsHome, breadcrumbsPrev, breadcrumbsNext, breadcrumbsCurrent, buildDefaultBreadcrumbs, } from './context.js';
5
6
  export { kuratchiDO, doRpc } from './do.js';
6
7
  export { extractSubdomainSlug, extractSlugFromPrefix, matchContainerViewPath, rewriteProxyLocationHeader, buildContainerRequest, createContainerEnvVars, startContainer, proxyToContainer, handleContainerRouting, forwardJsonPostToContainerDO, matchSiteViewPath, buildSiteContainerRequest, createWpContainerEnvVars, startSiteContainer, proxyToSiteContainer, } from './containers.js';
7
- export type { AppConfig, Env, AuthConfig, RouteContext, RouteModule, LayoutModule } from './types.js';
8
+ export type { AppConfig, Env, AuthConfig, RouteContext, RouteModule, LayoutModule, RuntimeContext, RuntimeDefinition, RuntimeStep, RuntimeNext, RuntimeErrorResult, } from './types.js';
8
9
  export type { RpcOf } from './do.js';
@@ -1,7 +1,8 @@
1
1
  export { createApp } from './app.js';
2
2
  export { defineConfig } from './config.js';
3
+ export { defineRuntime } from './runtime.js';
3
4
  export { Router, filePathToPattern } from './router.js';
4
- export { getEnv, getCtx, getRequest, getLocals, getParams, getParam, redirect, goto, setBreadcrumbs, getBreadcrumbs, breadcrumbsHome, breadcrumbsPrev, breadcrumbsNext, breadcrumbsCurrent, buildDefaultBreadcrumbs, } from './context.js';
5
+ export { getCtx, getRequest, getLocals, getParams, getParam, redirect, goto, setBreadcrumbs, getBreadcrumbs, breadcrumbsHome, breadcrumbsPrev, breadcrumbsNext, breadcrumbsCurrent, buildDefaultBreadcrumbs, } from './context.js';
5
6
  export { kuratchiDO, doRpc } from './do.js';
6
7
  export { extractSubdomainSlug, extractSlugFromPrefix, matchContainerViewPath, rewriteProxyLocationHeader, buildContainerRequest, createContainerEnvVars, startContainer, proxyToContainer, handleContainerRouting, forwardJsonPostToContainerDO,
7
8
  // Compatibility aliases
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Runtime extension system
3
+ */
4
+ import type { Env, RuntimeDefinition } from './types.js';
5
+ export declare function defineRuntime<E extends Env = Env>(runtime: RuntimeDefinition<E>): RuntimeDefinition<E>;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Runtime extension system
3
+ */
4
+ export function defineRuntime(runtime) {
5
+ return runtime;
6
+ }
@@ -115,6 +115,20 @@ export interface kuratchiConfig<E extends Env = Env> {
115
115
  /** The user field path that identifies the DO stub (e.g. 'user.orgId') */
116
116
  stubId?: string;
117
117
  }>;
118
+ /** Container classes exported into the generated worker entry. */
119
+ containers?: Record<string, string | {
120
+ /** Relative path from project root. Must end in `.container.ts|js|mjs|cjs`. */
121
+ file: string;
122
+ /** Optional override; inferred from exported class in `file` when omitted. */
123
+ className?: string;
124
+ }>;
125
+ /** Workflow classes exported into the generated worker entry. */
126
+ workflows?: Record<string, string | {
127
+ /** Relative path from project root. Must end in `.workflow.ts|js|mjs|cjs`. */
128
+ file: string;
129
+ /** Optional override; inferred from exported class in `file` when omitted. */
130
+ className?: string;
131
+ }>;
118
132
  }
119
133
  /** Auth configuration for kuratchi.config.ts */
120
134
  export interface AuthConfig {
@@ -205,3 +219,21 @@ export interface AuthConfig {
205
219
  binding: string;
206
220
  };
207
221
  }
222
+ /** Runtime pipeline context - shared across runtime step handlers */
223
+ export interface RuntimeContext<E extends Env = Env> {
224
+ request: Request;
225
+ env: E;
226
+ ctx: ExecutionContext;
227
+ url: URL;
228
+ params: Record<string, string>;
229
+ locals: Record<string, any>;
230
+ }
231
+ export type RuntimeNext = () => Promise<Response>;
232
+ export type RuntimeErrorResult = Response | null | undefined | void;
233
+ export interface RuntimeStep<E extends Env = Env> {
234
+ request?: (ctx: RuntimeContext<E>, next: RuntimeNext) => Promise<Response> | Response;
235
+ route?: (ctx: RuntimeContext<E>, next: RuntimeNext) => Promise<Response> | Response;
236
+ response?: (ctx: RuntimeContext<E>, response: Response) => Promise<Response> | Response;
237
+ error?: (ctx: RuntimeContext<E>, error: unknown) => Promise<RuntimeErrorResult> | RuntimeErrorResult;
238
+ }
239
+ export type RuntimeDefinition<E extends Env = Env> = Record<string, RuntimeStep<E>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kuratchi/js",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "A thin, Cloudflare Workers-native web framework with Svelte-inspired syntax",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -43,8 +43,4 @@
43
43
  "@types/node": "^24.4.0",
44
44
  "typescript": "^5.8.0"
45
45
  }
46
- }
47
-
48
-
49
-
50
-
46
+ }