@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 +4 -4
- package/dist/compiler/import-linking.js +1 -1
- package/dist/compiler/index.js +1 -1
- package/dist/compiler/root-layout-pipeline.js +11 -1
- package/dist/compiler/route-discovery.js +5 -5
- package/dist/compiler/route-pipeline.js +9 -1
- package/dist/compiler/routes-module-feature-blocks.js +6 -0
- package/dist/create.js +6 -6
- package/package.json +1 -1
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/
|
|
46
|
-
src/routes/items/
|
|
47
|
-
src/routes/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]/
|
|
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)
|
|
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
|
}
|
package/dist/compiler/index.js
CHANGED
|
@@ -220,7 +220,7 @@ export async function compile(options) {
|
|
|
220
220
|
}));
|
|
221
221
|
continue;
|
|
222
222
|
}
|
|
223
|
-
// -- Page route (
|
|
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){
|
|
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, '
|
|
29
|
+
const pageFile = path.join(dir, entry.name, 'index.html');
|
|
30
30
|
if (fs.existsSync(pageFile)) {
|
|
31
|
-
const routeFile = `${childPrefix}/
|
|
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 === '
|
|
60
|
-
const routeFile = prefix ? `${prefix}/
|
|
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 !== '
|
|
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
|
-
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
231
|
-
write(dir, 'src/routes/auth/signup/
|
|
232
|
-
write(dir, 'src/routes/admin/
|
|
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) {
|