@kuratchi/js 0.0.14 → 0.0.16

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.
Files changed (65) hide show
  1. package/README.md +135 -68
  2. package/dist/cli.js +80 -47
  3. package/dist/compiler/api-route-pipeline.d.ts +8 -0
  4. package/dist/compiler/api-route-pipeline.js +23 -0
  5. package/dist/compiler/asset-pipeline.d.ts +7 -0
  6. package/dist/compiler/asset-pipeline.js +33 -0
  7. package/dist/compiler/client-module-pipeline.d.ts +25 -0
  8. package/dist/compiler/client-module-pipeline.js +257 -0
  9. package/dist/compiler/compiler-shared.d.ts +55 -0
  10. package/dist/compiler/compiler-shared.js +4 -0
  11. package/dist/compiler/component-pipeline.d.ts +15 -0
  12. package/dist/compiler/component-pipeline.js +163 -0
  13. package/dist/compiler/config-reading.d.ts +11 -0
  14. package/dist/compiler/config-reading.js +323 -0
  15. package/dist/compiler/convention-discovery.d.ts +9 -0
  16. package/dist/compiler/convention-discovery.js +83 -0
  17. package/dist/compiler/durable-object-pipeline.d.ts +9 -0
  18. package/dist/compiler/durable-object-pipeline.js +255 -0
  19. package/dist/compiler/error-page-pipeline.d.ts +1 -0
  20. package/dist/compiler/error-page-pipeline.js +16 -0
  21. package/dist/compiler/import-linking.d.ts +36 -0
  22. package/dist/compiler/import-linking.js +139 -0
  23. package/dist/compiler/index.d.ts +3 -3
  24. package/dist/compiler/index.js +137 -3265
  25. package/dist/compiler/layout-pipeline.d.ts +31 -0
  26. package/dist/compiler/layout-pipeline.js +155 -0
  27. package/dist/compiler/page-route-pipeline.d.ts +16 -0
  28. package/dist/compiler/page-route-pipeline.js +62 -0
  29. package/dist/compiler/parser.d.ts +4 -0
  30. package/dist/compiler/parser.js +433 -51
  31. package/dist/compiler/root-layout-pipeline.d.ts +10 -0
  32. package/dist/compiler/root-layout-pipeline.js +517 -0
  33. package/dist/compiler/route-discovery.d.ts +7 -0
  34. package/dist/compiler/route-discovery.js +87 -0
  35. package/dist/compiler/route-pipeline.d.ts +57 -0
  36. package/dist/compiler/route-pipeline.js +296 -0
  37. package/dist/compiler/route-state-pipeline.d.ts +25 -0
  38. package/dist/compiler/route-state-pipeline.js +139 -0
  39. package/dist/compiler/routes-module-feature-blocks.d.ts +2 -0
  40. package/dist/compiler/routes-module-feature-blocks.js +330 -0
  41. package/dist/compiler/routes-module-pipeline.d.ts +2 -0
  42. package/dist/compiler/routes-module-pipeline.js +6 -0
  43. package/dist/compiler/routes-module-runtime-shell.d.ts +2 -0
  44. package/dist/compiler/routes-module-runtime-shell.js +81 -0
  45. package/dist/compiler/routes-module-types.d.ts +44 -0
  46. package/dist/compiler/routes-module-types.js +1 -0
  47. package/dist/compiler/script-transform.d.ts +16 -0
  48. package/dist/compiler/script-transform.js +218 -0
  49. package/dist/compiler/server-module-pipeline.d.ts +13 -0
  50. package/dist/compiler/server-module-pipeline.js +124 -0
  51. package/dist/compiler/template.d.ts +13 -1
  52. package/dist/compiler/template.js +323 -60
  53. package/dist/compiler/worker-output-pipeline.d.ts +13 -0
  54. package/dist/compiler/worker-output-pipeline.js +37 -0
  55. package/dist/compiler/wrangler-sync.d.ts +14 -0
  56. package/dist/compiler/wrangler-sync.js +185 -0
  57. package/dist/runtime/app.js +15 -3
  58. package/dist/runtime/generated-worker.d.ts +33 -0
  59. package/dist/runtime/generated-worker.js +412 -0
  60. package/dist/runtime/index.d.ts +2 -1
  61. package/dist/runtime/index.js +1 -0
  62. package/dist/runtime/router.d.ts +2 -1
  63. package/dist/runtime/router.js +12 -3
  64. package/dist/runtime/types.d.ts +8 -2
  65. package/package.json +5 -1
@@ -0,0 +1,330 @@
1
+ import * as path from 'node:path';
2
+ import { toSafeIdentifier } from './compiler-shared.js';
3
+ export function buildRoutesModuleFeatureBlocks(opts) {
4
+ const workerImport = `import { env as __env } from 'cloudflare:workers';`;
5
+ const contextImport = `import { __setRequestContext, __esc, __rawHtml, __sanitizeHtml, __setLocal, __getLocals, buildDefaultBreadcrumbs as __buildDefaultBreadcrumbs } from '${opts.runtimeContextImport}';`;
6
+ const runtimeImport = opts.hasRuntime && opts.runtimeImportPath
7
+ ? `import __kuratchiRuntime from '${opts.runtimeImportPath}';`
8
+ : '';
9
+ const authInit = buildAuthSessionInit(opts);
10
+ const { migrationImports, migrationInit } = buildOrmMigrationBlock(opts);
11
+ const { authPluginImports, authPluginInit } = buildAuthPluginBlock(opts);
12
+ const { doImports, doClassCode, doResolverInit } = buildDurableObjectBlock(opts);
13
+ const workflowStatusRpc = buildWorkflowStatusRpc(opts);
14
+ return {
15
+ workerImport,
16
+ contextImport,
17
+ runtimeImport,
18
+ migrationImports,
19
+ migrationInit,
20
+ authInit,
21
+ authPluginImports,
22
+ authPluginInit,
23
+ doImports,
24
+ doClassCode,
25
+ doResolverInit,
26
+ workflowStatusRpc,
27
+ };
28
+ }
29
+ function buildAuthSessionInit(opts) {
30
+ if (!opts.authConfig?.sessionEnabled)
31
+ return '';
32
+ const cookieName = opts.authConfig.cookieName;
33
+ return `
34
+ // Auth Session Init
35
+
36
+ function __parseCookies(header) {
37
+ const map = {};
38
+ if (!header) return map;
39
+ for (const pair of header.split(';')) {
40
+ const eq = pair.indexOf('=');
41
+ if (eq === -1) continue;
42
+ map[pair.slice(0, eq).trim()] = pair.slice(eq + 1).trim();
43
+ }
44
+ return map;
45
+ }
46
+
47
+ function __initAuth(request) {
48
+ const cookies = __parseCookies(request.headers.get('cookie'));
49
+ __setLocal('session', null);
50
+ __setLocal('user', null);
51
+ __setLocal('auth', {
52
+ cookies,
53
+ sessionCookie: cookies['${cookieName}'] || null,
54
+ cookieName: '${cookieName}',
55
+ });
56
+ }
57
+ `;
58
+ }
59
+ function buildOrmMigrationBlock(opts) {
60
+ if (opts.ormDatabases.length === 0) {
61
+ return { migrationImports: '', migrationInit: '' };
62
+ }
63
+ const schemaImports = [];
64
+ const migrateEntries = [];
65
+ for (const db of opts.ormDatabases) {
66
+ const resolvedPath = db.schemaImportPath.replace(/^\.\//, '../');
67
+ if (!db.skipMigrations && db.type === 'd1') {
68
+ schemaImports.push(`import { ${db.schemaExportName} } from '${resolvedPath}';`);
69
+ migrateEntries.push(` { binding: '${db.binding}', schema: ${db.schemaExportName} }`);
70
+ }
71
+ }
72
+ if (migrateEntries.length === 0) {
73
+ return { migrationImports: '', migrationInit: '' };
74
+ }
75
+ return {
76
+ migrationImports: [
77
+ `import { runMigrations } from '@kuratchi/orm/migrations';`,
78
+ `import { kuratchiORM } from '@kuratchi/orm';`,
79
+ ...schemaImports,
80
+ ].join('\n'),
81
+ migrationInit: `
82
+ // ORM Auto-Migration
83
+
84
+ let __migrated = false;
85
+ const __ormDatabases = [
86
+ ${migrateEntries.join(',\n')}
87
+ ];
88
+
89
+ async function __runMigrations() {
90
+ if (__migrated) return;
91
+ __migrated = true;
92
+ for (const db of __ormDatabases) {
93
+ const binding = __env[db.binding];
94
+ if (!binding) continue;
95
+ try {
96
+ const executor = (sql, params) => {
97
+ let stmt = binding.prepare(sql);
98
+ if (params?.length) stmt = stmt.bind(...params);
99
+ return stmt.all().then(r => ({ success: r.success ?? true, data: r.results, results: r.results }));
100
+ };
101
+ const result = await runMigrations({ execute: executor, schema: db.schema });
102
+ if (result.applied) {
103
+ console.log('[kuratchi] ' + db.binding + ': migrated (' + result.statementsRun + ' statements)');
104
+ }
105
+ if (result.warnings.length) {
106
+ result.warnings.forEach(w => console.warn('[kuratchi] ' + db.binding + ': ' + w));
107
+ }
108
+ } catch (err) {
109
+ console.error('[kuratchi] ' + db.binding + ' migration failed:', err.message);
110
+ }
111
+ }
112
+ }
113
+ `,
114
+ };
115
+ }
116
+ function buildAuthPluginBlock(opts) {
117
+ const ac = opts.authConfig;
118
+ if (!ac || !(ac.hasCredentials || ac.hasActivity || ac.hasRoles || ac.hasOAuth || ac.hasGuards || ac.hasRateLimit || ac.hasTurnstile || ac.hasOrganization)) {
119
+ return { authPluginImports: '', authPluginInit: '' };
120
+ }
121
+ const imports = [`import __kuratchiConfig from '../kuratchi.config';`];
122
+ const initLines = [];
123
+ if (ac.hasCredentials) {
124
+ imports.push(`import { configureCredentials as __configCreds } from '@kuratchi/auth';`);
125
+ initLines.push(` if (__kuratchiConfig.auth?.credentials) __configCreds(__kuratchiConfig.auth.credentials);`);
126
+ }
127
+ if (ac.hasActivity) {
128
+ imports.push(`import { defineActivities as __defActivities } from '@kuratchi/auth';`);
129
+ initLines.push(` if (__kuratchiConfig.auth?.activity) __defActivities(__kuratchiConfig.auth.activity);`);
130
+ }
131
+ if (ac.hasRoles) {
132
+ imports.push(`import { defineRoles as __defRoles } from '@kuratchi/auth';`);
133
+ initLines.push(` if (__kuratchiConfig.auth?.roles) __defRoles(__kuratchiConfig.auth.roles);`);
134
+ }
135
+ if (ac.hasOAuth) {
136
+ imports.push(`import { configureOAuth as __configOAuth } from '@kuratchi/auth';`);
137
+ initLines.push(` if (__kuratchiConfig.auth?.oauth) {`);
138
+ initLines.push(` const oc = __kuratchiConfig.auth.oauth;`);
139
+ initLines.push(` const providers = {};`);
140
+ initLines.push(` if (oc.providers) {`);
141
+ initLines.push(` for (const [name, cfg] of Object.entries(oc.providers)) {`);
142
+ initLines.push(` providers[name] = { clientId: __env[cfg.clientIdEnv] || '', clientSecret: __env[cfg.clientSecretEnv] || '', scopes: cfg.scopes };`);
143
+ initLines.push(` }`);
144
+ initLines.push(` }`);
145
+ initLines.push(` __configOAuth({ providers, loginRedirect: oc.loginRedirect });`);
146
+ initLines.push(` }`);
147
+ }
148
+ if (ac.hasGuards) {
149
+ imports.push(`import { configureGuards as __configGuards, checkGuard as __checkGuard } from '@kuratchi/auth';`);
150
+ initLines.push(` if (__kuratchiConfig.auth?.guards) __configGuards(__kuratchiConfig.auth.guards);`);
151
+ }
152
+ if (ac.hasRateLimit) {
153
+ imports.push(`import { configureRateLimit as __configRL, checkRateLimit as __checkRL } from '@kuratchi/auth';`);
154
+ initLines.push(` if (__kuratchiConfig.auth?.rateLimit) __configRL(__kuratchiConfig.auth.rateLimit);`);
155
+ }
156
+ if (ac.hasTurnstile) {
157
+ imports.push(`import { configureTurnstile as __configTS, checkTurnstile as __checkTS } from '@kuratchi/auth';`);
158
+ initLines.push(` if (__kuratchiConfig.auth?.turnstile) __configTS(__kuratchiConfig.auth.turnstile);`);
159
+ }
160
+ if (ac.hasOrganization) {
161
+ imports.push(`import { configureOrganization as __configOrg } from '@kuratchi/auth';`);
162
+ initLines.push(` if (__kuratchiConfig.auth?.organizations) __configOrg(__kuratchiConfig.auth.organizations);`);
163
+ }
164
+ return {
165
+ authPluginImports: imports.join('\n'),
166
+ authPluginInit: `
167
+ // Auth Plugin Init
168
+
169
+ function __initAuthPlugins() {
170
+ ${initLines.join('\n')}
171
+ }
172
+ `,
173
+ };
174
+ }
175
+ function buildDurableObjectBlock(opts) {
176
+ if (opts.doConfig.length === 0 || opts.doHandlers.length === 0) {
177
+ return { doImports: '', doClassCode: '', doResolverInit: '' };
178
+ }
179
+ const doImportLines = [];
180
+ const doClassLines = [];
181
+ const doResolverLines = [];
182
+ doImportLines.push(`import { DurableObject as __DO } from 'cloudflare:workers';`);
183
+ doImportLines.push(`import { initDO as __initDO } from '@kuratchi/orm';`);
184
+ doImportLines.push(`import { __registerDoResolver, __registerDoClassBinding, __setDoContext } from '${opts.runtimeDoImport}';`);
185
+ doImportLines.push(`const __DO_FD_TAG = '__kuratchi_form_data__';`);
186
+ doImportLines.push(`function __isDoPlainObject(__v) {`);
187
+ doImportLines.push(` if (!__v || typeof __v !== 'object') return false;`);
188
+ doImportLines.push(` const __proto = Object.getPrototypeOf(__v);`);
189
+ doImportLines.push(` return __proto === Object.prototype || __proto === null;`);
190
+ doImportLines.push(`}`);
191
+ doImportLines.push(`function __decodeDoArg(__v) {`);
192
+ doImportLines.push(` if (Array.isArray(__v)) return __v.map(__decodeDoArg);`);
193
+ doImportLines.push(` if (__isDoPlainObject(__v)) {`);
194
+ doImportLines.push(` if (__DO_FD_TAG in __v) {`);
195
+ doImportLines.push(` const __fd = new FormData();`);
196
+ doImportLines.push(` const __entries = Array.isArray(__v[__DO_FD_TAG]) ? __v[__DO_FD_TAG] : [];`);
197
+ doImportLines.push(` for (const __pair of __entries) { if (Array.isArray(__pair) && __pair.length >= 2) __fd.append(String(__pair[0]), __pair[1]); }`);
198
+ doImportLines.push(` return __fd;`);
199
+ doImportLines.push(` }`);
200
+ doImportLines.push(` const __out = {};`);
201
+ doImportLines.push(` for (const [__k, __val] of Object.entries(__v)) __out[__k] = __decodeDoArg(__val);`);
202
+ doImportLines.push(` return __out;`);
203
+ doImportLines.push(` }`);
204
+ doImportLines.push(` return __v;`);
205
+ doImportLines.push(`}`);
206
+ doImportLines.push(`import { getCurrentUser as __getCU, getOrgStubByName as __getOSBN } from '@kuratchi/auth';`);
207
+ const handlersByBinding = new Map();
208
+ for (const handler of opts.doHandlers) {
209
+ const list = handlersByBinding.get(handler.binding) ?? [];
210
+ list.push(handler);
211
+ handlersByBinding.set(handler.binding, list);
212
+ }
213
+ for (const doEntry of opts.doConfig) {
214
+ const handlers = handlersByBinding.get(doEntry.binding) ?? [];
215
+ const ormDb = opts.ormDatabases.find((db) => db.binding === doEntry.binding);
216
+ if (ormDb) {
217
+ const schemaPath = ormDb.schemaImportPath.replace(/^\.\//, '../');
218
+ doImportLines.push(`import { ${ormDb.schemaExportName} as __doSchema_${doEntry.binding} } from '${schemaPath}';`);
219
+ }
220
+ for (const handler of handlers) {
221
+ let handlerImportPath = path
222
+ .relative(path.join(opts.projectDir, '.kuratchi'), handler.absPath)
223
+ .replace(/\\/g, '/')
224
+ .replace(/\.ts$/, '.js');
225
+ if (!handlerImportPath.startsWith('.'))
226
+ handlerImportPath = './' + handlerImportPath;
227
+ const handlerVar = `__handler_${toSafeIdentifier(handler.fileName)}`;
228
+ doImportLines.push(`import ${handlerVar} from '${handlerImportPath}';`);
229
+ }
230
+ if (ormDb) {
231
+ const handler = handlers[0];
232
+ const handlerVar = handler ? `__handler_${toSafeIdentifier(handler.fileName)}` : '__DO';
233
+ const baseClass = handler ? handlerVar : '__DO';
234
+ doClassLines.push(...buildOrmDurableObjectClassLines(doEntry.className, doEntry.binding, baseClass));
235
+ }
236
+ else if (handlers.length > 0) {
237
+ const handler = handlers[0];
238
+ const handlerVar = `__handler_${toSafeIdentifier(handler.fileName)}`;
239
+ doClassLines.push(`export { ${handlerVar} as ${doEntry.className} };`);
240
+ }
241
+ for (const handler of handlers) {
242
+ const handlerVar = `__handler_${toSafeIdentifier(handler.fileName)}`;
243
+ doResolverLines.push(` __registerDoClassBinding(${handlerVar}, '${doEntry.binding}');`);
244
+ }
245
+ if (doEntry.stubId) {
246
+ const fieldPath = doEntry.stubId.startsWith('user.') ? `__u.${doEntry.stubId.slice(5)}` : doEntry.stubId;
247
+ const checkField = doEntry.stubId.startsWith('user.') ? doEntry.stubId.slice(5) : doEntry.stubId;
248
+ doResolverLines.push(` __registerDoResolver('${doEntry.binding}', async () => {`);
249
+ doResolverLines.push(` const __u = await __getCU();`);
250
+ doResolverLines.push(` if (!__u?.${checkField}) return null;`);
251
+ doResolverLines.push(` return __getOSBN(${fieldPath});`);
252
+ doResolverLines.push(` });`);
253
+ }
254
+ else {
255
+ doResolverLines.push(` // No 'stubId' config for ${doEntry.binding} - stub must be obtained manually`);
256
+ }
257
+ }
258
+ return {
259
+ doImports: doImportLines.join('\n'),
260
+ doClassCode: `\n// Durable Object Classes (generated)\n\n${doClassLines.join('\n')}\n`,
261
+ doResolverInit: `\nfunction __initDoResolvers() {\n${doResolverLines.join('\n')}\n}\n`,
262
+ };
263
+ }
264
+ function buildOrmDurableObjectClassLines(className, binding, baseClass) {
265
+ return [
266
+ `export class ${className} extends ${baseClass} {`,
267
+ ` constructor(ctx, env) {`,
268
+ ` super(ctx, env);`,
269
+ ` this.db = __initDO(ctx.storage.sql, __doSchema_${binding});`,
270
+ ` }`,
271
+ ` async __kuratchiLogActivity(payload) {`,
272
+ ` const now = new Date().toISOString();`,
273
+ ` try {`,
274
+ ` await this.db.activityLog.insert({`,
275
+ ` userId: payload?.userId ?? null,`,
276
+ ` action: payload?.action,`,
277
+ ` detail: payload?.detail ?? null,`,
278
+ ` ip: payload?.ip ?? null,`,
279
+ ` userAgent: payload?.userAgent ?? null,`,
280
+ ` createdAt: now,`,
281
+ ` updatedAt: now,`,
282
+ ` });`,
283
+ ` } catch (err) {`,
284
+ ` const msg = String((err && err.message) || err || '');`,
285
+ ` if (!msg.includes('userId')) throw err;`,
286
+ ` await this.db.activityLog.insert({`,
287
+ ` action: payload?.action,`,
288
+ ` detail: payload?.detail ?? null,`,
289
+ ` ip: payload?.ip ?? null,`,
290
+ ` userAgent: payload?.userAgent ?? null,`,
291
+ ` createdAt: now,`,
292
+ ` updatedAt: now,`,
293
+ ` });`,
294
+ ` }`,
295
+ ` }`,
296
+ ` async __kuratchiGetActivity(options = {}) {`,
297
+ ` let query = this.db.activityLog;`,
298
+ ` if (options?.action) query = query.where({ action: options.action });`,
299
+ ` const result = await query.orderBy({ createdAt: 'desc' }).many();`,
300
+ ` const rows = Array.isArray(result?.data) ? result.data : [];`,
301
+ ` const limit = Number(options?.limit);`,
302
+ ` if (Number.isFinite(limit) && limit > 0) return rows.slice(0, Math.floor(limit));`,
303
+ ` return rows;`,
304
+ ` }`,
305
+ `}`,
306
+ ];
307
+ }
308
+ function buildWorkflowStatusRpc(opts) {
309
+ if (opts.workflowConfig.length === 0)
310
+ return '';
311
+ const rpcLines = [];
312
+ rpcLines.push(`\n// Workflow Status RPCs (auto-generated)`);
313
+ rpcLines.push(`const __workflowStatusRpc = {`);
314
+ for (const workflow of opts.workflowConfig) {
315
+ const baseName = workflow.file.split('/').pop()?.replace(/\.workflow\.ts$/, '') || '';
316
+ const camelName = baseName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
317
+ const rpcName = `${camelName}WorkflowStatus`;
318
+ rpcLines.push(` '${rpcName}': async (instanceId) => {`);
319
+ rpcLines.push(` if (!instanceId) return { status: 'unknown', error: { name: 'Error', message: 'Missing instanceId' } };`);
320
+ rpcLines.push(` try {`);
321
+ rpcLines.push(` const instance = await __env.${workflow.binding}.get(instanceId);`);
322
+ rpcLines.push(` return await instance.status();`);
323
+ rpcLines.push(` } catch (err) {`);
324
+ rpcLines.push(` return { status: 'errored', error: { name: err?.name || 'Error', message: err?.message || 'Unknown error' } };`);
325
+ rpcLines.push(` }`);
326
+ rpcLines.push(` },`);
327
+ }
328
+ rpcLines.push(`};`);
329
+ return rpcLines.join('\n');
330
+ }
@@ -0,0 +1,2 @@
1
+ import type { GenerateRoutesModuleOptions } from './routes-module-types.js';
2
+ export declare function generateRoutesModule(opts: GenerateRoutesModuleOptions): string;
@@ -0,0 +1,6 @@
1
+ import { buildRoutesModuleFeatureBlocks } from './routes-module-feature-blocks.js';
2
+ import { buildRoutesModuleRuntimeShell } from './routes-module-runtime-shell.js';
3
+ export function generateRoutesModule(opts) {
4
+ const featureBlocks = buildRoutesModuleFeatureBlocks(opts);
5
+ return buildRoutesModuleRuntimeShell(opts, featureBlocks);
6
+ }
@@ -0,0 +1,2 @@
1
+ import type { GenerateRoutesModuleOptions, RoutesModuleFeatureBlocks } from './routes-module-types.js';
2
+ export declare function buildRoutesModuleRuntimeShell(opts: GenerateRoutesModuleOptions, blocks: RoutesModuleFeatureBlocks): string;
@@ -0,0 +1,81 @@
1
+ export function buildRoutesModuleRuntimeShell(opts, blocks) {
2
+ const layoutBlock = opts.compiledLayout ?? 'function __layout(content, _head = \'\') { return content; }';
3
+ const layoutActionsBlock = opts.compiledLayoutActions
4
+ ? `const __layoutActions = ${opts.compiledLayoutActions};`
5
+ : 'const __layoutActions = {};';
6
+ const componentBlock = opts.compiledComponents.length > 0 ? `// Components\n\n${opts.compiledComponents.join('\n\n')}\n` : '';
7
+ const customErrorFunctions = Array.from(opts.compiledErrorPages.entries())
8
+ .map(([status, fn]) => fn)
9
+ .join('\n\n');
10
+ const customErrorEntries = Array.from(opts.compiledErrorPages.keys())
11
+ .map((status) => ` ${status}: __error_${status},`)
12
+ .join('\n');
13
+ const initializeRequestBody = [
14
+ blocks.migrationInit ? ' await __runMigrations();' : '',
15
+ blocks.authInit ? ' __initAuth(ctx.request);' : '',
16
+ blocks.authPluginInit ? ' __initAuthPlugins();' : '',
17
+ blocks.doResolverInit ? ' __initDoResolvers();' : '',
18
+ ].filter(Boolean).join('\n');
19
+ const preRouteChecksBody = [
20
+ opts.authConfig?.hasRateLimit ? ` { const __rlRes = await __checkRL(); if (__rlRes) return __rlRes; }` : '',
21
+ opts.authConfig?.hasTurnstile ? ` { const __tsRes = await __checkTS(); if (__tsRes) return __tsRes; }` : '',
22
+ opts.authConfig?.hasGuards ? ` { const __gRes = __checkGuard(); if (__gRes) return __gRes; }` : '',
23
+ ' return null;',
24
+ ].filter(Boolean).join('\n');
25
+ return `// Generated by KuratchiJS compiler - do not edit.
26
+ ${opts.isDev ? '\nglobalThis.__kuratchi_DEV__ = true;\n' : ''}
27
+ ${blocks.workerImport}
28
+ import { createGeneratedWorker } from '${opts.runtimeWorkerImport}';
29
+ ${blocks.contextImport}
30
+ ${blocks.runtimeImport ? blocks.runtimeImport + '\n' : ''}${blocks.migrationImports ? blocks.migrationImports + '\n' : ''}${blocks.authPluginImports ? blocks.authPluginImports + '\n' : ''}${blocks.doImports ? blocks.doImports + '\n' : ''}${opts.serverImports.join('\n')}
31
+ ${blocks.workflowStatusRpc}
32
+
33
+ // Assets
34
+
35
+ const __assets = {
36
+ ${opts.compiledAssets.map((asset) => ` ${JSON.stringify(asset.name)}: { content: ${JSON.stringify(asset.content)}, mime: ${JSON.stringify(asset.mime)}, etag: ${JSON.stringify(asset.etag)} }`).join(',\n')}
37
+ };
38
+
39
+ // Layout
40
+
41
+ ${layoutBlock}
42
+
43
+ ${layoutActionsBlock}
44
+
45
+ // Error pages
46
+
47
+ ${customErrorFunctions ? '// Custom error page overrides (user-created NNN.html)\n' + customErrorFunctions + '\n' : ''}const __customErrors = {
48
+ ${customErrorEntries}
49
+ };
50
+
51
+ ${componentBlock}${blocks.migrationInit}${blocks.authInit}${blocks.authPluginInit}${blocks.doResolverInit}${blocks.doClassCode}
52
+ // Route definitions
53
+
54
+ const routes = [
55
+ ${opts.compiledRoutes.join(',\n')}
56
+ ];
57
+
58
+ const __runtimeDef = (typeof __kuratchiRuntime !== 'undefined' && __kuratchiRuntime && typeof __kuratchiRuntime === 'object') ? __kuratchiRuntime : {};
59
+
60
+ async function __initializeRequest(ctx) {
61
+ ${initializeRequestBody || ' return;'}
62
+ }
63
+
64
+ async function __preRouteChecks() {
65
+ ${preRouteChecksBody}
66
+ }
67
+
68
+ export default createGeneratedWorker({
69
+ routes,
70
+ layout: __layout,
71
+ layoutActions: __layoutActions,
72
+ assetsPrefix: ${JSON.stringify(opts.assetsPrefix)},
73
+ assets: __assets,
74
+ errorPages: __customErrors,
75
+ runtimeDefinition: __runtimeDef,
76
+ workflowStatusRpc: typeof __workflowStatusRpc !== 'undefined' ? __workflowStatusRpc : {},
77
+ initializeRequest: __initializeRequest,
78
+ preRouteChecks: __preRouteChecks,
79
+ });
80
+ `;
81
+ }
@@ -0,0 +1,44 @@
1
+ import type { AuthConfigEntry, DoConfigEntry, DoHandlerEntry, OrmDatabaseEntry, WorkerClassConfigEntry } from './compiler-shared.js';
2
+ export interface CompiledAssetEntry {
3
+ name: string;
4
+ content: string;
5
+ mime: string;
6
+ etag: string;
7
+ }
8
+ export interface GenerateRoutesModuleOptions {
9
+ projectDir: string;
10
+ serverImports: string[];
11
+ compiledRoutes: string[];
12
+ compiledLayout: string | null;
13
+ compiledComponents: string[];
14
+ isDev: boolean;
15
+ compiledAssets: CompiledAssetEntry[];
16
+ compiledErrorPages: Map<number, string>;
17
+ ormDatabases: OrmDatabaseEntry[];
18
+ authConfig: AuthConfigEntry | null;
19
+ doConfig: DoConfigEntry[];
20
+ doHandlers: DoHandlerEntry[];
21
+ workflowConfig: WorkerClassConfigEntry[];
22
+ isLayoutAsync: boolean;
23
+ compiledLayoutActions: string | null;
24
+ hasRuntime: boolean;
25
+ runtimeImportPath?: string;
26
+ assetsPrefix: string;
27
+ runtimeContextImport: string;
28
+ runtimeDoImport: string;
29
+ runtimeWorkerImport: string;
30
+ }
31
+ export interface RoutesModuleFeatureBlocks {
32
+ workerImport: string;
33
+ contextImport: string;
34
+ runtimeImport: string;
35
+ migrationImports: string;
36
+ migrationInit: string;
37
+ authInit: string;
38
+ authPluginImports: string;
39
+ authPluginInit: string;
40
+ doImports: string;
41
+ doClassCode: string;
42
+ doResolverInit: string;
43
+ workflowStatusRpc: string;
44
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ export interface RouteScriptSegment {
2
+ script: string;
3
+ dataVars: string[];
4
+ }
5
+ export declare function rewriteImportedFunctionCalls(source: string, fnToModule: Record<string, string>): string;
6
+ export declare function rewriteWorkerEnvAliases(source: string, aliases: string[]): string;
7
+ export declare function buildDevAliasDeclarations(aliases: string[], isDev: boolean): string;
8
+ export declare function buildSegmentedScriptBody(opts: {
9
+ segments: RouteScriptSegment[];
10
+ fnToModule: Record<string, string>;
11
+ importDecls?: string;
12
+ workerEnvAliases: string[];
13
+ devAliases: string[];
14
+ isDev: boolean;
15
+ asyncMode: boolean;
16
+ }): string;