@kuratchi/js 0.0.22 → 0.0.23

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.
@@ -136,7 +136,7 @@ export async function compile(options) {
136
136
  // Auto-discover convention-based worker class files (no config needed)
137
137
  const containerConfig = discoverContainerFiles(projectDir);
138
138
  const workflowConfig = discoverWorkflowFiles(projectDir);
139
- const agentConfig = discoverConventionClassFiles(projectDir, path.join('src', 'server'), '.agent.ts', '.agent');
139
+ const agentConfig = discoverConventionClassFiles(projectDir, path.join('src', 'server'), '.agents.ts', '.agents');
140
140
  // Generate handler proxy modules in .kuratchi/do/ (must happen BEFORE route processing
141
141
  // so that $durable-objects/X imports can be redirected to the generated proxies)
142
142
  const doProxyDir = path.join(projectDir, '.kuratchi', 'do');
@@ -301,12 +301,18 @@ export async function compile(options) {
301
301
  // routes.ts already exports the default fetch handler and all named DO classes;
302
302
  // worker.ts explicitly re-exports them so wrangler.jsonc can reference a
303
303
  // stable filename while routes.ts is freely regenerated.
304
+ // If user has src/index.ts with a default export, merge it with the generated worker
305
+ // to support scheduled, queue, and other Cloudflare Worker handlers.
306
+ const userIndexFile = path.join(srcDir, 'index.ts');
307
+ const hasUserIndex = fs.existsSync(userIndexFile) &&
308
+ fs.readFileSync(userIndexFile, 'utf-8').includes('export default');
304
309
  const workerFile = path.join(outDir, 'worker.ts');
305
310
  writeIfChanged(workerFile, buildWorkerEntrypointSource({
306
311
  projectDir,
307
312
  outDir,
308
313
  doClassNames: doConfig.map((entry) => entry.className),
309
314
  workerClassEntries: [...agentConfig, ...containerConfig, ...workflowConfig],
315
+ hasUserIndex,
310
316
  }));
311
317
  writeIfChanged(path.join(outDir, 'worker.js'), buildCompatEntrypointSource('./worker.ts'));
312
318
  // Auto-sync wrangler.jsonc with workflow/container/DO config from kuratchi.config.ts
@@ -323,12 +329,17 @@ export async function compile(options) {
323
329
  copyDirIfChanged(srcAssetsDir, publicAssetsDir);
324
330
  syncedAssetsDirectory = path.relative(projectDir, publicDir).replace(/\\/g, '/');
325
331
  }
332
+ // Convert agent config to DO config format (agents are Durable Objects)
333
+ const agentDoConfig = agentConfig.map((entry) => {
334
+ const binding = entry.className.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase();
335
+ return { binding, className: entry.className };
336
+ });
326
337
  syncWranglerConfigPipeline({
327
338
  projectDir,
328
339
  config: {
329
340
  workflows: workflowConfig,
330
341
  containers: containerConfig,
331
- durableObjects: doConfig,
342
+ durableObjects: [...doConfig, ...agentDoConfig],
332
343
  assetsDirectory: syncedAssetsDirectory,
333
344
  },
334
345
  writeFile: writeIfChanged,
@@ -10,5 +10,6 @@ export declare function buildWorkerEntrypointSource(opts: {
10
10
  outDir: string;
11
11
  doClassNames: string[];
12
12
  workerClassEntries: WorkerClassExportEntry[];
13
+ hasUserIndex?: boolean;
13
14
  }): string;
14
15
  export declare function buildCompatEntrypointSource(targetFile: string): string;
@@ -29,13 +29,18 @@ export function buildWorkerEntrypointSource(opts) {
29
29
  }
30
30
  return `export { ${entry.className} } from '${importPath}';`;
31
31
  });
32
- return [
32
+ const lines = [
33
33
  '// Auto-generated by kuratchi — do not edit.',
34
- "export { default } from './routes.ts';",
35
- ...opts.doClassNames.map((className) => `export { ${className} } from './routes.ts';`),
36
- ...workerClassExports,
37
- '',
38
- ].join('\n');
34
+ ];
35
+ // If user has src/index.ts with a default export, merge it with the generated fetch handler
36
+ if (opts.hasUserIndex) {
37
+ lines.push("import __generatedWorker from './routes.ts';", "import __userWorker from '../src/index.ts';", '', '// Merge user worker exports (scheduled, queue, etc.) with generated fetch handler', 'export default {', ' ...__userWorker,', ' fetch: __generatedWorker.fetch,', '};');
38
+ }
39
+ else {
40
+ lines.push("export { default } from './routes.ts';");
41
+ }
42
+ lines.push(...opts.doClassNames.map((className) => `export { ${className} } from './routes.ts';`), ...workerClassExports, '');
43
+ return lines.join('\n');
39
44
  }
40
45
  export function buildCompatEntrypointSource(targetFile) {
41
46
  return [
@@ -392,14 +392,22 @@ function __attachCookies(response) {
392
392
  const csrfCookie = getCsrfCookieHeader();
393
393
  const hasCookies = (cookies && cookies.length > 0) || csrfCookie;
394
394
  if (hasCookies) {
395
- const newResponse = new Response(response.body, response);
395
+ // Clone the response properly to avoid body stream issues with WARP/proxy layers.
396
+ // Using response.clone() ensures the body stream is properly duplicated.
397
+ const cloned = response.clone();
398
+ const newHeaders = new Headers(cloned.headers);
396
399
  if (cookies) {
397
400
  for (const header of cookies)
398
- newResponse.headers.append('Set-Cookie', header);
401
+ newHeaders.append('Set-Cookie', header);
399
402
  }
400
403
  if (csrfCookie) {
401
- newResponse.headers.append('Set-Cookie', csrfCookie);
404
+ newHeaders.append('Set-Cookie', csrfCookie);
402
405
  }
406
+ const newResponse = new Response(cloned.body, {
407
+ status: cloned.status,
408
+ statusText: cloned.statusText,
409
+ headers: newHeaders,
410
+ });
403
411
  return __secHeaders(newResponse);
404
412
  }
405
413
  return __secHeaders(response);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kuratchi/js",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "description": "A thin, Cloudflare Workers-native web framework with Svelte-inspired syntax",
5
5
  "license": "MIT",
6
6
  "type": "module",