@emkodev/emroute 1.7.2 → 1.8.0-beta.1

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 (236) hide show
  1. package/README.md +1 -1
  2. package/core/component/abstract.component.ts +74 -0
  3. package/{src → core}/component/page.component.ts +3 -61
  4. package/core/component/widget.component.ts +54 -0
  5. package/core/pipeline/pipeline.ts +224 -0
  6. package/{src/renderer/ssr → core/renderer}/html.renderer.ts +19 -45
  7. package/{src/renderer/ssr → core/renderer}/md.renderer.ts +21 -40
  8. package/{src/renderer/ssr → core/renderer}/ssr.renderer.ts +42 -53
  9. package/{src/route → core/router}/route.resolver.ts +1 -10
  10. package/core/router/route.trie.ts +175 -0
  11. package/core/runtime/abstract.runtime.ts +47 -0
  12. package/core/server/emroute.server.ts +346 -0
  13. package/core/type/component.type.ts +39 -0
  14. package/core/type/element.type.ts +10 -0
  15. package/core/type/logger.type.ts +20 -0
  16. package/core/type/markdown.type.ts +8 -0
  17. package/core/type/route-tree.type.ts +28 -0
  18. package/core/type/route.type.ts +75 -0
  19. package/core/type/widget.type.ts +27 -0
  20. package/core/util/html.util.ts +50 -0
  21. package/{src → core}/util/md.util.ts +0 -2
  22. package/{src/route → core/util}/route-tree.util.ts +0 -2
  23. package/{src → core}/util/widget-resolve.util.ts +15 -45
  24. package/{src → core}/widget/widget.parser.ts +0 -21
  25. package/core/widget/widget.registry.ts +24 -0
  26. package/dist/core/component/abstract.component.d.ts +48 -0
  27. package/dist/core/component/abstract.component.js +42 -0
  28. package/dist/core/component/abstract.component.js.map +1 -0
  29. package/dist/core/component/page.component.d.ts +23 -0
  30. package/dist/core/component/page.component.js +49 -0
  31. package/dist/core/component/page.component.js.map +1 -0
  32. package/dist/core/component/widget.component.d.ts +17 -0
  33. package/dist/core/component/widget.component.js +37 -0
  34. package/dist/core/component/widget.component.js.map +1 -0
  35. package/dist/core/pipeline/pipeline.d.ts +61 -0
  36. package/dist/core/pipeline/pipeline.js +189 -0
  37. package/dist/core/pipeline/pipeline.js.map +1 -0
  38. package/dist/{src/renderer/ssr → core/renderer}/html.renderer.d.ts +8 -24
  39. package/dist/{src/renderer/ssr → core/renderer}/html.renderer.js +12 -33
  40. package/dist/core/renderer/html.renderer.js.map +1 -0
  41. package/dist/{src/renderer/ssr → core/renderer}/md.renderer.d.ts +6 -21
  42. package/dist/{src/renderer/ssr → core/renderer}/md.renderer.js +14 -31
  43. package/dist/core/renderer/md.renderer.js.map +1 -0
  44. package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.d.ts +11 -17
  45. package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.js +34 -36
  46. package/dist/core/renderer/ssr.renderer.js.map +1 -0
  47. package/dist/{src/route → core/router}/route.resolver.d.ts +1 -8
  48. package/dist/{src/route → core/router}/route.resolver.js +0 -1
  49. package/dist/core/router/route.resolver.js.map +1 -0
  50. package/dist/core/router/route.trie.d.ts +32 -0
  51. package/dist/core/router/route.trie.js +152 -0
  52. package/dist/core/router/route.trie.js.map +1 -0
  53. package/dist/core/runtime/abstract.runtime.d.ts +32 -0
  54. package/dist/core/runtime/abstract.runtime.js +26 -0
  55. package/dist/core/runtime/abstract.runtime.js.map +1 -0
  56. package/dist/core/server/emroute.server.d.ts +48 -0
  57. package/dist/core/server/emroute.server.js +261 -0
  58. package/dist/core/server/emroute.server.js.map +1 -0
  59. package/dist/core/server/server.type.d.ts +45 -0
  60. package/dist/core/server/server.type.js +11 -0
  61. package/dist/core/server/server.type.js.map +1 -0
  62. package/dist/core/type/component.type.d.ts +37 -0
  63. package/dist/core/type/component.type.js +7 -0
  64. package/dist/core/type/component.type.js.map +1 -0
  65. package/dist/core/type/element.type.d.ts +9 -0
  66. package/dist/core/type/element.type.js +5 -0
  67. package/dist/core/type/element.type.js.map +1 -0
  68. package/dist/core/type/logger.type.d.ts +14 -0
  69. package/dist/core/type/logger.type.js +8 -0
  70. package/dist/core/type/logger.type.js.map +1 -0
  71. package/dist/core/type/markdown.type.d.ts +7 -0
  72. package/dist/core/type/markdown.type.js +5 -0
  73. package/dist/core/type/markdown.type.js.map +1 -0
  74. package/dist/{src → core}/type/route-tree.type.d.ts +0 -12
  75. package/dist/{src → core}/type/route-tree.type.js +0 -1
  76. package/dist/core/type/route-tree.type.js.map +1 -0
  77. package/dist/core/type/route.type.d.ts +62 -0
  78. package/dist/core/type/route.type.js +7 -0
  79. package/dist/core/type/route.type.js.map +1 -0
  80. package/dist/core/type/widget.type.d.ts +27 -0
  81. package/dist/core/type/widget.type.js +5 -0
  82. package/dist/core/type/widget.type.js.map +1 -0
  83. package/dist/core/util/html.util.d.ts +14 -0
  84. package/dist/core/util/html.util.js +43 -0
  85. package/dist/core/util/html.util.js.map +1 -0
  86. package/dist/{src → core}/util/md.util.d.ts +0 -1
  87. package/dist/{src → core}/util/md.util.js +0 -2
  88. package/dist/core/util/md.util.js.map +1 -0
  89. package/dist/{src/route → core/util}/route-tree.util.js +0 -2
  90. package/dist/core/util/route-tree.util.js.map +1 -0
  91. package/dist/core/util/widget-resolve.util.d.ts +32 -0
  92. package/dist/{src → core}/util/widget-resolve.util.js +11 -41
  93. package/dist/core/util/widget-resolve.util.js.map +1 -0
  94. package/dist/{src → core}/widget/widget.parser.d.ts +0 -13
  95. package/dist/{src → core}/widget/widget.parser.js +0 -21
  96. package/dist/core/widget/widget.parser.js.map +1 -0
  97. package/dist/core/widget/widget.registry.d.ts +13 -0
  98. package/dist/core/widget/widget.registry.js +19 -0
  99. package/dist/core/widget/widget.registry.js.map +1 -0
  100. package/dist/emroute.js +1137 -1151
  101. package/dist/emroute.js.map +36 -5
  102. package/dist/runtime/abstract.runtime.d.ts +50 -5
  103. package/dist/runtime/abstract.runtime.js +446 -6
  104. package/dist/runtime/abstract.runtime.js.map +1 -1
  105. package/dist/runtime/bun/fs/bun-fs.runtime.d.ts +1 -0
  106. package/dist/runtime/bun/fs/bun-fs.runtime.js +18 -2
  107. package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -1
  108. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.d.ts +2 -0
  109. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +11 -1
  110. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -1
  111. package/dist/runtime/fetch.runtime.d.ts +3 -3
  112. package/dist/runtime/fetch.runtime.js +3 -3
  113. package/dist/runtime/sitemap.generator.d.ts +1 -1
  114. package/dist/runtime/sitemap.generator.js +1 -1
  115. package/dist/runtime/sitemap.generator.js.map +1 -1
  116. package/dist/runtime/universal/fs/universal-fs.runtime.d.ts +1 -0
  117. package/dist/runtime/universal/fs/universal-fs.runtime.js +18 -2
  118. package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -1
  119. package/dist/server/build.util.d.ts +9 -10
  120. package/dist/server/build.util.js +45 -36
  121. package/dist/server/build.util.js.map +1 -1
  122. package/dist/server/codegen.util.d.ts +1 -1
  123. package/dist/server/emroute.server.d.ts +8 -35
  124. package/dist/server/emroute.server.js +7 -341
  125. package/dist/server/emroute.server.js.map +1 -1
  126. package/dist/server/esbuild-manifest.plugin.js +1 -1
  127. package/dist/server/esbuild-manifest.plugin.js.map +1 -1
  128. package/dist/server/server-api.type.d.ts +3 -68
  129. package/dist/server/server-api.type.js +1 -8
  130. package/dist/server/server-api.type.js.map +1 -1
  131. package/dist/src/element/component.element.d.ts +4 -7
  132. package/dist/src/element/component.element.js +23 -22
  133. package/dist/src/element/component.element.js.map +1 -1
  134. package/dist/src/element/markdown.element.d.ts +2 -2
  135. package/dist/src/element/markdown.element.js +4 -3
  136. package/dist/src/element/markdown.element.js.map +1 -1
  137. package/dist/src/index.d.ts +15 -13
  138. package/dist/src/index.js +8 -8
  139. package/dist/src/index.js.map +1 -1
  140. package/dist/src/renderer/spa/emroute.app.d.ts +50 -0
  141. package/dist/src/renderer/spa/emroute.app.js +246 -0
  142. package/dist/src/renderer/spa/emroute.app.js.map +1 -0
  143. package/dist/src/renderer/spa/mod.d.ts +17 -16
  144. package/dist/src/renderer/spa/mod.js +9 -9
  145. package/dist/src/renderer/spa/mod.js.map +1 -1
  146. package/dist/src/renderer/spa/thin-client.d.ts +3 -3
  147. package/dist/src/renderer/spa/thin-client.js +34 -12
  148. package/dist/src/renderer/spa/thin-client.js.map +1 -1
  149. package/dist/src/route/route.core.d.ts +3 -3
  150. package/dist/src/route/route.core.js +21 -7
  151. package/dist/src/route/route.core.js.map +1 -1
  152. package/dist/src/util/html.util.d.ts +5 -22
  153. package/dist/src/util/html.util.js +8 -56
  154. package/dist/src/util/html.util.js.map +1 -1
  155. package/dist/src/widget/breadcrumb.widget.d.ts +2 -2
  156. package/dist/src/widget/breadcrumb.widget.js +2 -2
  157. package/dist/src/widget/breadcrumb.widget.js.map +1 -1
  158. package/dist/src/widget/page-title.widget.d.ts +1 -1
  159. package/dist/src/widget/page-title.widget.js +1 -1
  160. package/dist/src/widget/page-title.widget.js.map +1 -1
  161. package/package.json +8 -8
  162. package/runtime/abstract.runtime.ts +483 -8
  163. package/runtime/bun/fs/bun-fs.runtime.ts +17 -1
  164. package/runtime/bun/sqlite/bun-sqlite.runtime.ts +11 -0
  165. package/runtime/fetch.runtime.ts +3 -3
  166. package/runtime/sitemap.generator.ts +2 -2
  167. package/runtime/universal/fs/universal-fs.runtime.ts +17 -1
  168. package/server/build.util.ts +53 -47
  169. package/server/codegen.util.ts +1 -1
  170. package/server/emroute.server.ts +12 -412
  171. package/src/element/component.element.ts +24 -31
  172. package/src/element/markdown.element.ts +5 -4
  173. package/src/index.ts +22 -18
  174. package/src/renderer/spa/{thin-client.ts → emroute.app.ts} +46 -22
  175. package/src/renderer/spa/mod.ts +22 -22
  176. package/src/util/html.util.ts +16 -61
  177. package/src/widget/breadcrumb.widget.ts +3 -3
  178. package/src/widget/page-title.widget.ts +1 -1
  179. package/dist/src/component/abstract.component.d.ts +0 -199
  180. package/dist/src/component/abstract.component.js +0 -84
  181. package/dist/src/component/abstract.component.js.map +0 -1
  182. package/dist/src/component/page.component.d.ts +0 -74
  183. package/dist/src/component/page.component.js +0 -107
  184. package/dist/src/component/page.component.js.map +0 -1
  185. package/dist/src/component/widget.component.d.ts +0 -47
  186. package/dist/src/component/widget.component.js +0 -69
  187. package/dist/src/component/widget.component.js.map +0 -1
  188. package/dist/src/renderer/ssr/html.renderer.js.map +0 -1
  189. package/dist/src/renderer/ssr/md.renderer.js.map +0 -1
  190. package/dist/src/renderer/ssr/ssr.renderer.js.map +0 -1
  191. package/dist/src/route/route-tree.util.js.map +0 -1
  192. package/dist/src/route/route.matcher.d.ts +0 -86
  193. package/dist/src/route/route.matcher.js +0 -214
  194. package/dist/src/route/route.matcher.js.map +0 -1
  195. package/dist/src/route/route.resolver.js.map +0 -1
  196. package/dist/src/route/route.trie.d.ts +0 -38
  197. package/dist/src/route/route.trie.js +0 -206
  198. package/dist/src/route/route.trie.js.map +0 -1
  199. package/dist/src/type/logger.type.d.ts +0 -17
  200. package/dist/src/type/logger.type.js +0 -9
  201. package/dist/src/type/logger.type.js.map +0 -1
  202. package/dist/src/type/markdown.type.d.ts +0 -20
  203. package/dist/src/type/markdown.type.js +0 -2
  204. package/dist/src/type/markdown.type.js.map +0 -1
  205. package/dist/src/type/route-tree.type.js.map +0 -1
  206. package/dist/src/type/route.type.d.ts +0 -94
  207. package/dist/src/type/route.type.js +0 -8
  208. package/dist/src/type/route.type.js.map +0 -1
  209. package/dist/src/type/widget.type.d.ts +0 -55
  210. package/dist/src/type/widget.type.js +0 -10
  211. package/dist/src/type/widget.type.js.map +0 -1
  212. package/dist/src/util/logger.util.d.ts +0 -26
  213. package/dist/src/util/logger.util.js +0 -80
  214. package/dist/src/util/logger.util.js.map +0 -1
  215. package/dist/src/util/md.util.js.map +0 -1
  216. package/dist/src/util/widget-resolve.util.d.ts +0 -52
  217. package/dist/src/util/widget-resolve.util.js.map +0 -1
  218. package/dist/src/widget/widget.parser.js.map +0 -1
  219. package/dist/src/widget/widget.registry.d.ts +0 -23
  220. package/dist/src/widget/widget.registry.js +0 -42
  221. package/dist/src/widget/widget.registry.js.map +0 -1
  222. package/runtime/bun/esbuild-runtime-loader.plugin.ts +0 -112
  223. package/server/esbuild-manifest.plugin.ts +0 -209
  224. package/server/server-api.type.ts +0 -97
  225. package/src/component/abstract.component.ts +0 -231
  226. package/src/component/widget.component.ts +0 -85
  227. package/src/route/route.core.ts +0 -362
  228. package/src/route/route.trie.ts +0 -265
  229. package/src/type/logger.type.ts +0 -24
  230. package/src/type/markdown.type.ts +0 -21
  231. package/src/type/route-tree.type.ts +0 -51
  232. package/src/type/route.type.ts +0 -124
  233. package/src/type/widget.type.ts +0 -65
  234. package/src/util/logger.util.ts +0 -83
  235. package/src/widget/widget.registry.ts +0 -51
  236. /package/dist/{src/route → core/util}/route-tree.util.d.ts +0 -0
@@ -4,18 +4,20 @@
4
4
  * Abstract base class for server-side renderers.
5
5
  * Provides the shared render() pipeline; subclasses supply format-specific rendering.
6
6
  */
7
- import { logger } from "../../type/logger.type.js";
8
- import defaultPageComponent from "../../component/page.component.js";
9
- import { assertSafeRedirect, DEFAULT_ROOT_ROUTE, RouteCore, } from "../../route/route.core.js";
7
+ import defaultPageComponent from "../component/page.component.js";
8
+ import { DEFAULT_ROOT_ROUTE } from "../pipeline/pipeline.js";
9
+ import { assertSafeRedirect } from "../util/html.util.js";
10
10
  /**
11
11
  * Abstract SSR renderer with shared routing pipeline.
12
12
  */
13
13
  export class SsrRenderer {
14
- core;
14
+ pipeline;
15
15
  widgets;
16
16
  widgetFiles;
17
- constructor(resolver, options = {}) {
18
- this.core = new RouteCore(resolver, options);
17
+ logger;
18
+ constructor(pipeline, options = {}) {
19
+ this.pipeline = pipeline;
20
+ this.logger = pipeline.logger;
19
21
  this.widgets = options.widgets ?? null;
20
22
  this.widgetFiles = options.widgetFiles ?? {};
21
23
  }
@@ -23,24 +25,24 @@ export class SsrRenderer {
23
25
  * Render a URL to a content string.
24
26
  */
25
27
  async render(url, signal) {
26
- const matched = this.core.match(url);
28
+ const matched = await this.pipeline.match(url);
27
29
  if (!matched) {
28
- const statusPage = this.core.getStatusPage(404);
30
+ const statusPage = await this.pipeline.getStatusPage(404);
29
31
  if (statusPage) {
30
32
  try {
31
33
  const ri = { url, params: {} };
32
34
  const result = await this.renderRouteContent(ri, statusPage, undefined, signal);
33
- return { content: this.stripSlots(result.content), status: 404, title: result.title };
35
+ return { content: this.stripSlots(result.content), status: 404, ...(result.title !== undefined ? { title: result.title } : {}) };
34
36
  }
35
37
  catch (e) {
36
- logger.error(`[${this.label}] Failed to render 404 status page for ${url.pathname}`, e instanceof Error ? e : undefined);
38
+ this.logger.error(`[${this.label}] Failed to render 404 status page for ${url.pathname}`, e instanceof Error ? e : undefined);
37
39
  }
38
40
  }
39
41
  return { content: this.renderStatusPage(404, url), status: 404 };
40
42
  }
41
43
  // Handle redirect
42
44
  if (matched.route.type === 'redirect') {
43
- const module = await this.core.loadModule(matched.route.modulePath);
45
+ const module = await this.pipeline.loadModule(matched.route.modulePath);
44
46
  const redirectConfig = module.default;
45
47
  assertSafeRedirect(redirectConfig.to);
46
48
  return {
@@ -49,14 +51,14 @@ export class SsrRenderer {
49
51
  redirect: redirectConfig.to,
50
52
  };
51
53
  }
52
- const routeInfo = this.core.toRouteInfo(matched, url);
54
+ const routeInfo = this.pipeline.toRouteInfo(matched, url);
53
55
  try {
54
56
  const { content, title } = await this.renderPage(routeInfo, matched, signal);
55
- return { content, status: 200, title };
57
+ return { content, status: 200, ...(title !== undefined ? { title } : {}) };
56
58
  }
57
59
  catch (error) {
58
60
  if (error instanceof Response) {
59
- const statusPage = this.core.getStatusPage(error.status);
61
+ const statusPage = await this.pipeline.getStatusPage(error.status);
60
62
  if (statusPage) {
61
63
  try {
62
64
  const ri = { url, params: {} };
@@ -64,23 +66,23 @@ export class SsrRenderer {
64
66
  return {
65
67
  content: this.stripSlots(result.content),
66
68
  status: error.status,
67
- title: result.title,
69
+ ...(result.title !== undefined ? { title: result.title } : {}),
68
70
  };
69
71
  }
70
72
  catch (e) {
71
- logger.error(`[${this.label}] Failed to render ${error.status} status page for ${url.pathname}`, e instanceof Error ? e : undefined);
73
+ this.logger.error(`[${this.label}] Failed to render ${error.status} status page for ${url.pathname}`, e instanceof Error ? e : undefined);
72
74
  }
73
75
  }
74
76
  return { content: this.renderStatusPage(error.status, url), status: error.status };
75
77
  }
76
- logger.error(`[${this.label}] Error rendering ${url.pathname}:`, error instanceof Error ? error : undefined);
77
- const boundary = this.core.findErrorBoundary(url.pathname);
78
+ this.logger.error(`[${this.label}] Error rendering ${url.pathname}:`, error instanceof Error ? error : undefined);
79
+ const boundary = await this.pipeline.findErrorBoundary(url.pathname);
78
80
  if (boundary) {
79
81
  const result = await this.tryRenderErrorModule(boundary.modulePath, url, 'boundary');
80
82
  if (result)
81
83
  return result;
82
84
  }
83
- const errorHandler = this.core.getErrorHandler();
85
+ const errorHandler = await this.pipeline.getErrorHandler();
84
86
  if (errorHandler) {
85
87
  const result = await this.tryRenderErrorModule(errorHandler.modulePath, url, 'handler');
86
88
  if (result)
@@ -93,12 +95,11 @@ export class SsrRenderer {
93
95
  * Render a matched page by composing the route hierarchy.
94
96
  */
95
97
  async renderPage(routeInfo, matched, signal) {
96
- const hierarchy = this.core.buildRouteHierarchy(matched.route.pattern);
97
- // Resolve routes for each hierarchy segment (skip missing / duplicate wildcard)
98
+ const hierarchy = this.pipeline.buildRouteHierarchy(matched.route.pattern);
98
99
  const segments = [];
99
100
  for (let i = 0; i < hierarchy.length; i++) {
100
101
  const routePattern = hierarchy[i];
101
- let route = this.core.findRoute(routePattern);
102
+ let route = await this.pipeline.findRoute(routePattern);
102
103
  if (!route && routePattern === '/') {
103
104
  route = DEFAULT_ROOT_ROUTE;
104
105
  }
@@ -108,9 +109,7 @@ export class SsrRenderer {
108
109
  continue;
109
110
  segments.push({ route, isLeaf: i === hierarchy.length - 1 });
110
111
  }
111
- // Fire all renderRouteContent calls in parallel
112
112
  const results = await Promise.all(segments.map(({ route, isLeaf }) => this.renderRouteContent(routeInfo, route, isLeaf, signal)));
113
- // Sequential slot injection
114
113
  let result = '';
115
114
  let pageTitle;
116
115
  let lastRenderedPattern = '';
@@ -125,7 +124,7 @@ export class SsrRenderer {
125
124
  else {
126
125
  const injected = this.injectSlot(result, content, lastRenderedPattern);
127
126
  if (injected === result) {
128
- logger.warn(`[${this.label}] Route "${lastRenderedPattern}" has no <router-slot> ` +
127
+ this.logger.warn(`[${this.label}] Route "${lastRenderedPattern}" has no <router-slot> ` +
129
128
  `for child route "${hierarchy[i]}" to render into. ` +
130
129
  `Add <router-slot></router-slot> to the parent template.`);
131
130
  }
@@ -134,30 +133,29 @@ export class SsrRenderer {
134
133
  lastRenderedPattern = segments[i].route.pattern;
135
134
  }
136
135
  result = this.stripSlots(result);
137
- return { content: result, title: pageTitle };
136
+ return { content: result, ...(pageTitle !== undefined ? { title: pageTitle } : {}) };
138
137
  }
139
138
  /** Load component, build context, get data, render content, get title. */
140
139
  async loadRouteContent(routeInfo, route, isLeaf, signal) {
141
140
  const files = route.files ?? {};
142
141
  const tsModule = files.ts ?? files.js;
143
- const component = tsModule
144
- ? (await this.core.loadModule(tsModule)).default
145
- : defaultPageComponent;
146
- const context = await this.core.buildComponentContext(routeInfo, route, signal, isLeaf);
147
- const data = await component.getData({ params: routeInfo.params, signal, context });
142
+ const loadedModule = tsModule
143
+ ? await this.pipeline.loadModule(tsModule)
144
+ : undefined;
145
+ const component = loadedModule?.default ?? defaultPageComponent;
146
+ const context = await this.pipeline.buildContext(routeInfo, route, signal, isLeaf, loadedModule);
147
+ const data = await component.getData({ params: routeInfo.params, ...(signal ? { signal } : {}), context });
148
148
  const content = this.renderContent(component, { data, params: routeInfo.params, context });
149
149
  const title = component.getTitle({ data, params: routeInfo.params, context });
150
- return { content, title };
150
+ return { content, ...(title !== undefined ? { title } : {}) };
151
151
  }
152
- /** Render a component for error boundary/handler with minimal context. */
153
152
  renderComponent(component, data, context) {
154
153
  return this.renderContent(component, { data, params: {}, context });
155
154
  }
156
155
  static EMPTY_URL = new URL('http://error');
157
- /** Try to load and render an error boundary or handler module. Returns null on failure. */
158
156
  async tryRenderErrorModule(modulePath, url, kind) {
159
157
  try {
160
- const module = await this.core.loadModule(modulePath);
158
+ const module = await this.pipeline.loadModule(modulePath);
161
159
  const component = module.default;
162
160
  const minCtx = {
163
161
  url: SsrRenderer.EMPTY_URL,
@@ -170,7 +168,7 @@ export class SsrRenderer {
170
168
  return { content, status: 500 };
171
169
  }
172
170
  catch (e) {
173
- logger.error(`[${this.label}] Error ${kind} failed for ${url.pathname}`, e instanceof Error ? e : undefined);
171
+ this.logger.error(`[${this.label}] Error ${kind} failed for ${url.pathname}`, e instanceof Error ? e : undefined);
174
172
  return null;
175
173
  }
176
174
  }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssr.renderer.js","sourceRoot":"","sources":["../../../core/renderer/ssr.renderer.ts"],"names":[],"mappings":"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"}
@@ -5,24 +5,17 @@
5
5
  * provides O(depth) matching, error boundary lookup, and hierarchy traversal.
6
6
  *
7
7
  * Implementations: RouteTrie (in-memory trie from RouteNode tree).
8
- * RouteCore depends on this interface, not on the algorithm.
9
8
  */
10
9
  import type { RouteNode } from '../type/route-tree.type.ts';
11
10
  /** Result of matching a URL pathname against the route tree. */
12
11
  export interface ResolvedRoute {
13
- /** The matched route node. */
14
12
  readonly node: RouteNode;
15
- /** URL pattern reconstructed from the tree path (e.g. "/projects/:id"). */
16
13
  readonly pattern: string;
17
- /** Extracted URL parameters (e.g. { id: "42" }). */
18
14
  readonly params: Record<string, string>;
19
15
  }
20
- /** Route lookup interface. Decouples matching algorithm from the router. */
16
+ /** Route lookup interface. Decouples matching algorithm from the server. */
21
17
  export interface RouteResolver {
22
- /** Match a URL pathname to a route. */
23
18
  match(pathname: string): ResolvedRoute | undefined;
24
- /** Find the most specific error boundary for a pathname. */
25
19
  findErrorBoundary(pathname: string): string | undefined;
26
- /** Look up a route node by its exact pattern (e.g. "/projects/:id"). */
27
20
  findRoute(pattern: string): RouteNode | undefined;
28
21
  }
@@ -5,7 +5,6 @@
5
5
  * provides O(depth) matching, error boundary lookup, and hierarchy traversal.
6
6
  *
7
7
  * Implementations: RouteTrie (in-memory trie from RouteNode tree).
8
- * RouteCore depends on this interface, not on the algorithm.
9
8
  */
10
9
  export {};
11
10
  //# sourceMappingURL=route.resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.resolver.js","sourceRoot":"","sources":["../../../core/router/route.resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Route Trie
3
+ *
4
+ * Default RouteResolver implementation. O(depth) route matching over
5
+ * the RouteNode tree.
6
+ *
7
+ * Walks the RouteNode tree directly — no conversion step, no internal state
8
+ * beyond the tree reference. Each URL segment is matched in order:
9
+ * static → dynamic (:param) → wildcard (:rest*). Backtracking handles
10
+ * cases where a dynamic path leads to a dead end but a wildcard at an
11
+ * ancestor would match.
12
+ *
13
+ * Static segment matching is case-sensitive, per RFC 3986.
14
+ */
15
+ import type { RouteNode } from '../type/route-tree.type.ts';
16
+ import type { ResolvedRoute, RouteResolver } from './route.resolver.ts';
17
+ /**
18
+ * Default RouteResolver implementation.
19
+ * Walks the RouteNode tree directly — no conversion, no Maps.
20
+ */
21
+ export declare class RouteTrie implements RouteResolver {
22
+ private readonly tree;
23
+ constructor(tree: RouteNode);
24
+ match(pathname: string): ResolvedRoute | undefined;
25
+ findErrorBoundary(pathname: string): string | undefined;
26
+ findRoute(pattern: string): RouteNode | undefined;
27
+ private safeDecode;
28
+ private splitSegments;
29
+ private normalizePath;
30
+ private walk;
31
+ private walkForBoundary;
32
+ }
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Route Trie
3
+ *
4
+ * Default RouteResolver implementation. O(depth) route matching over
5
+ * the RouteNode tree.
6
+ *
7
+ * Walks the RouteNode tree directly — no conversion step, no internal state
8
+ * beyond the tree reference. Each URL segment is matched in order:
9
+ * static → dynamic (:param) → wildcard (:rest*). Backtracking handles
10
+ * cases where a dynamic path leads to a dead end but a wildcard at an
11
+ * ancestor would match.
12
+ *
13
+ * Static segment matching is case-sensitive, per RFC 3986.
14
+ */
15
+ /**
16
+ * Default RouteResolver implementation.
17
+ * Walks the RouteNode tree directly — no conversion, no Maps.
18
+ */
19
+ export class RouteTrie {
20
+ tree;
21
+ constructor(tree) {
22
+ this.tree = tree;
23
+ }
24
+ match(pathname) {
25
+ pathname = this.normalizePath(pathname);
26
+ if (pathname === '/') {
27
+ if (this.tree.files || this.tree.redirect) {
28
+ return { node: this.tree, pattern: '/', params: {} };
29
+ }
30
+ return undefined;
31
+ }
32
+ return this.walk(this.tree, this.splitSegments(pathname), 0, {}, '/');
33
+ }
34
+ findErrorBoundary(pathname) {
35
+ pathname = this.normalizePath(pathname);
36
+ if (pathname === '/')
37
+ return this.tree.errorBoundary;
38
+ return this.walkForBoundary(this.tree, this.splitSegments(pathname), 0, this.tree.errorBoundary);
39
+ }
40
+ findRoute(pattern) {
41
+ if (pattern === '/') {
42
+ return (this.tree.files || this.tree.redirect) ? this.tree : undefined;
43
+ }
44
+ const segments = this.splitSegments(pattern);
45
+ let node = this.tree;
46
+ for (const segment of segments) {
47
+ let child;
48
+ if (segment.startsWith(':') && segment.endsWith('*')) {
49
+ child = node.wildcard?.child;
50
+ }
51
+ else if (segment.startsWith(':')) {
52
+ child = node.dynamic?.child;
53
+ }
54
+ else {
55
+ child = node.children?.[segment];
56
+ }
57
+ if (!child)
58
+ return undefined;
59
+ node = child;
60
+ }
61
+ return (node.files || node.redirect) ? node : undefined;
62
+ }
63
+ // ── Private helpers ─────────────────────────────────────────────────
64
+ safeDecode(segment) {
65
+ try {
66
+ return decodeURIComponent(segment);
67
+ }
68
+ catch {
69
+ return segment;
70
+ }
71
+ }
72
+ splitSegments(pathname) {
73
+ return pathname.substring(1).split('/');
74
+ }
75
+ normalizePath(pathname) {
76
+ if (pathname.length > 1 && pathname.endsWith('/')) {
77
+ pathname = pathname.slice(0, -1);
78
+ }
79
+ if (!pathname.startsWith('/')) {
80
+ pathname = '/' + pathname;
81
+ }
82
+ return pathname;
83
+ }
84
+ walk(node, segments, index, params, pattern) {
85
+ if (index === segments.length) {
86
+ if (node.files || node.redirect) {
87
+ return { node, pattern, params: { ...params } };
88
+ }
89
+ if (node.wildcard && (node.wildcard.child.files || node.wildcard.child.redirect)) {
90
+ const wp = pattern === '/' ? `/:${node.wildcard.param}*` : `${pattern}/:${node.wildcard.param}*`;
91
+ return {
92
+ node: node.wildcard.child,
93
+ pattern: wp,
94
+ params: { ...params, [node.wildcard.param]: '' },
95
+ };
96
+ }
97
+ return undefined;
98
+ }
99
+ const segment = segments[index];
100
+ // Static
101
+ const staticChild = node.children?.[segment];
102
+ if (staticChild) {
103
+ const childPattern = pattern === '/' ? `/${segment}` : `${pattern}/${segment}`;
104
+ const result = this.walk(staticChild, segments, index + 1, params, childPattern);
105
+ if (result)
106
+ return result;
107
+ }
108
+ // Dynamic
109
+ if (node.dynamic) {
110
+ const { param, child } = node.dynamic;
111
+ params[param] = this.safeDecode(segment);
112
+ const childPattern = pattern === '/' ? `/:${param}` : `${pattern}/:${param}`;
113
+ const result = this.walk(child, segments, index + 1, params, childPattern);
114
+ if (result)
115
+ return result;
116
+ delete params[param];
117
+ }
118
+ // Wildcard
119
+ if (node.wildcard && (node.wildcard.child.files || node.wildcard.child.redirect)) {
120
+ const { param, child } = node.wildcard;
121
+ let rest = this.safeDecode(segments[index]);
122
+ for (let i = index + 1; i < segments.length; i++) {
123
+ rest += '/' + this.safeDecode(segments[i]);
124
+ }
125
+ const wp = pattern === '/' ? `/:${param}*` : `${pattern}/:${param}*`;
126
+ return {
127
+ node: child,
128
+ pattern: wp,
129
+ params: { ...params, [param]: rest },
130
+ };
131
+ }
132
+ return undefined;
133
+ }
134
+ walkForBoundary(node, segments, index, deepest) {
135
+ if (index === segments.length) {
136
+ return node.errorBoundary ?? deepest;
137
+ }
138
+ const segment = segments[index];
139
+ const staticChild = node.children?.[segment];
140
+ if (staticChild) {
141
+ return this.walkForBoundary(staticChild, segments, index + 1, staticChild.errorBoundary ?? deepest);
142
+ }
143
+ if (node.dynamic) {
144
+ return this.walkForBoundary(node.dynamic.child, segments, index + 1, node.dynamic.child.errorBoundary ?? deepest);
145
+ }
146
+ if (node.wildcard) {
147
+ return node.wildcard.child.errorBoundary ?? deepest;
148
+ }
149
+ return deepest;
150
+ }
151
+ }
152
+ //# sourceMappingURL=route.trie.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.trie.js","sourceRoot":"","sources":["../../../core/router/route.trie.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Abstract Runtime
3
+ *
4
+ * Storage contract. Speaks Request/Response.
5
+ * Concrete implementations decide how to store, cache, scan, and serve.
6
+ *
7
+ * Three access patterns:
8
+ * - handle() — raw passthrough
9
+ * - query() — read (Response or string)
10
+ * - command() — write/delete
11
+ */
12
+ export type FetchParams = Parameters<typeof fetch>;
13
+ export type FetchReturn = ReturnType<typeof fetch>;
14
+ /** Well-known manifest paths (convention between Runtime and consumers). */
15
+ export declare const ROUTES_MANIFEST_PATH = "/routes.manifest.json";
16
+ export declare const WIDGETS_MANIFEST_PATH = "/widgets.manifest.json";
17
+ export declare const ELEMENTS_MANIFEST_PATH = "/elements.manifest.json";
18
+ export declare abstract class Runtime {
19
+ /** Raw passthrough — same signature as fetch(). */
20
+ abstract handle(resource: FetchParams[0], init?: FetchParams[1]): FetchReturn;
21
+ /** Read. Returns Response, or string with { as: 'text' }. */
22
+ abstract query(resource: FetchParams[0], options: FetchParams[1] & {
23
+ as: 'text';
24
+ }): Promise<string>;
25
+ abstract query(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn;
26
+ /** Write (PUT) or delete (DELETE). */
27
+ abstract command(resource: FetchParams[0], options?: FetchParams[1]): FetchReturn;
28
+ /** Dynamically import a module from storage. */
29
+ loadModule(_path: string): Promise<unknown>;
30
+ /** Transpile TypeScript to JavaScript. */
31
+ transpile(_source: string): Promise<string>;
32
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Abstract Runtime
3
+ *
4
+ * Storage contract. Speaks Request/Response.
5
+ * Concrete implementations decide how to store, cache, scan, and serve.
6
+ *
7
+ * Three access patterns:
8
+ * - handle() — raw passthrough
9
+ * - query() — read (Response or string)
10
+ * - command() — write/delete
11
+ */
12
+ /** Well-known manifest paths (convention between Runtime and consumers). */
13
+ export const ROUTES_MANIFEST_PATH = '/routes.manifest.json';
14
+ export const WIDGETS_MANIFEST_PATH = '/widgets.manifest.json';
15
+ export const ELEMENTS_MANIFEST_PATH = '/elements.manifest.json';
16
+ export class Runtime {
17
+ /** Dynamically import a module from storage. */
18
+ loadModule(_path) {
19
+ throw new Error(`loadModule not implemented for ${this.constructor.name}`);
20
+ }
21
+ /** Transpile TypeScript to JavaScript. */
22
+ transpile(_source) {
23
+ throw new Error(`transpile not implemented for ${this.constructor.name}`);
24
+ }
25
+ }
26
+ //# sourceMappingURL=abstract.runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract.runtime.js","sourceRoot":"","sources":["../../../core/runtime/abstract.runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AAC5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,wBAAwB,CAAC;AAC9D,MAAM,CAAC,MAAM,sBAAsB,GAAG,yBAAyB,CAAC;AAEhE,MAAM,OAAgB,OAAO;IAiB3B,gDAAgD;IAChD,UAAU,CAAC,KAAa;QACtB,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,0CAA0C;IAC1C,SAAS,CAAC,OAAe;QACvB,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;CACF"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Emroute
3
+ *
4
+ * Framework entry point. Reads manifests from Runtime,
5
+ * builds Pipeline + Renderers, handles Request → Response.
6
+ */
7
+ import type { Runtime } from '../runtime/abstract.runtime.ts';
8
+ import { SsrHtmlRenderer } from '../renderer/html.renderer.ts';
9
+ import { SsrMdRenderer } from '../renderer/md.renderer.ts';
10
+ import { WidgetRegistry } from '../widget/widget.registry.ts';
11
+ import type { RouteNode } from '../type/route-tree.type.ts';
12
+ import type { MarkdownRenderer } from '../type/markdown.type.ts';
13
+ import type { SpaMode } from '../type/widget.type.ts';
14
+ import type { ContextProvider } from '../type/component.type.ts';
15
+ export declare const DEFAULT_BASE_PATH: {
16
+ html: string;
17
+ md: string;
18
+ app: string;
19
+ };
20
+ export type BasePath = Record<keyof typeof DEFAULT_BASE_PATH, string>;
21
+ export declare class Emroute {
22
+ private readonly runtime;
23
+ private readonly htmlBase;
24
+ private readonly mdBase;
25
+ private readonly appBase;
26
+ private readonly spa;
27
+ private readonly title;
28
+ readonly htmlRenderer: SsrHtmlRenderer | null;
29
+ readonly mdRenderer: SsrMdRenderer | null;
30
+ readonly shell: string;
31
+ private constructor();
32
+ static create(config: {
33
+ routeTree?: RouteNode;
34
+ widgets?: WidgetRegistry;
35
+ spa?: SpaMode;
36
+ basePath?: BasePath;
37
+ title?: string;
38
+ markdownRenderer?: MarkdownRenderer;
39
+ extendContext?: ContextProvider;
40
+ moduleLoaders?: Record<string, () => Promise<unknown>>;
41
+ }, runtime: Runtime): Promise<Emroute>;
42
+ handleRequest(req: Request): Promise<Response | null>;
43
+ private static extractWidgetExport;
44
+ private static importWidgets;
45
+ private static buildHtmlShell;
46
+ private static injectSsrContent;
47
+ private static resolveShell;
48
+ }