@emkodev/emroute 1.6.2 → 1.6.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.
Files changed (128) hide show
  1. package/README.md +6 -6
  2. package/dist/runtime/abstract.runtime.d.ts +94 -0
  3. package/dist/runtime/abstract.runtime.js +339 -0
  4. package/dist/runtime/abstract.runtime.js.map +1 -0
  5. package/dist/runtime/bun/esbuild-runtime-loader.plugin.d.ts +25 -0
  6. package/dist/runtime/bun/esbuild-runtime-loader.plugin.js +72 -0
  7. package/dist/runtime/bun/esbuild-runtime-loader.plugin.js.map +1 -0
  8. package/dist/runtime/bun/fs/bun-fs.runtime.d.ts +21 -0
  9. package/dist/runtime/bun/fs/bun-fs.runtime.js +205 -0
  10. package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -0
  11. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.d.ts +27 -0
  12. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +234 -0
  13. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -0
  14. package/dist/runtime/sitemap.generator.d.ts +58 -0
  15. package/dist/runtime/sitemap.generator.js +107 -0
  16. package/dist/runtime/sitemap.generator.js.map +1 -0
  17. package/dist/runtime/universal/fs/universal-fs.runtime.d.ts +29 -0
  18. package/dist/runtime/universal/fs/universal-fs.runtime.js +213 -0
  19. package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -0
  20. package/dist/server/codegen.util.d.ts +16 -0
  21. package/dist/server/codegen.util.js +46 -0
  22. package/dist/server/codegen.util.js.map +1 -0
  23. package/dist/server/emroute.server.d.ts +37 -0
  24. package/dist/server/emroute.server.js +314 -0
  25. package/dist/server/emroute.server.js.map +1 -0
  26. package/dist/server/esbuild-manifest.plugin.d.ts +26 -0
  27. package/dist/server/esbuild-manifest.plugin.js +187 -0
  28. package/dist/server/esbuild-manifest.plugin.js.map +1 -0
  29. package/dist/server/scanner.util.d.ts +22 -0
  30. package/dist/server/scanner.util.js +194 -0
  31. package/dist/server/scanner.util.js.map +1 -0
  32. package/dist/server/server-api.type.d.ts +71 -0
  33. package/dist/server/server-api.type.js +9 -0
  34. package/dist/server/server-api.type.js.map +1 -0
  35. package/dist/src/component/abstract.component.d.ts +197 -0
  36. package/dist/src/component/abstract.component.js +84 -0
  37. package/dist/src/component/abstract.component.js.map +1 -0
  38. package/dist/src/component/page.component.d.ts +74 -0
  39. package/dist/src/component/page.component.js +107 -0
  40. package/dist/src/component/page.component.js.map +1 -0
  41. package/dist/src/component/widget.component.d.ts +47 -0
  42. package/dist/src/component/widget.component.js +69 -0
  43. package/dist/src/component/widget.component.js.map +1 -0
  44. package/dist/src/element/component.element.d.ts +79 -0
  45. package/dist/src/element/component.element.js +293 -0
  46. package/dist/src/element/component.element.js.map +1 -0
  47. package/dist/src/element/markdown.element.d.ts +36 -0
  48. package/dist/src/element/markdown.element.js +93 -0
  49. package/dist/src/element/markdown.element.js.map +1 -0
  50. package/dist/src/element/slot.element.d.ts +30 -0
  51. package/dist/src/element/slot.element.js +31 -0
  52. package/dist/src/element/slot.element.js.map +1 -0
  53. package/dist/src/index.d.ts +23 -0
  54. package/dist/src/index.js +24 -0
  55. package/dist/src/index.js.map +1 -0
  56. package/dist/src/overlay/mod.d.ts +9 -0
  57. package/dist/src/overlay/mod.js +9 -0
  58. package/dist/src/overlay/mod.js.map +1 -0
  59. package/dist/src/overlay/overlay.css.d.ts +8 -0
  60. package/dist/src/overlay/overlay.css.js +170 -0
  61. package/dist/src/overlay/overlay.css.js.map +1 -0
  62. package/dist/src/overlay/overlay.service.d.ts +14 -0
  63. package/dist/src/overlay/overlay.service.js +307 -0
  64. package/dist/src/overlay/overlay.service.js.map +1 -0
  65. package/dist/src/overlay/overlay.type.d.ts +33 -0
  66. package/dist/src/overlay/overlay.type.js +11 -0
  67. package/dist/src/overlay/overlay.type.js.map +1 -0
  68. package/dist/src/renderer/spa/base.renderer.d.ts +39 -0
  69. package/dist/src/renderer/spa/base.renderer.js +149 -0
  70. package/dist/src/renderer/spa/base.renderer.js.map +1 -0
  71. package/dist/src/renderer/spa/hash.renderer.d.ts +78 -0
  72. package/dist/src/renderer/spa/hash.renderer.js +162 -0
  73. package/dist/src/renderer/spa/hash.renderer.js.map +1 -0
  74. package/dist/src/renderer/spa/html.renderer.d.ts +81 -0
  75. package/dist/src/renderer/spa/html.renderer.js +304 -0
  76. package/dist/src/renderer/spa/html.renderer.js.map +1 -0
  77. package/dist/src/renderer/spa/mod.d.ts +30 -0
  78. package/dist/src/renderer/spa/mod.js +35 -0
  79. package/dist/src/renderer/spa/mod.js.map +1 -0
  80. package/dist/src/renderer/ssr/html.renderer.d.ts +49 -0
  81. package/dist/src/renderer/ssr/html.renderer.js +108 -0
  82. package/dist/src/renderer/ssr/html.renderer.js.map +1 -0
  83. package/dist/src/renderer/ssr/md.renderer.d.ts +40 -0
  84. package/dist/src/renderer/ssr/md.renderer.js +100 -0
  85. package/dist/src/renderer/ssr/md.renderer.js.map +1 -0
  86. package/dist/src/renderer/ssr/ssr.renderer.d.ts +74 -0
  87. package/dist/src/renderer/ssr/ssr.renderer.js +185 -0
  88. package/dist/src/renderer/ssr/ssr.renderer.js.map +1 -0
  89. package/dist/src/route/route.core.d.ts +129 -0
  90. package/dist/src/route/route.core.js +255 -0
  91. package/dist/src/route/route.core.js.map +1 -0
  92. package/dist/src/route/route.matcher.d.ts +86 -0
  93. package/dist/src/route/route.matcher.js +214 -0
  94. package/dist/src/route/route.matcher.js.map +1 -0
  95. package/dist/src/type/logger.type.d.ts +17 -0
  96. package/dist/src/type/logger.type.js +9 -0
  97. package/dist/src/type/logger.type.js.map +1 -0
  98. package/dist/src/type/markdown.type.d.ts +20 -0
  99. package/dist/src/type/markdown.type.js +2 -0
  100. package/dist/src/type/markdown.type.js.map +1 -0
  101. package/dist/src/type/route.type.d.ts +112 -0
  102. package/dist/src/type/route.type.js +8 -0
  103. package/dist/src/type/route.type.js.map +1 -0
  104. package/dist/src/type/widget.type.d.ts +55 -0
  105. package/dist/src/type/widget.type.js +10 -0
  106. package/dist/src/type/widget.type.js.map +1 -0
  107. package/dist/src/util/html.util.d.ts +29 -0
  108. package/dist/src/util/html.util.js +158 -0
  109. package/dist/src/util/html.util.js.map +1 -0
  110. package/dist/src/util/logger.util.d.ts +26 -0
  111. package/dist/src/util/logger.util.js +80 -0
  112. package/dist/src/util/logger.util.js.map +1 -0
  113. package/dist/src/util/widget-resolve.util.d.ts +52 -0
  114. package/dist/src/util/widget-resolve.util.js +149 -0
  115. package/dist/src/util/widget-resolve.util.js.map +1 -0
  116. package/dist/src/widget/breadcrumb.widget.d.ts +48 -0
  117. package/dist/src/widget/breadcrumb.widget.js +72 -0
  118. package/dist/src/widget/breadcrumb.widget.js.map +1 -0
  119. package/dist/src/widget/page-title.widget.d.ts +33 -0
  120. package/dist/src/widget/page-title.widget.js +33 -0
  121. package/dist/src/widget/page-title.widget.js.map +1 -0
  122. package/dist/src/widget/widget.parser.d.ts +26 -0
  123. package/dist/src/widget/widget.parser.js +76 -0
  124. package/dist/src/widget/widget.parser.js.map +1 -0
  125. package/dist/src/widget/widget.registry.d.ts +23 -0
  126. package/dist/src/widget/widget.registry.js +42 -0
  127. package/dist/src/widget/widget.registry.js.map +1 -0
  128. package/package.json +72 -13
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Emroute Server
3
+ *
4
+ * Runtime-agnostic server that handles SSR rendering, manifest resolution,
5
+ * static file serving, and route matching. Works with any Runtime implementation.
6
+ *
7
+ * Usage (standalone):
8
+ * ```ts
9
+ * import { createEmrouteServer } from '@emkodev/emroute/server';
10
+ * import { BunFsRuntime } from '@emkodev/emroute/runtime/bun/fs';
11
+ *
12
+ * const runtime = new BunFsRuntime('.', { routesDir: '/routes' });
13
+ * const emroute = await createEmrouteServer({ spa: 'root' }, runtime);
14
+ *
15
+ * Bun.serve({ fetch: (req) => emroute.handleRequest(req) ?? new Response('Not Found', { status: 404 }) });
16
+ * ```
17
+ *
18
+ * Usage (composable):
19
+ * ```ts
20
+ * const emroute = await createEmrouteServer(config, runtime);
21
+ *
22
+ * Bun.serve({ async fetch(req) {
23
+ * if (isApiRoute(req)) return handleApi(req);
24
+ * const response = await emroute.handleRequest(req);
25
+ * if (response) return response;
26
+ * return new Response('Not Found', { status: 404 });
27
+ * }});
28
+ * ```
29
+ */
30
+ import { DEFAULT_BASE_PATH, prefixManifest } from "../src/route/route.core.js";
31
+ import { SsrHtmlRouter } from "../src/renderer/ssr/html.renderer.js";
32
+ import { SsrMdRouter } from "../src/renderer/ssr/md.renderer.js";
33
+ import { WidgetRegistry } from "../src/widget/widget.registry.js";
34
+ import { escapeHtml } from "../src/util/html.util.js";
35
+ import { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH, } from "../runtime/abstract.runtime.js";
36
+ // ── Module loaders ─────────────────────────────────────────────────────
37
+ /**
38
+ * Create module loaders for server-side SSR imports.
39
+ * Uses `runtime.loadModule()` — each runtime decides how to load modules
40
+ * (filesystem import, SQLite transpile + blob URL, etc.).
41
+ */
42
+ function createModuleLoaders(manifest, runtime) {
43
+ const loaders = {};
44
+ const modulePaths = new Set();
45
+ for (const route of manifest.routes) {
46
+ if (route.files?.ts)
47
+ modulePaths.add(route.files.ts);
48
+ if (route.modulePath.endsWith('.ts'))
49
+ modulePaths.add(route.modulePath);
50
+ }
51
+ for (const boundary of manifest.errorBoundaries) {
52
+ modulePaths.add(boundary.modulePath);
53
+ }
54
+ if (manifest.errorHandler) {
55
+ modulePaths.add(manifest.errorHandler.modulePath);
56
+ }
57
+ for (const [_, statusRoute] of manifest.statusPages) {
58
+ if (statusRoute.modulePath.endsWith('.ts')) {
59
+ modulePaths.add(statusRoute.modulePath);
60
+ }
61
+ }
62
+ for (const path of modulePaths) {
63
+ loaders[path] = () => runtime.loadModule(path);
64
+ }
65
+ return loaders;
66
+ }
67
+ // ── Widget helpers ─────────────────────────────────────────────────────
68
+ /** Find a WidgetComponent export from a module. */
69
+ function extractWidgetExport(mod) {
70
+ for (const value of Object.values(mod)) {
71
+ if (!value)
72
+ continue;
73
+ if (typeof value === 'object' && 'getData' in value) {
74
+ return value;
75
+ }
76
+ if (typeof value === 'function' && value.prototype?.getData) {
77
+ return new value();
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+ /** Import widget modules for SSR via runtime.loadModule(). */
83
+ async function importWidgets(entries, runtime, manual) {
84
+ const registry = new WidgetRegistry();
85
+ for (const entry of entries) {
86
+ try {
87
+ const runtimePath = entry.modulePath.startsWith('/')
88
+ ? entry.modulePath
89
+ : `/${entry.modulePath}`;
90
+ const mod = await runtime.loadModule(runtimePath);
91
+ const instance = extractWidgetExport(mod);
92
+ if (!instance)
93
+ continue;
94
+ registry.add(instance);
95
+ }
96
+ catch (e) {
97
+ console.error(`[emroute] Failed to load widget ${entry.modulePath}:`, e);
98
+ }
99
+ }
100
+ if (manual) {
101
+ for (const widget of manual) {
102
+ registry.add(widget);
103
+ }
104
+ }
105
+ const widgetFiles = {};
106
+ for (const entry of entries) {
107
+ if (entry.files)
108
+ widgetFiles[entry.name] = entry.files;
109
+ }
110
+ return { registry, widgetFiles };
111
+ }
112
+ // ── HTML shell ─────────────────────────────────────────────────────────
113
+ /** Build a default HTML shell. */
114
+ function buildHtmlShell(title) {
115
+ return `<!DOCTYPE html>
116
+ <html>
117
+ <head>
118
+ <meta charset="utf-8">
119
+ <meta name="viewport" content="width=device-width, initial-scale=1">
120
+ <title>${escapeHtml(title)}</title>
121
+ <style>@view-transition { navigation: auto; } router-slot { display: contents; }</style>
122
+ </head>
123
+ <body>
124
+ <router-slot></router-slot>
125
+ </body>
126
+ </html>`;
127
+ }
128
+ /** Inject SSR-rendered content into an HTML shell. */
129
+ function injectSsrContent(html, content, title, ssrRoute) {
130
+ const slotPattern = /<router-slot\b[^>]*>.*?<\/router-slot>/s;
131
+ if (!slotPattern.test(html))
132
+ return html;
133
+ const ssrAttr = ssrRoute ? ` data-ssr-route="${ssrRoute}"` : '';
134
+ html = html.replace(slotPattern, `<router-slot${ssrAttr}>${content}</router-slot>`);
135
+ if (title) {
136
+ html = html.replace(/<title>[^<]*<\/title>/, `<title>${escapeHtml(title)}</title>`);
137
+ }
138
+ return html;
139
+ }
140
+ /** Read the HTML shell from runtime, with fallback to a default shell. */
141
+ async function resolveShell(runtime, title) {
142
+ const response = await runtime.query('/index.html');
143
+ if (response.status !== 404)
144
+ return await response.text();
145
+ return buildHtmlShell(title);
146
+ }
147
+ // ── More path helpers ─────────────────────────────────────────────────
148
+ /** Deserialize a routes manifest from JSON (statusPages array → Map). */
149
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
150
+ function deserializeManifest(raw) {
151
+ return {
152
+ routes: raw.routes,
153
+ errorBoundaries: raw.errorBoundaries,
154
+ statusPages: new Map(raw.statusPages ?? []),
155
+ errorHandler: raw.errorHandler,
156
+ };
157
+ }
158
+ // ── createEmrouteServer ────────────────────────────────────────────────
159
+ /**
160
+ * Create an emroute server.
161
+ *
162
+ * All paths are Runtime-relative (starting with `/`). Runtime root = appRoot.
163
+ */
164
+ export async function createEmrouteServer(config, runtime) {
165
+ const { spa = 'root', } = config;
166
+ // Let the runtime know the SPA mode so bundle() can skip when 'none'.
167
+ runtime.config.spa = spa;
168
+ const { html: htmlBase, md: mdBase } = config.basePath ?? DEFAULT_BASE_PATH;
169
+ // ── Routes manifest (read from runtime) ─────────────────────────────
170
+ let routesManifest;
171
+ if (config.routesManifest) {
172
+ routesManifest = config.routesManifest;
173
+ }
174
+ else {
175
+ const manifestResponse = await runtime.query(ROUTES_MANIFEST_PATH);
176
+ if (manifestResponse.status === 404) {
177
+ throw new Error(`[emroute] ${ROUTES_MANIFEST_PATH} not found in runtime. ` +
178
+ 'Provide routesManifest in config or ensure the runtime produces it.');
179
+ }
180
+ const raw = await manifestResponse.json();
181
+ routesManifest = deserializeManifest(raw);
182
+ }
183
+ routesManifest.moduleLoaders = createModuleLoaders(routesManifest, runtime);
184
+ // ── Widgets (read from runtime) ────────────────────────────────────
185
+ let widgets = config.widgets;
186
+ let widgetFiles = {};
187
+ let discoveredWidgetEntries = [];
188
+ const widgetsResponse = await runtime.query(WIDGETS_MANIFEST_PATH);
189
+ if (widgetsResponse.status !== 404) {
190
+ discoveredWidgetEntries = await widgetsResponse.json();
191
+ const imported = await importWidgets(discoveredWidgetEntries, runtime, config.widgets);
192
+ widgets = imported.registry;
193
+ widgetFiles = imported.widgetFiles;
194
+ }
195
+ // ── SSR routers ──────────────────────────────────────────────────────
196
+ let ssrHtmlRouter = null;
197
+ let ssrMdRouter = null;
198
+ function buildSsrRouters() {
199
+ if (spa === 'only') {
200
+ ssrHtmlRouter = null;
201
+ ssrMdRouter = null;
202
+ return;
203
+ }
204
+ ssrHtmlRouter = new SsrHtmlRouter(prefixManifest(routesManifest, htmlBase), {
205
+ fileReader: (path) => runtime.query(path, { as: 'text' }),
206
+ basePath: htmlBase,
207
+ markdownRenderer: config.markdownRenderer,
208
+ extendContext: config.extendContext,
209
+ widgets,
210
+ widgetFiles,
211
+ });
212
+ ssrMdRouter = new SsrMdRouter(prefixManifest(routesManifest, mdBase), {
213
+ fileReader: (path) => runtime.query(path, { as: 'text' }),
214
+ basePath: mdBase,
215
+ extendContext: config.extendContext,
216
+ widgets,
217
+ widgetFiles,
218
+ });
219
+ }
220
+ buildSsrRouters();
221
+ // ── Bundling (runtime decides whether/how to bundle) ────────────────
222
+ await runtime.bundle();
223
+ // ── HTML shell ───────────────────────────────────────────────────────
224
+ const title = config.title ?? 'emroute';
225
+ let shell = await resolveShell(runtime, title);
226
+ // Auto-discover main.css and inject <link> into <head>
227
+ if ((await runtime.query('/main.css')).status !== 404) {
228
+ shell = shell.replace('</head>', ' <link rel="stylesheet" href="/main.css">\n</head>');
229
+ }
230
+ // ── handleRequest ────────────────────────────────────────────────────
231
+ async function handleRequest(req) {
232
+ const url = new URL(req.url);
233
+ const pathname = url.pathname;
234
+ const mdPrefix = mdBase + '/';
235
+ const htmlPrefix = htmlBase + '/';
236
+ // SSR Markdown: /md/*
237
+ if (ssrMdRouter &&
238
+ (pathname.startsWith(mdPrefix) || pathname === mdBase)) {
239
+ try {
240
+ const { content, status, redirect } = await ssrMdRouter.render(pathname);
241
+ if (redirect) {
242
+ return Response.redirect(new URL(redirect, url.origin), status);
243
+ }
244
+ return new Response(content, {
245
+ status,
246
+ headers: { 'Content-Type': 'text/markdown; charset=utf-8; variant=CommonMark' },
247
+ });
248
+ }
249
+ catch (e) {
250
+ console.error(`[emroute] Error rendering ${pathname}:`, e);
251
+ return new Response('Internal Server Error', { status: 500 });
252
+ }
253
+ }
254
+ // SSR HTML: /html/*
255
+ if (ssrHtmlRouter &&
256
+ (pathname.startsWith(htmlPrefix) || pathname === htmlBase)) {
257
+ try {
258
+ const result = await ssrHtmlRouter.render(pathname);
259
+ if (result.redirect) {
260
+ return Response.redirect(new URL(result.redirect, url.origin), result.status);
261
+ }
262
+ const ssrTitle = result.title ?? title;
263
+ const html = injectSsrContent(shell, result.content, ssrTitle, pathname);
264
+ return new Response(html, {
265
+ status: result.status,
266
+ headers: { 'Content-Type': 'text/html; charset=utf-8' },
267
+ });
268
+ }
269
+ catch (e) {
270
+ console.error(`[emroute] Error rendering ${pathname}:`, e);
271
+ return new Response('Internal Server Error', { status: 500 });
272
+ }
273
+ }
274
+ // /html/* or /md/* that wasn't handled by SSR (e.g. 'only' mode) — serve SPA shell
275
+ if (pathname.startsWith(htmlPrefix) || pathname === htmlBase ||
276
+ pathname.startsWith(mdPrefix) || pathname === mdBase) {
277
+ return new Response(shell, {
278
+ status: 200,
279
+ headers: { 'Content-Type': 'text/html; charset=utf-8' },
280
+ });
281
+ }
282
+ // Static files — only try runtime for paths with a file extension
283
+ const lastSegment = pathname.split('/').pop() ?? '';
284
+ if (lastSegment.includes('.')) {
285
+ const fileResponse = await runtime.handle(pathname);
286
+ if (fileResponse.status === 200)
287
+ return fileResponse;
288
+ return null;
289
+ }
290
+ // Bare paths — redirect to /html/* in all modes.
291
+ const bare = pathname === '/' ? '' : pathname.slice(1).replace(/\/$/, '');
292
+ return Response.redirect(new URL(`${htmlBase}/${bare}`, url.origin), 302);
293
+ }
294
+ // ── Return ───────────────────────────────────────────────────────────
295
+ return {
296
+ handleRequest,
297
+ get htmlRouter() {
298
+ return ssrHtmlRouter;
299
+ },
300
+ get mdRouter() {
301
+ return ssrMdRouter;
302
+ },
303
+ get manifest() {
304
+ return routesManifest;
305
+ },
306
+ get widgetEntries() {
307
+ return discoveredWidgetEntries;
308
+ },
309
+ get shell() {
310
+ return shell;
311
+ },
312
+ };
313
+ }
314
+ //# sourceMappingURL=emroute.server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emroute.server.js","sourceRoot":"","sources":["../../server/emroute.server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AAGjE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAElE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EACL,oBAAoB,EAEpB,qBAAqB,GACtB,MAAM,gCAAgC,CAAC;AAGxC,0EAA0E;AAE1E;;;;GAIG;AACH,SAAS,mBAAmB,CAC1B,QAAwB,EACxB,OAAgB;IAEhB,MAAM,OAAO,GAA2C,EAAE,CAAC;IAE3D,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IAEtC,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,KAAK,EAAE,EAAE;YAAE,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACrD,IAAI,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC1E,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,QAAQ,CAAC,eAAe,EAAE,CAAC;QAChD,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;QAC1B,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACpD,CAAC;IACD,KAAK,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;QACpD,IAAI,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC3C,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,0EAA0E;AAE1E,mDAAmD;AACnD,SAAS,mBAAmB,CAC1B,GAA4B;IAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;YACpD,OAAO,KAAwB,CAAC;QAClC,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,UAAU,IAAI,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,CAAC;YAC5D,OAAO,IAAK,KAAmC,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8DAA8D;AAC9D,KAAK,UAAU,aAAa,CAC1B,OAA8B,EAC9B,OAAgB,EAChB,MAAuB;IAKvB,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IAEtC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC;gBAClD,CAAC,CAAC,KAAK,CAAC,UAAU;gBAClB,CAAC,CAAC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YAE3B,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,WAAW,CAA4B,CAAC;YAC7E,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;YAC1C,IAAI,CAAC,QAAQ;gBAAE,SAAS;YACxB,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACzB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,mCAAmC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC;YAC5B,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAiE,EAAE,CAAC;IACrF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,KAAK;YAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC;IACzD,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC;AAED,0EAA0E;AAE1E,kCAAkC;AAClC,SAAS,cAAc,CAAC,KAAa;IACnC,OAAO;;;;;WAKE,UAAU,CAAC,KAAK,CAAC;;;;;;QAMpB,CAAC;AACT,CAAC;AAED,sDAAsD;AACtD,SAAS,gBAAgB,CACvB,IAAY,EACZ,OAAe,EACf,KAAyB,EACzB,QAAiB;IAEjB,MAAM,WAAW,GAAG,yCAAyC,CAAC;IAC9D,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,oBAAoB,QAAQ,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,eAAe,OAAO,IAAI,OAAO,gBAAgB,CAAC,CAAC;IAEpF,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,UAAU,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACtF,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,0EAA0E;AAC1E,KAAK,UAAU,YAAY,CACzB,OAAgB,EAChB,KAAa;IAEb,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACpD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC1D,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,yEAAyE;AAEzE,yEAAyE;AACzE,8DAA8D;AAC9D,SAAS,mBAAmB,CAAC,GAAQ;IACnC,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,eAAe,EAAE,GAAG,CAAC,eAAe;QACpC,WAAW,EAAE,IAAI,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC;QAC3C,YAAY,EAAE,GAAG,CAAC,YAAY;KAC/B,CAAC;AACJ,CAAC;AAED,0EAA0E;AAE1E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAA2B,EAC3B,OAAgB;IAEhB,MAAM,EACJ,GAAG,GAAG,MAAM,GACb,GAAG,MAAM,CAAC;IAEX,sEAAsE;IACtE,OAAO,CAAC,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;IAEzB,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,IAAI,iBAAiB,CAAC;IAE5E,uEAAuE;IAEvE,IAAI,cAA8B,CAAC;IAEnC,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QAC1B,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IACzC,CAAC;SAAM,CAAC;QACN,MAAM,gBAAgB,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACnE,IAAI,gBAAgB,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,aAAa,oBAAoB,yBAAyB;gBACxD,qEAAqE,CACxE,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAC1C,cAAc,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC;IAED,cAAc,CAAC,aAAa,GAAG,mBAAmB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAE5E,sEAAsE;IAEtE,IAAI,OAAO,GAA+B,MAAM,CAAC,OAAO,CAAC;IACzD,IAAI,WAAW,GAAiE,EAAE,CAAC;IACnF,IAAI,uBAAuB,GAA0B,EAAE,CAAC;IAExD,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACnE,IAAI,eAAe,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACnC,uBAAuB,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,CAAC;QACvD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,uBAAuB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QACvF,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC;QAC5B,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;IACrC,CAAC;IAED,wEAAwE;IAExE,IAAI,aAAa,GAAyB,IAAI,CAAC;IAC/C,IAAI,WAAW,GAAuB,IAAI,CAAC;IAE3C,SAAS,eAAe;QACtB,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACnB,aAAa,GAAG,IAAI,CAAC;YACrB,WAAW,GAAG,IAAI,CAAC;YACnB,OAAO;QACT,CAAC;QAED,aAAa,GAAG,IAAI,aAAa,CAAC,cAAc,CAAC,cAAc,EAAE,QAAQ,CAAC,EAAE;YAC1E,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;YACzD,QAAQ,EAAE,QAAQ;YAClB,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,OAAO;YACP,WAAW;SACZ,CAAC,CAAC;QAEH,WAAW,GAAG,IAAI,WAAW,CAAC,cAAc,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE;YACpE,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;YACzD,QAAQ,EAAE,MAAM;YAChB,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,OAAO;YACP,WAAW;SACZ,CAAC,CAAC;IACL,CAAC;IAED,eAAe,EAAE,CAAC;IAElB,uEAAuE;IAEvE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;IAEvB,wEAAwE;IAExE,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,SAAS,CAAC;IACxC,IAAI,KAAK,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE/C,uDAAuD;IACvD,IAAI,CAAC,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACtD,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,qDAAqD,CAAC,CAAC;IAC1F,CAAC;IAED,wEAAwE;IAExE,KAAK,UAAU,aAAa,CAAC,GAAY;QACvC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;QAE9B,MAAM,QAAQ,GAAG,MAAM,GAAG,GAAG,CAAC;QAC9B,MAAM,UAAU,GAAG,QAAQ,GAAG,GAAG,CAAC;QAElC,sBAAsB;QACtB,IACE,WAAW;YACX,CAAC,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,MAAM,CAAC,EACtD,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACzE,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;gBAClE,CAAC;gBACD,OAAO,IAAI,QAAQ,CAAC,OAAO,EAAE;oBAC3B,MAAM;oBACN,OAAO,EAAE,EAAE,cAAc,EAAE,kDAAkD,EAAE;iBAChF,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,6BAA6B,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC3D,OAAO,IAAI,QAAQ,CAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,IACE,aAAa;YACb,CAAC,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,QAAQ,KAAK,QAAQ,CAAC,EAC1D,CAAC;YACD,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBACpD,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACpB,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;gBAChF,CAAC;gBACD,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;gBACvC,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;gBACzE,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE;oBACxB,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,OAAO,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE;iBACxD,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,6BAA6B,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC3D,OAAO,IAAI,QAAQ,CAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QAED,mFAAmF;QACnF,IACE,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,QAAQ,KAAK,QAAQ;YACxD,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,QAAQ,KAAK,MAAM,EACpD,CAAC;YACD,OAAO,IAAI,QAAQ,CAAC,KAAK,EAAE;gBACzB,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE;aACxD,CAAC,CAAC;QACL,CAAC;QAED,kEAAkE;QAClE,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QACpD,IAAI,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACpD,IAAI,YAAY,CAAC,MAAM,KAAK,GAAG;gBAAE,OAAO,YAAY,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,iDAAiD;QACjD,MAAM,IAAI,GAAG,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC1E,OAAO,QAAQ,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,GAAG,QAAQ,IAAI,IAAI,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5E,CAAC;IAED,wEAAwE;IAExE,OAAO;QACL,aAAa;QACb,IAAI,UAAU;YACZ,OAAO,aAAa,CAAC;QACvB,CAAC;QACD,IAAI,QAAQ;YACV,OAAO,WAAW,CAAC;QACrB,CAAC;QACD,IAAI,QAAQ;YACV,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,IAAI,aAAa;YACf,OAAO,uBAAuB,CAAC;QACjC,CAAC;QACD,IAAI,KAAK;YACP,OAAO,KAAK,CAAC;QACf,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * esbuild Virtual Manifest Plugin
3
+ *
4
+ * Intercepts `emroute:routes` and `emroute:widgets` import specifiers.
5
+ * Reads JSON manifests from the runtime and generates TypeScript modules
6
+ * with `moduleLoaders` (dynamic `import()` calls) in-memory — no .g.ts
7
+ * files on disk.
8
+ *
9
+ * This is the single source of truth: JSON manifest → esbuild bundle.
10
+ */
11
+ import type { Runtime } from '../runtime/abstract.runtime.ts';
12
+ interface ManifestPluginOptions {
13
+ runtime: Runtime;
14
+ /** HTML base path prefix for route patterns (e.g. '/html'). */
15
+ basePath?: string;
16
+ /**
17
+ * Directory prefix to strip from module paths so that import() calls
18
+ * are relative to the entry point (e.g. 'routes/' strips '/routes/').
19
+ */
20
+ stripPrefix?: string;
21
+ /** Absolute directory for resolving relative import() paths in generated code. */
22
+ resolveDir: string;
23
+ }
24
+ type EsbuildPlugin = any;
25
+ export declare function createManifestPlugin(options: ManifestPluginOptions): EsbuildPlugin;
26
+ export {};
@@ -0,0 +1,187 @@
1
+ /**
2
+ * esbuild Virtual Manifest Plugin
3
+ *
4
+ * Intercepts `emroute:routes` and `emroute:widgets` import specifiers.
5
+ * Reads JSON manifests from the runtime and generates TypeScript modules
6
+ * with `moduleLoaders` (dynamic `import()` calls) in-memory — no .g.ts
7
+ * files on disk.
8
+ *
9
+ * This is the single source of truth: JSON manifest → esbuild bundle.
10
+ */
11
+ import { ROUTES_MANIFEST_PATH, WIDGETS_MANIFEST_PATH } from "../runtime/abstract.runtime.js";
12
+ /** Escape a string for use inside a single-quoted JS/TS string literal. */
13
+ function esc(value) {
14
+ return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
15
+ }
16
+ export function createManifestPlugin(options) {
17
+ const { runtime, basePath = '', stripPrefix = '', resolveDir } = options;
18
+ const prefixPattern = (pattern) => basePath ? (pattern === '/' ? basePath : basePath + pattern) : pattern;
19
+ const strip = (p) => stripPrefix && p.startsWith(stripPrefix) ? p.slice(stripPrefix.length) : p;
20
+ return {
21
+ name: 'emroute-manifest',
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ setup(build) {
24
+ // ── Resolve virtual specifiers ──────────────────────────────────
25
+ build.onResolve({ filter: /^emroute:/ },
26
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
27
+ (args) => ({ path: args.path, namespace: 'emroute' }));
28
+ // ── Load virtual modules ────────────────────────────────────────
29
+ build.onLoad({ filter: /.*/, namespace: 'emroute' },
30
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
+ async (args) => {
32
+ if (args.path === 'emroute:routes') {
33
+ return { contents: await generateRoutesModule(), loader: 'ts', resolveDir };
34
+ }
35
+ if (args.path === 'emroute:widgets') {
36
+ return { contents: await generateWidgetsModule(), loader: 'ts', resolveDir };
37
+ }
38
+ return undefined;
39
+ });
40
+ },
41
+ };
42
+ // ── Routes module generator ───────────────────────────────────────
43
+ async function generateRoutesModule() {
44
+ const response = await runtime.query(ROUTES_MANIFEST_PATH);
45
+ if (response.status === 404) {
46
+ return `export const routesManifest = { routes: [], errorBoundaries: [], statusPages: new Map(), moduleLoaders: {} };`;
47
+ }
48
+ const raw = await response.json();
49
+ // Routes array
50
+ const routesArray = (raw.routes ?? [])
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ .map((r) => {
53
+ const filesStr = r.files
54
+ ? `\n files: { ${Object.entries(r.files)
55
+ .filter(([_, v]) => v)
56
+ .map(([k, v]) => `${k}: '${esc(strip(v))}'`)
57
+ .join(', ')} },`
58
+ : '';
59
+ return ` {
60
+ pattern: '${esc(prefixPattern(r.pattern))}',
61
+ type: '${esc(r.type)}',
62
+ modulePath: '${esc(strip(r.modulePath))}',${filesStr}${r.parent ? `\n parent: '${esc(prefixPattern(r.parent))}',` : ''}${r.statusCode ? `\n statusCode: ${r.statusCode},` : ''}
63
+ }`;
64
+ })
65
+ .join(',\n');
66
+ // Error boundaries
67
+ const errorBoundariesArray = (raw.errorBoundaries ?? [])
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
+ .map((e) => ` {
70
+ pattern: '${esc(prefixPattern(e.pattern))}',
71
+ modulePath: '${esc(strip(e.modulePath))}',
72
+ }`)
73
+ .join(',\n');
74
+ // Status pages
75
+ const statusPagesEntries = (raw.statusPages ?? [])
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ .map(([status, route]) => {
78
+ const filesStr = route.files
79
+ ? `, files: { ${Object.entries(route.files)
80
+ .map(([k, v]) => `${k}: '${esc(strip(v))}'`)
81
+ .join(', ')} }`
82
+ : '';
83
+ return ` [${status}, { pattern: '${esc(prefixPattern(route.pattern))}', type: '${esc(route.type)}', modulePath: '${esc(strip(route.modulePath))}', statusCode: ${status}${filesStr} }]`;
84
+ })
85
+ .join(',\n');
86
+ // Error handler
87
+ const errorHandlerCode = raw.errorHandler
88
+ ? `{
89
+ pattern: '${esc(prefixPattern(raw.errorHandler.pattern))}',
90
+ type: '${esc(raw.errorHandler.type)}',
91
+ modulePath: '${esc(strip(raw.errorHandler.modulePath))}',
92
+ }`
93
+ : 'undefined';
94
+ // Module loaders — collect all .ts module paths
95
+ const tsModulePaths = new Set();
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
+ for (const route of (raw.routes ?? [])) {
98
+ if (route.files?.ts)
99
+ tsModulePaths.add(route.files.ts);
100
+ if (route.modulePath.endsWith('.ts'))
101
+ tsModulePaths.add(route.modulePath);
102
+ }
103
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
104
+ for (const boundary of (raw.errorBoundaries ?? [])) {
105
+ tsModulePaths.add(boundary.modulePath);
106
+ }
107
+ if (raw.errorHandler) {
108
+ tsModulePaths.add(raw.errorHandler.modulePath);
109
+ }
110
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
111
+ for (const [_, statusRoute] of (raw.statusPages ?? [])) {
112
+ if (statusRoute.modulePath.endsWith('.ts')) {
113
+ tsModulePaths.add(statusRoute.modulePath);
114
+ }
115
+ }
116
+ const moduleLoadersCode = [...tsModulePaths]
117
+ .map((p) => {
118
+ const key = strip(p);
119
+ const rel = key.replace(/^\.?\//, '');
120
+ return ` '${esc(key)}': () => import('./${esc(rel)}'),`;
121
+ })
122
+ .join('\n');
123
+ return `import type { RoutesManifest } from '@emkodev/emroute';
124
+
125
+ export const routesManifest: RoutesManifest = {
126
+ routes: [
127
+ ${routesArray}
128
+ ],
129
+
130
+ errorBoundaries: [
131
+ ${errorBoundariesArray}
132
+ ],
133
+
134
+ statusPages: new Map([
135
+ ${statusPagesEntries}
136
+ ]),
137
+
138
+ errorHandler: ${errorHandlerCode},
139
+
140
+ moduleLoaders: {
141
+ ${moduleLoadersCode}
142
+ },
143
+ };
144
+ `;
145
+ }
146
+ // ── Widgets module generator ──────────────────────────────────────
147
+ async function generateWidgetsModule() {
148
+ const response = await runtime.query(WIDGETS_MANIFEST_PATH);
149
+ if (response.status === 404) {
150
+ return `export const widgetsManifest = { widgets: [], moduleLoaders: {} };`;
151
+ }
152
+ const entries = await response.json();
153
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
154
+ const widgetEntries = entries.map((e) => {
155
+ const filesStr = e.files
156
+ ? `\n files: { ${Object.entries(e.files)
157
+ .filter(([_, v]) => v)
158
+ .map(([k, v]) => `${k}: '${esc(strip(v))}'`)
159
+ .join(', ')} },`
160
+ : '';
161
+ return ` {
162
+ name: '${esc(e.name)}',
163
+ modulePath: '${esc(strip(e.modulePath))}',
164
+ tagName: '${esc(e.tagName)}',${filesStr}
165
+ }`;
166
+ }).join(',\n');
167
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
168
+ const loaderEntries = entries.map((e) => {
169
+ const key = strip(e.modulePath);
170
+ const rel = key.replace(/^\.?\//, '');
171
+ return ` '${esc(key)}': () => import('./${esc(rel)}'),`;
172
+ }).join('\n');
173
+ return `import type { WidgetsManifest } from '@emkodev/emroute';
174
+
175
+ export const widgetsManifest: WidgetsManifest = {
176
+ widgets: [
177
+ ${widgetEntries}
178
+ ],
179
+
180
+ moduleLoaders: {
181
+ ${loaderEntries}
182
+ },
183
+ };
184
+ `;
185
+ }
186
+ }
187
+ //# sourceMappingURL=esbuild-manifest.plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esbuild-manifest.plugin.js","sourceRoot":"","sources":["../../server/esbuild-manifest.plugin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Standalone Scanning Utilities
3
+ *
4
+ * Runtime-agnostic route and widget scanning. Works with any Runtime
5
+ * that implements query() — used by tests with mock runtimes and by
6
+ * the CLI generate command.
7
+ *
8
+ * Note: BunFsRuntime has these as instance methods with lazy caching.
9
+ * These standalone functions are the same logic without caching.
10
+ */
11
+ import type { Runtime } from '../runtime/abstract.runtime.ts';
12
+ import type { RoutesManifest } from '../src/type/route.type.ts';
13
+ import type { WidgetManifestEntry } from '../src/type/widget.type.ts';
14
+ export interface GeneratorResult extends RoutesManifest {
15
+ warnings: string[];
16
+ }
17
+ /** Generate routes manifest by scanning a directory via Runtime. */
18
+ export declare function generateRoutesManifest(routesDir: string, runtime: Runtime): Promise<GeneratorResult>;
19
+ /**
20
+ * Discover widget modules and companion files by scanning a directory.
21
+ */
22
+ export declare function discoverWidgets(widgetsDir: string, runtime: Runtime, pathPrefix?: string): Promise<WidgetManifestEntry[]>;