@kuratchi/js 0.0.18 → 0.0.19

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
@@ -42,9 +42,9 @@ For the framework's internal compiler/runtime orchestration and tracked implemen
42
42
  Place `.html` files inside `src/routes/`. The file path becomes the URL pattern.
43
43
 
44
44
  ```
45
- src/routes/page.html → /
46
- src/routes/items/page.html → /items
47
- src/routes/blog/[slug]/page.html → /blog/:slug
45
+ src/routes/index.html → /
46
+ src/routes/items/index.html → /items
47
+ src/routes/blog/[slug]/index.html → /blog/:slug
48
48
  src/routes/layout.html → shared layout wrapping all routes
49
49
  ```
50
50
 
@@ -277,7 +277,7 @@ Throw `PageError` from a route's load scope to return the correct HTTP error pag
277
277
  ```ts
278
278
  import { PageError } from '@kuratchi/js';
279
279
 
280
- // In src/routes/posts/[id]/page.html <script> block:
280
+ // In src/routes/posts/[id]/index.html <script> block:
281
281
  const post = await db.posts.findOne({ id: params.id });
282
282
  if (!post) throw new PageError(404);
283
283
  if (!post.isPublished && !currentUser?.isAdmin) throw new PageError(403);
@@ -120,7 +120,7 @@ export function linkRouteServerImports(opts) {
120
120
  continue;
121
121
  }
122
122
  fnToModule[binding.local] = moduleId;
123
- if (!routeImportDeclMap.has(binding.local) && !RESERVED_RENDER_VARS.has(binding.local)) {
123
+ if (!routeImportDeclMap.has(binding.local)) {
124
124
  const accessExpr = binding.imported === 'default' ? `${moduleId}.default` : `${moduleId}.${binding.imported}`;
125
125
  routeImportDeclMap.set(binding.local, `const ${binding.local} = ${accessExpr};`);
126
126
  }
@@ -220,7 +220,7 @@ export async function compile(options) {
220
220
  }));
221
221
  continue;
222
222
  }
223
- // -- Page route (page.html) --
223
+ // -- Page route (index.html) --
224
224
  const source = fileContents.get(fullPath) ?? fs.readFileSync(fullPath, 'utf-8');
225
225
  const parsed = parseFile(source, { kind: 'route', filePath: fullPath });
226
226
  const routeState = assembleRouteState({
@@ -354,8 +354,18 @@ const BRIDGE_SOURCE = `(function(){
354
354
  (function tick(){
355
355
  setTimeout(function(){
356
356
  fetch(location.pathname + location.search, { headers: { 'x-kuratchi-fragment': pollId } })
357
- .then(function(r){ return r.text(); })
357
+ .then(function(r){
358
+ if(r.status === 404){
359
+ // Fragment no longer exists (e.g., item completed and removed from list)
360
+ // Remove the element and stop polling
361
+ el.remove();
362
+ return null;
363
+ }
364
+ if(!r.ok) return null;
365
+ return r.text();
366
+ })
358
367
  .then(function(html){
368
+ if(html === null) return;
359
369
  if(prevHtml !== html){
360
370
  el.innerHTML = html;
361
371
  prevHtml = html;
@@ -26,9 +26,9 @@ export function discoverRoutes(routesDir) {
26
26
  for (const entry of entries) {
27
27
  if (entry.isDirectory()) {
28
28
  const childPrefix = prefix ? `${prefix}/${entry.name}` : entry.name;
29
- const pageFile = path.join(dir, entry.name, 'page.html');
29
+ const pageFile = path.join(dir, entry.name, 'index.html');
30
30
  if (fs.existsSync(pageFile)) {
31
- const routeFile = `${childPrefix}/page.html`;
31
+ const routeFile = `${childPrefix}/index.html`;
32
32
  if (!registered.has(routeFile)) {
33
33
  registered.add(routeFile);
34
34
  results.push({ file: routeFile, name: childPrefix, layouts: getLayoutsForPrefix(childPrefix), type: 'page' });
@@ -56,15 +56,15 @@ export function discoverRoutes(routesDir) {
56
56
  }
57
57
  continue;
58
58
  }
59
- if (entry.name === 'page.html') {
60
- const routeFile = prefix ? `${prefix}/page.html` : 'page.html';
59
+ if (entry.name === 'index.html') {
60
+ const routeFile = prefix ? `${prefix}/index.html` : 'index.html';
61
61
  if (!registered.has(routeFile)) {
62
62
  registered.add(routeFile);
63
63
  results.push({ file: routeFile, name: prefix || 'index', layouts: getLayoutsForPrefix(prefix), type: 'page' });
64
64
  }
65
65
  continue;
66
66
  }
67
- if (entry.name.endsWith('.html') && entry.name !== 'page.html') {
67
+ if (entry.name.endsWith('.html') && entry.name !== 'index.html') {
68
68
  const name = prefix
69
69
  ? `${prefix}/${entry.name.replace('.html', '')}`
70
70
  : entry.name.replace('.html', '');
@@ -94,10 +94,18 @@ export function analyzeRouteBuild(opts) {
94
94
  const routeImportDecls = routeImportDeclLines.join('\n');
95
95
  const importedBindingNames = new Set(Object.keys(fnToModule));
96
96
  const renderScopeActionNames = new Set(parsed.actionFunctions);
97
+ // Filter out params/breadcrumbs from render prelude since they come from data destructuring
98
+ const reservedRenderVars = new Set(['params', 'breadcrumbs']);
97
99
  const renderImportPrelude = routeImportDeclLines
98
100
  .filter((statement) => {
99
101
  const declaredName = extractDeclaredConstName(statement);
100
- return declaredName ? !renderScopeActionNames.has(declaredName) : true;
102
+ if (!declaredName)
103
+ return true;
104
+ if (renderScopeActionNames.has(declaredName))
105
+ return false;
106
+ if (reservedRenderVars.has(declaredName))
107
+ return false;
108
+ return true;
101
109
  })
102
110
  .join('\n');
103
111
  let scriptBody = '';
@@ -311,10 +311,12 @@ function buildWorkflowStatusRpc(opts) {
311
311
  const rpcLines = [];
312
312
  rpcLines.push(`\n// Workflow Status RPCs (auto-generated)`);
313
313
  rpcLines.push(`const __workflowStatusRpc = {`);
314
+ const rpcNames = [];
314
315
  for (const workflow of opts.workflowConfig) {
315
316
  const baseName = workflow.file.split('/').pop()?.replace(/\.workflow\.ts$/, '') || '';
316
317
  const camelName = baseName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
317
318
  const rpcName = `${camelName}WorkflowStatus`;
319
+ rpcNames.push(rpcName);
318
320
  rpcLines.push(` '${rpcName}': async (instanceId) => {`);
319
321
  rpcLines.push(` if (!instanceId) return { status: 'unknown', error: { name: 'Error', message: 'Missing instanceId' } };`);
320
322
  rpcLines.push(` try {`);
@@ -326,5 +328,9 @@ function buildWorkflowStatusRpc(opts) {
326
328
  rpcLines.push(` },`);
327
329
  }
328
330
  rpcLines.push(`};`);
331
+ // Export individual functions for use in route templates
332
+ for (const rpcName of rpcNames) {
333
+ rpcLines.push(`const ${rpcName} = __workflowStatusRpc['${rpcName}'];`);
334
+ }
329
335
  return rpcLines.join('\n');
330
336
  }
package/dist/create.js CHANGED
@@ -211,25 +211,25 @@ function scaffold(dir, opts) {
211
211
  write(dir, 'tsconfig.json', genTsConfig());
212
212
  write(dir, '.gitignore', genGitIgnore());
213
213
  write(dir, 'src/routes/layout.html', genLayout(opts));
214
- write(dir, 'src/routes/page.html', genLandingPage(opts));
214
+ write(dir, 'src/routes/index.html', genLandingPage(opts));
215
215
  if (orm) {
216
216
  write(dir, 'src/schemas/app.ts', genSchema(opts));
217
217
  write(dir, 'src/database/items.ts', genItemsCrud());
218
- write(dir, 'src/routes/items/page.html', genItemsPage());
218
+ write(dir, 'src/routes/items/index.html', genItemsPage());
219
219
  }
220
220
  if (enableDO) {
221
221
  write(dir, 'src/schemas/notes.ts', genNotesSchema());
222
222
  write(dir, 'src/server/notes.do.ts', genNotesDoHandler());
223
223
  write(dir, 'src/database/notes.ts', genNotesDb());
224
- write(dir, 'src/routes/notes/page.html', genNotesPage());
224
+ write(dir, 'src/routes/notes/index.html', genNotesPage());
225
225
  }
226
226
  if (auth) {
227
227
  write(dir, '.dev.vars', genDevVars());
228
228
  write(dir, 'src/database/auth.ts', genAuthFunctions());
229
229
  write(dir, 'src/database/admin.ts', genAdminLoader());
230
- write(dir, 'src/routes/auth/login/page.html', genLoginPage());
231
- write(dir, 'src/routes/auth/signup/page.html', genSignupPage());
232
- write(dir, 'src/routes/admin/page.html', genAdminPage());
230
+ write(dir, 'src/routes/auth/login/index.html', genLoginPage());
231
+ write(dir, 'src/routes/auth/signup/index.html', genSignupPage());
232
+ write(dir, 'src/routes/admin/index.html', genAdminPage());
233
233
  }
234
234
  }
235
235
  function write(dir, filePath, content) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kuratchi/js",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "description": "A thin, Cloudflare Workers-native web framework with Svelte-inspired syntax",
5
5
  "license": "MIT",
6
6
  "type": "module",