@emkodev/emroute 1.6.2 → 1.6.4

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 +63 -13
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  </p>
4
4
 
5
5
  <p align="center">
6
- File-based router with triple rendering. Zero dependencies.
6
+ File-based (but storage-agnostic) router with triple rendering. Zero dependencies.
7
7
  </p>
8
8
 
9
9
  ---
@@ -25,8 +25,8 @@ GET /md/projects/42 → plain Markdown
25
25
  npm add @emkodev/emroute # or bun add, pnpm add, yarn add
26
26
  ```
27
27
 
28
- > emroute ships TypeScript source. Your toolchain must handle `.ts` imports
29
- > (Bun, tsx, esbuild, etc.).
28
+ Works on **Node**, **Bun**, and **Deno**. Node uses compiled JS; Bun and Deno
29
+ use TypeScript source directly.
30
30
 
31
31
  For markdown rendering, add [@emkodev/emkoma](doc/08c-setup-emkoma.md) (built
32
32
  for emroute) or bring your own — [marked](doc/08a-setup-marked.md) and
@@ -134,12 +134,12 @@ publishes to npm. Full analysis:
134
134
 
135
135
  ## Getting Started
136
136
 
137
- See [Setup](doc/01-setup.md) and [First Route](doc/02-first-route.md).
137
+ Pick your runtime: [Bun](doc/01a-setup-bun.md) | [Node](doc/01b-setup-node.md) | [Deno](doc/01c-setup-deno.md)
138
138
 
139
139
  ## Documentation
140
140
 
141
- - [Setup](doc/01-setup.md) install and create a server
142
- - [First route](doc/02-first-route.md) — create your first page
141
+ - Setup — [Bun](doc/01a-setup-bun.md), [Node](doc/01b-setup-node.md), [Deno](doc/01c-setup-deno.md)
142
+ - [First route](doc/02-first-route.md) — route files and rendering modes
143
143
  - [Pages](doc/03-pages.md) — page components, companion files, data fetching
144
144
  - [Routing](doc/04-routing.md) — dynamic segments, catch-all, redirects
145
145
  - [Nesting](doc/05-nesting.md) — layouts, slots, passthrough pages, tips and tricks
@@ -0,0 +1,94 @@
1
+ import type { RoutesManifest } from '../src/type/route.type.ts';
2
+ import type { WidgetManifestEntry } from '../src/type/widget.type.ts';
3
+ export declare const CONTENT_TYPES: Map<string, string>;
4
+ export type FetchParams = Parameters<typeof fetch>;
5
+ export type FetchReturn = ReturnType<typeof fetch>;
6
+ export declare const DEFAULT_ROUTES_DIR = "/routes";
7
+ export declare const DEFAULT_WIDGETS_DIR = "/widgets";
8
+ export declare const ROUTES_MANIFEST_PATH = "/routes.manifest.json";
9
+ export declare const WIDGETS_MANIFEST_PATH = "/widgets.manifest.json";
10
+ export declare const EMROUTE_EXTERNALS: readonly ["@emkodev/emroute/spa", "@emkodev/emroute/overlay", "@emkodev/emroute"];
11
+ export interface RuntimeConfig {
12
+ routesDir?: string;
13
+ widgetsDir?: string;
14
+ /** SPA mode. When 'none', bundling is skipped entirely. */
15
+ spa?: 'none' | 'leaf' | 'root' | 'only';
16
+ /** Consumer's SPA entry point (e.g. '/main.ts'). Skips app bundle when absent. */
17
+ entryPoint?: string;
18
+ bundlePaths?: {
19
+ emroute: string;
20
+ app: string;
21
+ widgets?: string;
22
+ };
23
+ }
24
+ /**
25
+ * Abstract resource provider. Speaks Request/Response (ADR-1).
26
+ *
27
+ * Three access patterns:
28
+ * - `handle()` — raw passthrough, server forwards browser requests as-is.
29
+ * - `query()` — read. Returns Response, or string when `{ as: "text" }`.
30
+ * - `command()` — write (PUT by default, override with `{ method }` in options).
31
+ *
32
+ * Includes manifest resolution: when `query(ROUTES_MANIFEST_PATH)` or
33
+ * `query(WIDGETS_MANIFEST_PATH)` returns 404, the runtime scans the
34
+ * configured directories and caches the result.
35
+ */
36
+ export declare abstract class Runtime {
37
+ readonly config: RuntimeConfig;
38
+ constructor(config?: RuntimeConfig);
39
+ /** Concrete runtimes implement this. Accepts the same args as `fetch()`. */
40
+ abstract handle(resource: FetchParams[0], init?: FetchParams[1]): FetchReturn;
41
+ /**
42
+ * Read with `{ as: "text" }` — skip metadata, return contents only.
43
+ * Semantically equivalent to `Accept: text/plain`; `as` exists for type safety.
44
+ */
45
+ abstract query(resource: FetchParams[0], options: FetchParams[1] & {
46
+ as: 'text';
47
+ }): Promise<string>;
48
+ /** Read — returns full Response with headers, status, body. */
49
+ abstract query(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn;
50
+ /** Write. Defaults to PUT; pass `{ method: "DELETE" }` etc. to override. */
51
+ command(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn;
52
+ /**
53
+ * Dynamically import a module from this runtime's storage.
54
+ * Used by the server for SSR imports of `.page.ts` and `.widget.ts` files.
55
+ */
56
+ loadModule(_path: string): Promise<unknown>;
57
+ static transpile(_ts: string): Promise<string>;
58
+ /**
59
+ * Build client bundles. Called by the server after manifests are written.
60
+ * No-op by default — override in runtimes that support bundling.
61
+ */
62
+ bundle(): Promise<void>;
63
+ /**
64
+ * Generate an HTML shell (`index.html`) if one doesn't already exist.
65
+ * Writes through `this.command()` so it works for any runtime.
66
+ */
67
+ protected writeShell(paths: {
68
+ emroute: string;
69
+ app: string;
70
+ widgets?: string;
71
+ }): Promise<void>;
72
+ static compress(_data: Uint8Array, _encoding: 'br' | 'gzip'): Promise<Uint8Array>;
73
+ /** Stop the bundler subprocess if running. No-op by default. */
74
+ static stopBundler(): Promise<void>;
75
+ private routesManifestCache;
76
+ private widgetsManifestCache;
77
+ /** Clear cached manifests so the next query triggers a fresh scan. */
78
+ invalidateManifests(): void;
79
+ /**
80
+ * Resolve the routes manifest. Called when the concrete runtime returns
81
+ * 404 for ROUTES_MANIFEST_PATH. Scans `config.routesDir` (or default).
82
+ */
83
+ resolveRoutesManifest(): Promise<Response>;
84
+ /**
85
+ * Resolve the widgets manifest. Called when the concrete runtime returns
86
+ * 404 for WIDGETS_MANIFEST_PATH. Scans `config.widgetsDir` (or default).
87
+ */
88
+ resolveWidgetsManifest(): Promise<Response>;
89
+ protected walkDirectory(dir: string): AsyncGenerator<string>;
90
+ protected scanRoutes(routesDir: string): Promise<RoutesManifest & {
91
+ warnings: string[];
92
+ }>;
93
+ protected scanWidgets(widgetsDir: string, pathPrefix?: string): Promise<WidgetManifestEntry[]>;
94
+ }
@@ -0,0 +1,339 @@
1
+ import { filePathToPattern, getPageFileType, getRouteType, sortRoutesBySpecificity, } from "../src/route/route.matcher.js";
2
+ export const CONTENT_TYPES = new Map([
3
+ ['.html', 'text/html; charset=utf-8'],
4
+ ['.css', 'text/css; charset=utf-8'],
5
+ ['.js', 'application/javascript; charset=utf-8'],
6
+ ['.mjs', 'application/javascript; charset=utf-8'],
7
+ ['.ts', 'text/typescript; charset=utf-8'],
8
+ ['.json', 'application/json; charset=utf-8'],
9
+ ['.md', 'text/plain; charset=utf-8'],
10
+ ['.txt', 'text/plain; charset=utf-8'],
11
+ ['.wasm', 'application/wasm'],
12
+ ['.map', 'application/json; charset=utf-8'],
13
+ ['.png', 'image/png'],
14
+ ['.jpg', 'image/jpeg'],
15
+ ['.jpeg', 'image/jpeg'],
16
+ ['.gif', 'image/gif'],
17
+ ['.svg', 'image/svg+xml'],
18
+ ['.ico', 'image/x-icon'],
19
+ ['.webp', 'image/webp'],
20
+ ['.avif', 'image/avif'],
21
+ ['.woff', 'font/woff'],
22
+ ['.woff2', 'font/woff2'],
23
+ ['.ttf', 'font/ttf'],
24
+ ]);
25
+ export const DEFAULT_ROUTES_DIR = '/routes';
26
+ export const DEFAULT_WIDGETS_DIR = '/widgets';
27
+ export const ROUTES_MANIFEST_PATH = '/routes.manifest.json';
28
+ export const WIDGETS_MANIFEST_PATH = '/widgets.manifest.json';
29
+ export const EMROUTE_EXTERNALS = [
30
+ '@emkodev/emroute/spa',
31
+ '@emkodev/emroute/overlay',
32
+ '@emkodev/emroute',
33
+ ];
34
+ /**
35
+ * Abstract resource provider. Speaks Request/Response (ADR-1).
36
+ *
37
+ * Three access patterns:
38
+ * - `handle()` — raw passthrough, server forwards browser requests as-is.
39
+ * - `query()` — read. Returns Response, or string when `{ as: "text" }`.
40
+ * - `command()` — write (PUT by default, override with `{ method }` in options).
41
+ *
42
+ * Includes manifest resolution: when `query(ROUTES_MANIFEST_PATH)` or
43
+ * `query(WIDGETS_MANIFEST_PATH)` returns 404, the runtime scans the
44
+ * configured directories and caches the result.
45
+ */
46
+ export class Runtime {
47
+ config;
48
+ constructor(config = {}) {
49
+ this.config = config;
50
+ this.config = config;
51
+ }
52
+ /** Write. Defaults to PUT; pass `{ method: "DELETE" }` etc. to override. */
53
+ command(resource, options) {
54
+ return this.handle(resource, { method: 'PUT', ...options });
55
+ }
56
+ /**
57
+ * Dynamically import a module from this runtime's storage.
58
+ * Used by the server for SSR imports of `.page.ts` and `.widget.ts` files.
59
+ */
60
+ loadModule(_path) {
61
+ throw new Error(`loadModule not implemented for ${this.constructor.name}`);
62
+ }
63
+ static transpile(_ts) {
64
+ throw new Error('Not implemented');
65
+ }
66
+ /**
67
+ * Build client bundles. Called by the server after manifests are written.
68
+ * No-op by default — override in runtimes that support bundling.
69
+ */
70
+ bundle() {
71
+ return Promise.resolve();
72
+ }
73
+ /**
74
+ * Generate an HTML shell (`index.html`) if one doesn't already exist.
75
+ * Writes through `this.command()` so it works for any runtime.
76
+ */
77
+ async writeShell(paths) {
78
+ if ((await this.query('/index.html')).status !== 404)
79
+ return;
80
+ const imports = Object.fromEntries(EMROUTE_EXTERNALS.map((pkg) => [pkg, paths.emroute]));
81
+ const importMap = JSON.stringify({ imports }, null, 2);
82
+ const scripts = [
83
+ `<script type="importmap">\n${importMap}\n </script>`,
84
+ ];
85
+ if (this.config.entryPoint) {
86
+ scripts.push(`<script type="module" src="${paths.app}"></script>`);
87
+ }
88
+ const html = `<!DOCTYPE html>
89
+ <html>
90
+ <head>
91
+ <meta charset="utf-8">
92
+ <meta name="viewport" content="width=device-width, initial-scale=1">
93
+ <title>emroute</title>
94
+ <style>@view-transition { navigation: auto; } router-slot { display: contents; }</style>
95
+ </head>
96
+ <body>
97
+ <router-slot></router-slot>
98
+ ${scripts.join('\n ')}
99
+ </body>
100
+ </html>`;
101
+ await this.command('/index.html', { body: html });
102
+ }
103
+ static compress(_data, _encoding) {
104
+ throw new Error('Not implemented');
105
+ }
106
+ /** Stop the bundler subprocess if running. No-op by default. */
107
+ static stopBundler() {
108
+ return Promise.resolve();
109
+ }
110
+ // ── Manifest resolution ─────────────────────────────────────────────
111
+ routesManifestCache = null;
112
+ widgetsManifestCache = null;
113
+ /** Clear cached manifests so the next query triggers a fresh scan. */
114
+ invalidateManifests() {
115
+ this.routesManifestCache = null;
116
+ this.widgetsManifestCache = null;
117
+ }
118
+ /**
119
+ * Resolve the routes manifest. Called when the concrete runtime returns
120
+ * 404 for ROUTES_MANIFEST_PATH. Scans `config.routesDir` (or default).
121
+ */
122
+ async resolveRoutesManifest() {
123
+ if (this.routesManifestCache)
124
+ return this.routesManifestCache.clone();
125
+ const routesDir = this.config.routesDir ?? DEFAULT_ROUTES_DIR;
126
+ // Check if directory exists by querying it
127
+ const dirResponse = await this.query(routesDir + '/');
128
+ if (dirResponse.status === 404) {
129
+ return new Response('Not Found', { status: 404 });
130
+ }
131
+ const { warnings, ...manifest } = await this.scanRoutes(routesDir);
132
+ for (const w of warnings)
133
+ console.warn(w);
134
+ const json = {
135
+ routes: manifest.routes,
136
+ errorBoundaries: manifest.errorBoundaries,
137
+ statusPages: [...manifest.statusPages.entries()],
138
+ errorHandler: manifest.errorHandler,
139
+ };
140
+ this.routesManifestCache = Response.json(json);
141
+ return this.routesManifestCache.clone();
142
+ }
143
+ /**
144
+ * Resolve the widgets manifest. Called when the concrete runtime returns
145
+ * 404 for WIDGETS_MANIFEST_PATH. Scans `config.widgetsDir` (or default).
146
+ */
147
+ async resolveWidgetsManifest() {
148
+ if (this.widgetsManifestCache)
149
+ return this.widgetsManifestCache.clone();
150
+ const widgetsDir = this.config.widgetsDir ?? DEFAULT_WIDGETS_DIR;
151
+ const dirResponse = await this.query(widgetsDir + '/');
152
+ if (dirResponse.status === 404) {
153
+ return new Response('Not Found', { status: 404 });
154
+ }
155
+ const entries = await this.scanWidgets(widgetsDir, widgetsDir.replace(/^\//, ''));
156
+ this.widgetsManifestCache = Response.json(entries);
157
+ return this.widgetsManifestCache.clone();
158
+ }
159
+ // ── Scanning ──────────────────────────────────────────────────────────
160
+ async *walkDirectory(dir) {
161
+ const trailingDir = dir.endsWith('/') ? dir : dir + '/';
162
+ const response = await this.query(trailingDir);
163
+ const entries = await response.json();
164
+ for (const entry of entries) {
165
+ const path = `${trailingDir}${entry}`;
166
+ if (entry.endsWith('/')) {
167
+ yield* this.walkDirectory(path);
168
+ }
169
+ else {
170
+ yield path;
171
+ }
172
+ }
173
+ }
174
+ async scanRoutes(routesDir) {
175
+ const pageFiles = [];
176
+ const redirects = [];
177
+ const errorBoundaries = [];
178
+ const statusPages = new Map();
179
+ let errorHandler;
180
+ const allFiles = [];
181
+ for await (const file of this.walkDirectory(routesDir)) {
182
+ allFiles.push(file);
183
+ }
184
+ for (const filePath of allFiles) {
185
+ const relativePath = filePath.replace(`${routesDir}/`, '');
186
+ const filename = relativePath.split('/').pop() ?? '';
187
+ if (filename === 'index.error.ts' && relativePath === 'index.error.ts') {
188
+ errorHandler = {
189
+ pattern: '/',
190
+ type: 'error',
191
+ modulePath: filePath,
192
+ };
193
+ continue;
194
+ }
195
+ const cssFileType = getPageFileType(filename);
196
+ if (cssFileType === 'css') {
197
+ const pattern = filePathToPattern(relativePath);
198
+ pageFiles.push({ path: filePath, pattern, fileType: 'css' });
199
+ continue;
200
+ }
201
+ const routeType = getRouteType(filename);
202
+ if (!routeType)
203
+ continue;
204
+ const statusMatch = filename.match(/^(\d{3})\.page\.(ts|html|md)$/);
205
+ if (statusMatch) {
206
+ const statusCode = parseInt(statusMatch[1], 10);
207
+ const fileType = getPageFileType(filename);
208
+ if (fileType) {
209
+ const existing = statusPages.get(statusCode);
210
+ if (existing) {
211
+ existing.files ??= {};
212
+ existing.files[fileType] = filePath;
213
+ existing.modulePath = existing.files.ts ?? existing.files.html ?? existing.files.md ??
214
+ '';
215
+ }
216
+ else {
217
+ const files = { [fileType]: filePath };
218
+ statusPages.set(statusCode, {
219
+ pattern: `/${statusCode}`,
220
+ type: 'page',
221
+ modulePath: filePath,
222
+ statusCode,
223
+ files,
224
+ });
225
+ }
226
+ }
227
+ continue;
228
+ }
229
+ const pattern = filePathToPattern(relativePath);
230
+ if (routeType === 'error') {
231
+ const boundaryPattern = pattern.replace(/\/[^/]+$/, '') || '/';
232
+ errorBoundaries.push({ pattern: boundaryPattern, modulePath: filePath });
233
+ continue;
234
+ }
235
+ if (routeType === 'redirect') {
236
+ redirects.push({ pattern, type: 'redirect', modulePath: filePath });
237
+ continue;
238
+ }
239
+ const fileType = getPageFileType(filename);
240
+ if (fileType) {
241
+ pageFiles.push({ path: filePath, pattern, fileType });
242
+ }
243
+ }
244
+ // Group files by pattern
245
+ const groups = new Map();
246
+ for (const { path, pattern, fileType } of pageFiles) {
247
+ let group = groups.get(pattern);
248
+ if (!group) {
249
+ group = { pattern, files: {} };
250
+ const segments = pattern.split('/').filter(Boolean);
251
+ if (segments.length > 1) {
252
+ group.parent = '/' + segments.slice(0, -1).join('/');
253
+ }
254
+ groups.set(pattern, group);
255
+ }
256
+ const existing = group.files[fileType];
257
+ if (existing?.includes('/index.page.') && !path.includes('/index.page.')) {
258
+ continue;
259
+ }
260
+ group.files[fileType] = path;
261
+ }
262
+ // Detect collisions
263
+ const warnings = [];
264
+ for (const [pattern, group] of groups) {
265
+ const filePaths = Object.values(group.files).filter(Boolean);
266
+ const hasIndex = filePaths.some((p) => p?.includes('/index.page.'));
267
+ const hasFlat = filePaths.some((p) => p && !p.includes('/index.page.'));
268
+ if (hasIndex && hasFlat) {
269
+ warnings.push(`Warning: Mixed file structure for ${pattern}:\n` +
270
+ filePaths.map((p) => ` ${p}`).join('\n') +
271
+ `\n Both folder/index and flat files detected`);
272
+ }
273
+ }
274
+ // Convert groups to RouteConfig array
275
+ const routes = [];
276
+ for (const [_, group] of groups) {
277
+ const modulePath = group.files.ts ?? group.files.html ?? group.files.md ?? '';
278
+ if (!modulePath)
279
+ continue;
280
+ const route = {
281
+ pattern: group.pattern,
282
+ type: 'page',
283
+ modulePath,
284
+ files: group.files,
285
+ };
286
+ if (group.parent)
287
+ route.parent = group.parent;
288
+ routes.push(route);
289
+ }
290
+ routes.push(...redirects);
291
+ const sortedRoutes = sortRoutesBySpecificity(routes);
292
+ return {
293
+ routes: sortedRoutes,
294
+ errorBoundaries,
295
+ statusPages,
296
+ errorHandler,
297
+ warnings,
298
+ };
299
+ }
300
+ async scanWidgets(widgetsDir, pathPrefix) {
301
+ const COMPANION_EXTENSIONS = ['html', 'md', 'css'];
302
+ const WIDGET_FILE_SUFFIX = '.widget.ts';
303
+ const entries = [];
304
+ const trailingDir = widgetsDir.endsWith('/') ? widgetsDir : widgetsDir + '/';
305
+ const response = await this.query(trailingDir);
306
+ const listing = await response.json();
307
+ for (const item of listing) {
308
+ if (!item.endsWith('/'))
309
+ continue;
310
+ const name = item.slice(0, -1);
311
+ const moduleFile = `${name}${WIDGET_FILE_SUFFIX}`;
312
+ const modulePath = `${trailingDir}${name}/${moduleFile}`;
313
+ if ((await this.query(modulePath)).status === 404)
314
+ continue;
315
+ const prefix = pathPrefix ? `${pathPrefix}/` : '';
316
+ const entry = {
317
+ name,
318
+ modulePath: `${prefix}${name}/${moduleFile}`,
319
+ tagName: `widget-${name}`,
320
+ };
321
+ const files = {};
322
+ let hasFiles = false;
323
+ for (const ext of COMPANION_EXTENSIONS) {
324
+ const companionFile = `${name}.widget.${ext}`;
325
+ const companionPath = `${trailingDir}${name}/${companionFile}`;
326
+ if ((await this.query(companionPath)).status !== 404) {
327
+ files[ext] = `${prefix}${name}/${companionFile}`;
328
+ hasFiles = true;
329
+ }
330
+ }
331
+ if (hasFiles)
332
+ entry.files = files;
333
+ entries.push(entry);
334
+ }
335
+ entries.sort((a, b) => a.name.localeCompare(b.name));
336
+ return entries;
337
+ }
338
+ }
339
+ //# sourceMappingURL=abstract.runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract.runtime.js","sourceRoot":"","sources":["../../runtime/abstract.runtime.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,uBAAuB,GACxB,MAAM,+BAA+B,CAAC;AASvC,MAAM,CAAC,MAAM,aAAa,GAAwB,IAAI,GAAG,CAAiB;IACxE,CAAC,OAAO,EAAE,0BAA0B,CAAC;IACrC,CAAC,MAAM,EAAE,yBAAyB,CAAC;IACnC,CAAC,KAAK,EAAE,uCAAuC,CAAC;IAChD,CAAC,MAAM,EAAE,uCAAuC,CAAC;IACjD,CAAC,KAAK,EAAE,gCAAgC,CAAC;IACzC,CAAC,OAAO,EAAE,iCAAiC,CAAC;IAC5C,CAAC,KAAK,EAAE,2BAA2B,CAAC;IACpC,CAAC,MAAM,EAAE,2BAA2B,CAAC;IACrC,CAAC,OAAO,EAAE,kBAAkB,CAAC;IAC7B,CAAC,MAAM,EAAE,iCAAiC,CAAC;IAC3C,CAAC,MAAM,EAAE,WAAW,CAAC;IACrB,CAAC,MAAM,EAAE,YAAY,CAAC;IACtB,CAAC,OAAO,EAAE,YAAY,CAAC;IACvB,CAAC,MAAM,EAAE,WAAW,CAAC;IACrB,CAAC,MAAM,EAAE,eAAe,CAAC;IACzB,CAAC,MAAM,EAAE,cAAc,CAAC;IACxB,CAAC,OAAO,EAAE,YAAY,CAAC;IACvB,CAAC,OAAO,EAAE,YAAY,CAAC;IACvB,CAAC,OAAO,EAAE,WAAW,CAAC;IACtB,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,MAAM,EAAE,UAAU,CAAC;CACrB,CAAC,CAAC;AAKH,MAAM,CAAC,MAAM,kBAAkB,GAAG,SAAS,CAAC;AAC5C,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAC9C,MAAM,CAAC,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAC5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC;AAE9D,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,sBAAsB;IACtB,0BAA0B;IAC1B,kBAAkB;CACV,CAAC;AAgBX;;;;;;;;;;;GAWG;AACH,MAAM,OAAgB,OAAO;IACN;IAArB,YAAqB,SAAwB,EAAE;QAA1B,WAAM,GAAN,MAAM,CAAoB;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAkBD,4EAA4E;IAC5E,OAAO,CAAC,QAAwB,EAAE,OAAwB;QACxD,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,KAAa;QACtB,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,MAAM,CAAC,SAAS,CAAC,GAAW;QAC1B,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;IAED;;;OAGG;IACH,MAAM;QACJ,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACO,KAAK,CAAC,UAAU,CACxB,KAAyD;QAEzD,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO;QAE7D,MAAM,OAAO,GAAuD,MAAM,CAAC,WAAW,CACpF,iBAAiB,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CACC,CAAC;QACxD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAEvD,MAAM,OAAO,GAAG;YACd,8BAA8B,SAAS,eAAe;SACvD,CAAC;QACF,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,8BAA8B,KAAK,CAAC,GAAG,aAAa,CAAC,CAAC;QACrE,CAAC;QAED,MAAM,IAAI,GAAG;;;;;;;;;;IAUb,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;;QAEhB,CAAC;QAEL,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,CAAC,QAAQ,CACb,KAAiB,EACjB,SAAwB;QAExB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;IAED,gEAAgE;IAChE,MAAM,CAAC,WAAW;QAChB,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAED,uEAAuE;IAE/D,mBAAmB,GAAoB,IAAI,CAAC;IAC5C,oBAAoB,GAAoB,IAAI,CAAC;IAErD,sEAAsE;IACtE,mBAAmB;QACjB,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;QAChC,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;IACnC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,qBAAqB;QACzB,IAAI,IAAI,CAAC,mBAAmB;YAAE,OAAO,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;QAEtE,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,kBAAkB,CAAC;QAE9D,2CAA2C;QAC3C,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC;QACtD,IAAI,WAAW,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC/B,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QACnE,KAAK,MAAM,CAAC,IAAI,QAAQ;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAE1C,MAAM,IAAI,GAAG;YACX,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,eAAe,EAAE,QAAQ,CAAC,eAAe;YACzC,WAAW,EAAE,CAAC,GAAG,QAAQ,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YAChD,YAAY,EAAE,QAAQ,CAAC,YAAY;SACpC,CAAC;QAEF,IAAI,CAAC,mBAAmB,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC,mBAAmB,CAAC,KAAK,EAAE,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,sBAAsB;QAC1B,IAAI,IAAI,CAAC,oBAAoB;YAAE,OAAO,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;QAExE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,IAAI,mBAAmB,CAAC;QAEjE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;QACvD,IAAI,WAAW,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YAC/B,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;QAClF,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;IAC3C,CAAC;IAED,yEAAyE;IAE/D,KAAK,CAAC,CAAC,aAAa,CAAC,GAAW;QACxC,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;QACxD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAa,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEhD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,GAAG,WAAW,GAAG,KAAK,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,CAAC;YACb,CAAC;QACH,CAAC;IACH,CAAC;IAES,KAAK,CAAC,UAAU,CAAC,SAAiB;QAC1C,MAAM,SAAS,GAIV,EAAE,CAAC;QACR,MAAM,SAAS,GAAkB,EAAE,CAAC;QACpC,MAAM,eAAe,GAAoB,EAAE,CAAC;QAC5C,MAAM,WAAW,GAAG,IAAI,GAAG,EAAuB,CAAC;QACnD,IAAI,YAAqC,CAAC;QAE1C,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;YACvD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAChC,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;YAErD,IAAI,QAAQ,KAAK,gBAAgB,IAAI,YAAY,KAAK,gBAAgB,EAAE,CAAC;gBACvE,YAAY,GAAG;oBACb,OAAO,EAAE,GAAG;oBACZ,IAAI,EAAE,OAAO;oBACb,UAAU,EAAE,QAAQ;iBACrB,CAAC;gBACF,SAAS;YACX,CAAC;YAED,MAAM,WAAW,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;YAC9C,IAAI,WAAW,KAAK,KAAK,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;gBAChD,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC7D,SAAS;YACX,CAAC;YAED,MAAM,SAAS,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,CAAC,SAAS;gBAAE,SAAS;YAEzB,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACpE,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,UAAU,GAAG,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAChD,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;gBAC3C,IAAI,QAAQ,EAAE,CAAC;oBACb,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;oBAC7C,IAAI,QAAQ,EAAE,CAAC;wBACb,QAAQ,CAAC,KAAK,KAAK,EAAE,CAAC;wBACtB,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;wBACpC,QAAQ,CAAC,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE;4BACjF,EAAE,CAAC;oBACP,CAAC;yBAAM,CAAC;wBACN,MAAM,KAAK,GAAe,EAAE,CAAC,QAAQ,CAAC,EAAE,QAAQ,EAAE,CAAC;wBACnD,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE;4BAC1B,OAAO,EAAE,IAAI,UAAU,EAAE;4BACzB,IAAI,EAAE,MAAM;4BACZ,UAAU,EAAE,QAAQ;4BACpB,UAAU;4BACV,KAAK;yBACN,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC;gBACD,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;YAEhD,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC;gBAC1B,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC;gBAC/D,eAAe,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACzE,SAAS;YACX,CAAC;YAED,IAAI,SAAS,KAAK,UAAU,EAAE,CAAC;gBAC7B,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACpE,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;YAC3C,IAAI,QAAQ,EAAE,CAAC;gBACb,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;YACxD,CAAC;QACH,CAAC;QAED,yBAAyB;QACzB,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmE,CAAC;QAC1F,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,SAAS,EAAE,CAAC;YACpD,IAAI,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;gBAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBACpD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxB,KAAK,CAAC,MAAM,GAAG,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACvD,CAAC;gBACD,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC7B,CAAC;YACD,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACvC,IAAI,QAAQ,EAAE,QAAQ,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACzE,SAAS;YACX,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;QAC/B,CAAC;QAED,oBAAoB;QACpB,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YACtC,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAC7D,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YACpE,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;YACxE,IAAI,QAAQ,IAAI,OAAO,EAAE,CAAC;gBACxB,QAAQ,CAAC,IAAI,CACX,qCAAqC,OAAO,KAAK;oBAC/C,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;oBAC5C,kDAAkD,CACrD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,sCAAsC;QACtC,MAAM,MAAM,GAAkB,EAAE,CAAC;QACjC,KAAK,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;YAC9E,IAAI,CAAC,UAAU;gBAAE,SAAS;YAC1B,MAAM,KAAK,GAAgB;gBACzB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,IAAI,EAAE,MAAM;gBACZ,UAAU;gBACV,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB,CAAC;YACF,IAAI,KAAK,CAAC,MAAM;gBAAE,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;QAC1B,MAAM,YAAY,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAErD,OAAO;YACL,MAAM,EAAE,YAAY;YACpB,eAAe;YACf,WAAW;YACX,YAAY;YACZ,QAAQ;SACT,CAAC;IACJ,CAAC;IAES,KAAK,CAAC,WAAW,CACzB,UAAkB,EAClB,UAAmB;QAEnB,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAU,CAAC;QAC5D,MAAM,kBAAkB,GAAG,YAAY,CAAC;QACxC,MAAM,OAAO,GAA0B,EAAE,CAAC;QAE1C,MAAM,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC;QAC7E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAa,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAEhD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,SAAS;YAElC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,UAAU,GAAG,GAAG,IAAI,GAAG,kBAAkB,EAAE,CAAC;YAClD,MAAM,UAAU,GAAG,GAAG,WAAW,GAAG,IAAI,IAAI,UAAU,EAAE,CAAC;YAEzD,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG;gBAAE,SAAS;YAE5D,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,MAAM,KAAK,GAAwB;gBACjC,IAAI;gBACJ,UAAU,EAAE,GAAG,MAAM,GAAG,IAAI,IAAI,UAAU,EAAE;gBAC5C,OAAO,EAAE,UAAU,IAAI,EAAE;aAC1B,CAAC;YAEF,MAAM,KAAK,GAAiD,EAAE,CAAC;YAC/D,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,KAAK,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;gBACvC,MAAM,aAAa,GAAG,GAAG,IAAI,WAAW,GAAG,EAAE,CAAC;gBAC9C,MAAM,aAAa,GAAG,GAAG,WAAW,GAAG,IAAI,IAAI,aAAa,EAAE,CAAC;gBAC/D,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBACrD,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,MAAM,GAAG,IAAI,IAAI,aAAa,EAAE,CAAC;oBACjD,QAAQ,GAAG,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;YAED,IAAI,QAAQ;gBAAE,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACrD,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * esbuild Runtime Loader Plugin
3
+ *
4
+ * Intercepts file resolution so esbuild reads source files through the
5
+ * runtime's `query()` method instead of the filesystem. This allows
6
+ * bundling to work with any Runtime implementation (filesystem, SQLite,
7
+ * in-memory, etc.).
8
+ *
9
+ * The plugin intercepts `.ts` and `.js` imports that resolve under the
10
+ * virtual root and loads their contents from the runtime.
11
+ */
12
+ import type { Runtime } from '../../runtime/abstract.runtime.ts';
13
+ interface RuntimeLoaderOptions {
14
+ runtime: Runtime;
15
+ /**
16
+ * The filesystem root that esbuild would normally resolve paths against.
17
+ * Paths starting with this prefix are stripped to produce runtime paths
18
+ * (e.g. `/app/root/routes/index.page.ts` → `/routes/index.page.ts`).
19
+ * For runtimes without a filesystem root, pass an empty string.
20
+ */
21
+ root: string;
22
+ }
23
+ type EsbuildPlugin = any;
24
+ export declare function createRuntimeLoaderPlugin(options: RuntimeLoaderOptions): EsbuildPlugin;
25
+ export {};
@@ -0,0 +1,72 @@
1
+ /**
2
+ * esbuild Runtime Loader Plugin
3
+ *
4
+ * Intercepts file resolution so esbuild reads source files through the
5
+ * runtime's `query()` method instead of the filesystem. This allows
6
+ * bundling to work with any Runtime implementation (filesystem, SQLite,
7
+ * in-memory, etc.).
8
+ *
9
+ * The plugin intercepts `.ts` and `.js` imports that resolve under the
10
+ * virtual root and loads their contents from the runtime.
11
+ */
12
+ export function createRuntimeLoaderPlugin(options) {
13
+ const { runtime, root } = options;
14
+ return {
15
+ name: 'emroute-runtime-loader',
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ setup(build) {
18
+ // Intercept .ts and .js file resolution — redirect to 'runtime' namespace
19
+ // Only intercepts files that resolve under the runtime root.
20
+ build.onResolve({ filter: /\.[tj]s$/ },
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ (args) => {
23
+ // Skip bare specifiers (node_modules, packages)
24
+ if (!args.path.startsWith('.') && !args.path.startsWith('/'))
25
+ return undefined;
26
+ // Skip if already in a custom namespace (except 'runtime' for nested imports)
27
+ // Entry points have namespace '' (empty string)
28
+ if (args.namespace !== 'file' && args.namespace !== 'runtime' && args.namespace !== '')
29
+ return undefined;
30
+ let absPath;
31
+ if (args.path.startsWith('/')) {
32
+ absPath = args.path;
33
+ }
34
+ else if (args.resolveDir) {
35
+ absPath = args.resolveDir + '/' + args.path;
36
+ }
37
+ else {
38
+ return undefined;
39
+ }
40
+ // Normalize ../ and ./ segments
41
+ const parts = absPath.split('/');
42
+ const normalized = [];
43
+ for (const part of parts) {
44
+ if (part === '..')
45
+ normalized.pop();
46
+ else if (part !== '.' && part !== '')
47
+ normalized.push(part);
48
+ }
49
+ absPath = '/' + normalized.join('/');
50
+ // Only intercept files under the runtime root
51
+ if (root && !absPath.startsWith(root + '/'))
52
+ return undefined;
53
+ return { path: absPath, namespace: 'runtime' };
54
+ });
55
+ // Load file contents from the runtime
56
+ build.onLoad({ filter: /.*/, namespace: 'runtime' },
57
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
58
+ async (args) => {
59
+ // Strip root prefix to get runtime path (e.g. /app/root/routes/x.ts → /routes/x.ts)
60
+ const runtimePath = root && args.path.startsWith(root)
61
+ ? args.path.slice(root.length)
62
+ : args.path;
63
+ const contents = await runtime.query(runtimePath, { as: 'text' });
64
+ const ext = args.path.slice(args.path.lastIndexOf('.') + 1);
65
+ const loader = ext === 'ts' ? 'ts' : 'js';
66
+ const resolveDir = args.path.slice(0, args.path.lastIndexOf('/'));
67
+ return { contents, loader, resolveDir };
68
+ });
69
+ },
70
+ };
71
+ }
72
+ //# sourceMappingURL=esbuild-runtime-loader.plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esbuild-runtime-loader.plugin.js","sourceRoot":"","sources":["../../../runtime/bun/esbuild-runtime-loader.plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAkBH,MAAM,UAAU,yBAAyB,CAAC,OAA6B;IACrE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IAElC,OAAO;QACL,IAAI,EAAE,wBAAwB;QAE9B,8DAA8D;QAC9D,KAAK,CAAC,KAAU;YACd,0EAA0E;YAC1E,6DAA6D;YAC7D,KAAK,CAAC,SAAS,CACb,EAAE,MAAM,EAAE,UAAU,EAAE;YACtB,8DAA8D;YAC9D,CAAC,IAAS,EAAE,EAAE;gBACZ,gDAAgD;gBAChD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;oBAAE,OAAO,SAAS,CAAC;gBAC/E,8EAA8E;gBAC9E,gDAAgD;gBAChD,IAAI,IAAI,CAAC,SAAS,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,EAAE;oBAAE,OAAO,SAAS,CAAC;gBAEzG,IAAI,OAAe,CAAC;gBACpB,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC9B,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;gBACtB,CAAC;qBAAM,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;oBAC3B,OAAO,GAAG,IAAI,CAAC,UAAU,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC;gBAC9C,CAAC;qBAAM,CAAC;oBACN,OAAO,SAAS,CAAC;gBACnB,CAAC;gBAED,gCAAgC;gBAChC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBACjC,MAAM,UAAU,GAAa,EAAE,CAAC;gBAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,IAAI,IAAI,KAAK,IAAI;wBAAE,UAAU,CAAC,GAAG,EAAE,CAAC;yBAC/B,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,EAAE;wBAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9D,CAAC;gBACD,OAAO,GAAG,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAErC,8CAA8C;gBAC9C,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC;oBAAE,OAAO,SAAS,CAAC;gBAE9D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;YACjD,CAAC,CACF,CAAC;YAEF,sCAAsC;YACtC,KAAK,CAAC,MAAM,CACV,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE;YACtC,8DAA8D;YAC9D,KAAK,EAAE,IAAS,EAAE,EAAE;gBAClB,oFAAoF;gBACpF,MAAM,WAAW,GAAG,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;oBACpD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;oBAC9B,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;gBAEd,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;gBAClE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5D,MAAM,MAAM,GAAG,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;gBAElE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YAC1C,CAAC,CACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type FetchParams, type FetchReturn, Runtime, type RuntimeConfig } from '../../abstract.runtime.ts';
2
+ export declare class BunFsRuntime extends Runtime {
3
+ private readonly root;
4
+ constructor(root: string, config?: RuntimeConfig);
5
+ handle(resource: FetchParams[0], init?: FetchParams[1]): FetchReturn;
6
+ query(resource: FetchParams[0], options: FetchParams[1] & {
7
+ as: 'text';
8
+ }): Promise<string>;
9
+ query(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn;
10
+ private parsePath;
11
+ private parse;
12
+ private read;
13
+ private list;
14
+ private write;
15
+ loadModule(path: string): Promise<unknown>;
16
+ bundle(): Promise<void>;
17
+ private static _esbuild;
18
+ private static esbuild;
19
+ static transpile(source: string): Promise<string>;
20
+ static stopBundler(): Promise<void>;
21
+ }