@emkodev/emroute 1.7.3 → 1.8.0-beta.2

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 (238) 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 +26 -47
  7. package/{src/renderer/ssr → core/renderer}/md.renderer.ts +22 -41
  8. package/{src/renderer/ssr → core/renderer}/ssr.renderer.ts +44 -58
  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 +324 -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 +3 -5
  22. package/{src/route → core/util}/route-tree.util.ts +0 -2
  23. package/{src → core}/util/widget-resolve.util.ts +15 -46
  24. package/{src → core}/widget/widget.parser.ts +2 -23
  25. package/core/widget/widget.registry.ts +36 -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 +20 -35
  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 +16 -32
  43. package/dist/core/renderer/md.renderer.js.map +1 -0
  44. package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.d.ts +11 -27
  45. package/dist/{src/renderer/ssr → core/renderer}/ssr.renderer.js +33 -37
  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 +239 -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 +28 -0
  92. package/dist/{src → core}/util/widget-resolve.util.js +12 -42
  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 +1 -22
  96. package/dist/core/widget/widget.parser.js.map +1 -0
  97. package/dist/core/widget/widget.registry.d.ts +14 -0
  98. package/dist/core/widget/widget.registry.js +26 -0
  99. package/dist/core/widget/widget.registry.js.map +1 -0
  100. package/dist/emroute.js +1092 -1220
  101. package/dist/emroute.js.map +36 -5
  102. package/dist/runtime/abstract.runtime.d.ts +41 -7
  103. package/dist/runtime/abstract.runtime.js +404 -9
  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 +15 -1
  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 +8 -0
  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 +15 -1
  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 +11 -31
  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 -351
  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 -71
  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 +6 -14
  132. package/dist/src/element/component.element.js +13 -40
  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 +3 -2
  136. package/dist/src/element/markdown.element.js.map +1 -1
  137. package/dist/src/index.d.ts +15 -14
  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 +7 -7
  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/util/html.util.d.ts +5 -22
  151. package/dist/src/util/html.util.js +8 -56
  152. package/dist/src/util/html.util.js.map +1 -1
  153. package/dist/src/widget/breadcrumb.widget.d.ts +2 -2
  154. package/dist/src/widget/breadcrumb.widget.js +2 -2
  155. package/dist/src/widget/breadcrumb.widget.js.map +1 -1
  156. package/dist/src/widget/page-title.widget.d.ts +1 -1
  157. package/dist/src/widget/page-title.widget.js +1 -1
  158. package/dist/src/widget/page-title.widget.js.map +1 -1
  159. package/package.json +8 -8
  160. package/runtime/abstract.runtime.ts +433 -17
  161. package/runtime/bun/fs/bun-fs.runtime.ts +15 -1
  162. package/runtime/bun/sqlite/bun-sqlite.runtime.ts +9 -0
  163. package/runtime/fetch.runtime.ts +3 -3
  164. package/runtime/sitemap.generator.ts +2 -2
  165. package/runtime/universal/fs/universal-fs.runtime.ts +15 -1
  166. package/server/build.util.ts +17 -43
  167. package/server/codegen.util.ts +1 -1
  168. package/server/emroute.server.ts +12 -426
  169. package/src/element/component.element.ts +14 -54
  170. package/src/element/markdown.element.ts +4 -3
  171. package/src/index.ts +22 -19
  172. package/src/renderer/spa/{thin-client.ts → emroute.app.ts} +19 -20
  173. package/src/renderer/spa/mod.ts +22 -22
  174. package/src/util/html.util.ts +16 -61
  175. package/src/widget/breadcrumb.widget.ts +3 -3
  176. package/src/widget/page-title.widget.ts +1 -1
  177. package/dist/src/component/abstract.component.d.ts +0 -199
  178. package/dist/src/component/abstract.component.js +0 -84
  179. package/dist/src/component/abstract.component.js.map +0 -1
  180. package/dist/src/component/page.component.d.ts +0 -74
  181. package/dist/src/component/page.component.js +0 -107
  182. package/dist/src/component/page.component.js.map +0 -1
  183. package/dist/src/component/widget.component.d.ts +0 -47
  184. package/dist/src/component/widget.component.js +0 -69
  185. package/dist/src/component/widget.component.js.map +0 -1
  186. package/dist/src/renderer/ssr/html.renderer.js.map +0 -1
  187. package/dist/src/renderer/ssr/md.renderer.js.map +0 -1
  188. package/dist/src/renderer/ssr/ssr.renderer.js.map +0 -1
  189. package/dist/src/route/route-tree.util.js.map +0 -1
  190. package/dist/src/route/route.matcher.d.ts +0 -86
  191. package/dist/src/route/route.matcher.js +0 -214
  192. package/dist/src/route/route.matcher.js.map +0 -1
  193. package/dist/src/route/route.resolver.js.map +0 -1
  194. package/dist/src/route/route.trie.d.ts +0 -38
  195. package/dist/src/route/route.trie.js +0 -206
  196. package/dist/src/route/route.trie.js.map +0 -1
  197. package/dist/src/type/element.type.d.ts +0 -19
  198. package/dist/src/type/element.type.js +0 -9
  199. package/dist/src/type/element.type.js.map +0 -1
  200. package/dist/src/type/logger.type.d.ts +0 -17
  201. package/dist/src/type/logger.type.js +0 -9
  202. package/dist/src/type/logger.type.js.map +0 -1
  203. package/dist/src/type/markdown.type.d.ts +0 -20
  204. package/dist/src/type/markdown.type.js +0 -2
  205. package/dist/src/type/markdown.type.js.map +0 -1
  206. package/dist/src/type/route-tree.type.js.map +0 -1
  207. package/dist/src/type/route.type.d.ts +0 -94
  208. package/dist/src/type/route.type.js +0 -8
  209. package/dist/src/type/route.type.js.map +0 -1
  210. package/dist/src/type/widget.type.d.ts +0 -55
  211. package/dist/src/type/widget.type.js +0 -10
  212. package/dist/src/type/widget.type.js.map +0 -1
  213. package/dist/src/util/logger.util.d.ts +0 -26
  214. package/dist/src/util/logger.util.js +0 -80
  215. package/dist/src/util/logger.util.js.map +0 -1
  216. package/dist/src/util/md.util.js.map +0 -1
  217. package/dist/src/util/widget-resolve.util.d.ts +0 -52
  218. package/dist/src/util/widget-resolve.util.js.map +0 -1
  219. package/dist/src/widget/widget.parser.js.map +0 -1
  220. package/dist/src/widget/widget.registry.d.ts +0 -23
  221. package/dist/src/widget/widget.registry.js +0 -42
  222. package/dist/src/widget/widget.registry.js.map +0 -1
  223. package/runtime/bun/esbuild-runtime-loader.plugin.ts +0 -112
  224. package/server/esbuild-manifest.plugin.ts +0 -209
  225. package/server/server-api.type.ts +0 -101
  226. package/src/component/abstract.component.ts +0 -231
  227. package/src/component/widget.component.ts +0 -85
  228. package/src/route/route.core.ts +0 -371
  229. package/src/route/route.trie.ts +0 -265
  230. package/src/type/element.type.ts +0 -22
  231. package/src/type/logger.type.ts +0 -24
  232. package/src/type/markdown.type.ts +0 -21
  233. package/src/type/route-tree.type.ts +0 -51
  234. package/src/type/route.type.ts +0 -124
  235. package/src/type/widget.type.ts +0 -65
  236. package/src/util/logger.util.ts +0 -83
  237. package/src/widget/widget.registry.ts +0 -51
  238. /package/dist/{src/route → core/util}/route-tree.util.d.ts +0 -0
@@ -4,43 +4,43 @@
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
- widgetFiles;
17
- constructor(resolver, options = {}) {
18
- this.core = new RouteCore(resolver, options);
16
+ logger;
17
+ constructor(pipeline, options = {}) {
18
+ this.pipeline = pipeline;
19
+ this.logger = pipeline.logger;
19
20
  this.widgets = options.widgets ?? null;
20
- this.widgetFiles = options.widgetFiles ?? {};
21
21
  }
22
22
  /**
23
23
  * Render a URL to a content string.
24
24
  */
25
25
  async render(url, signal) {
26
- const matched = this.core.match(url);
26
+ const matched = await this.pipeline.match(url);
27
27
  if (!matched) {
28
- const statusPage = this.core.getStatusPage(404);
28
+ const statusPage = await this.pipeline.getStatusPage(404);
29
29
  if (statusPage) {
30
30
  try {
31
31
  const ri = { url, params: {} };
32
32
  const result = await this.renderRouteContent(ri, statusPage, undefined, signal);
33
- return { content: this.stripSlots(result.content), status: 404, ...(result.title != null ? { title: result.title } : {}) };
33
+ return { content: this.stripSlots(result.content), status: 404, ...(result.title !== undefined ? { title: result.title } : {}) };
34
34
  }
35
35
  catch (e) {
36
- logger.error(`[${this.label}] Failed to render 404 status page for ${url.pathname}`, e instanceof Error ? e : undefined);
36
+ this.logger.error(`[${this.label}] Failed to render 404 status page for ${url.pathname}`, e instanceof Error ? e : undefined);
37
37
  }
38
38
  }
39
39
  return { content: this.renderStatusPage(404, url), status: 404 };
40
40
  }
41
41
  // Handle redirect
42
42
  if (matched.route.type === 'redirect') {
43
- const module = await this.core.loadModule(matched.route.modulePath);
43
+ const module = await this.pipeline.loadModule(matched.route.modulePath);
44
44
  const redirectConfig = module.default;
45
45
  assertSafeRedirect(redirectConfig.to);
46
46
  return {
@@ -49,14 +49,14 @@ export class SsrRenderer {
49
49
  redirect: redirectConfig.to,
50
50
  };
51
51
  }
52
- const routeInfo = this.core.toRouteInfo(matched, url);
52
+ const routeInfo = this.pipeline.toRouteInfo(matched, url);
53
53
  try {
54
54
  const { content, title } = await this.renderPage(routeInfo, matched, signal);
55
- return { content, status: 200, ...(title != null ? { title } : {}) };
55
+ return { content, status: 200, ...(title !== undefined ? { title } : {}) };
56
56
  }
57
57
  catch (error) {
58
58
  if (error instanceof Response) {
59
- const statusPage = this.core.getStatusPage(error.status);
59
+ const statusPage = await this.pipeline.getStatusPage(error.status);
60
60
  if (statusPage) {
61
61
  try {
62
62
  const ri = { url, params: {} };
@@ -64,23 +64,23 @@ export class SsrRenderer {
64
64
  return {
65
65
  content: this.stripSlots(result.content),
66
66
  status: error.status,
67
- ...(result.title != null ? { title: result.title } : {}),
67
+ ...(result.title !== undefined ? { title: result.title } : {}),
68
68
  };
69
69
  }
70
70
  catch (e) {
71
- logger.error(`[${this.label}] Failed to render ${error.status} status page for ${url.pathname}`, e instanceof Error ? e : undefined);
71
+ this.logger.error(`[${this.label}] Failed to render ${error.status} status page for ${url.pathname}`, e instanceof Error ? e : undefined);
72
72
  }
73
73
  }
74
74
  return { content: this.renderStatusPage(error.status, url), status: error.status };
75
75
  }
76
- logger.error(`[${this.label}] Error rendering ${url.pathname}:`, error instanceof Error ? error : undefined);
77
- const boundary = this.core.findErrorBoundary(url.pathname);
76
+ this.logger.error(`[${this.label}] Error rendering ${url.pathname}:`, error instanceof Error ? error : undefined);
77
+ const boundary = await this.pipeline.findErrorBoundary(url.pathname);
78
78
  if (boundary) {
79
79
  const result = await this.tryRenderErrorModule(boundary.modulePath, url, 'boundary');
80
80
  if (result)
81
81
  return result;
82
82
  }
83
- const errorHandler = this.core.getErrorHandler();
83
+ const errorHandler = await this.pipeline.getErrorHandler();
84
84
  if (errorHandler) {
85
85
  const result = await this.tryRenderErrorModule(errorHandler.modulePath, url, 'handler');
86
86
  if (result)
@@ -93,12 +93,11 @@ export class SsrRenderer {
93
93
  * Render a matched page by composing the route hierarchy.
94
94
  */
95
95
  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)
96
+ const hierarchy = this.pipeline.buildRouteHierarchy(matched.route.pattern);
98
97
  const segments = [];
99
98
  for (let i = 0; i < hierarchy.length; i++) {
100
99
  const routePattern = hierarchy[i];
101
- let route = this.core.findRoute(routePattern);
100
+ let route = await this.pipeline.findRoute(routePattern);
102
101
  if (!route && routePattern === '/') {
103
102
  route = DEFAULT_ROOT_ROUTE;
104
103
  }
@@ -108,9 +107,7 @@ export class SsrRenderer {
108
107
  continue;
109
108
  segments.push({ route, isLeaf: i === hierarchy.length - 1 });
110
109
  }
111
- // Fire all renderRouteContent calls in parallel
112
110
  const results = await Promise.all(segments.map(({ route, isLeaf }) => this.renderRouteContent(routeInfo, route, isLeaf, signal)));
113
- // Sequential slot injection
114
111
  let result = '';
115
112
  let pageTitle;
116
113
  let lastRenderedPattern = '';
@@ -125,7 +122,7 @@ export class SsrRenderer {
125
122
  else {
126
123
  const injected = this.injectSlot(result, content, lastRenderedPattern);
127
124
  if (injected === result) {
128
- logger.warn(`[${this.label}] Route "${lastRenderedPattern}" has no <router-slot> ` +
125
+ this.logger.warn(`[${this.label}] Route "${lastRenderedPattern}" has no <router-slot> ` +
129
126
  `for child route "${hierarchy[i]}" to render into. ` +
130
127
  `Add <router-slot></router-slot> to the parent template.`);
131
128
  }
@@ -134,30 +131,29 @@ export class SsrRenderer {
134
131
  lastRenderedPattern = segments[i].route.pattern;
135
132
  }
136
133
  result = this.stripSlots(result);
137
- return { content: result, ...(pageTitle != null ? { title: pageTitle } : {}) };
134
+ return { content: result, ...(pageTitle !== undefined ? { title: pageTitle } : {}) };
138
135
  }
139
136
  /** Load component, build context, get data, render content, get title. */
140
137
  async loadRouteContent(routeInfo, route, isLeaf, signal) {
141
138
  const files = route.files ?? {};
142
139
  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);
140
+ const loadedModule = tsModule
141
+ ? await this.pipeline.loadModule(tsModule)
142
+ : undefined;
143
+ const component = loadedModule?.default ?? defaultPageComponent;
144
+ const context = await this.pipeline.buildContext(routeInfo, route, signal, isLeaf, loadedModule);
147
145
  const data = await component.getData({ params: routeInfo.params, ...(signal ? { signal } : {}), context });
148
146
  const content = this.renderContent(component, { data, params: routeInfo.params, context });
149
147
  const title = component.getTitle({ data, params: routeInfo.params, context });
150
- return { content, ...(title != null ? { title } : {}) };
148
+ return { content, ...(title !== undefined ? { title } : {}) };
151
149
  }
152
- /** Render a component for error boundary/handler with minimal context. */
153
150
  renderComponent(component, data, context) {
154
151
  return this.renderContent(component, { data, params: {}, context });
155
152
  }
156
153
  static EMPTY_URL = new URL('http://error');
157
- /** Try to load and render an error boundary or handler module. Returns null on failure. */
158
154
  async tryRenderErrorModule(modulePath, url, kind) {
159
155
  try {
160
- const module = await this.core.loadModule(modulePath);
156
+ const module = await this.pipeline.loadModule(modulePath);
161
157
  const component = module.default;
162
158
  const minCtx = {
163
159
  url: SsrRenderer.EMPTY_URL,
@@ -170,7 +166,7 @@ export class SsrRenderer {
170
166
  return { content, status: 500 };
171
167
  }
172
168
  catch (e) {
173
- logger.error(`[${this.label}] Error ${kind} failed for ${url.pathname}`, e instanceof Error ? e : undefined);
169
+ this.logger.error(`[${this.label}] Error ${kind} failed for ${url.pathname}`, e instanceof Error ? e : undefined);
174
170
  return null;
175
171
  }
176
172
  }
@@ -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(segment);
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
+ }