@emkodev/emroute 1.6.6-beta.2 → 1.6.6-beta.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.
- package/dist/emroute.js +2757 -0
- package/dist/emroute.js.map +7 -0
- package/dist/runtime/abstract.runtime.d.ts +0 -28
- package/dist/runtime/abstract.runtime.js +10 -58
- package/dist/runtime/abstract.runtime.js.map +1 -1
- package/dist/runtime/bun/esbuild-runtime-loader.plugin.js +3 -0
- package/dist/runtime/bun/esbuild-runtime-loader.plugin.js.map +1 -1
- package/dist/runtime/bun/fs/bun-fs.runtime.d.ts +0 -5
- package/dist/runtime/bun/fs/bun-fs.runtime.js +1 -95
- package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -1
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.d.ts +0 -5
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +2 -96
- package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -1
- package/dist/runtime/fetch.runtime.d.ts +26 -0
- package/dist/runtime/fetch.runtime.js +55 -0
- package/dist/runtime/fetch.runtime.js.map +1 -0
- package/dist/runtime/sitemap.generator.d.ts +4 -4
- package/dist/runtime/sitemap.generator.js +32 -11
- package/dist/runtime/sitemap.generator.js.map +1 -1
- package/dist/runtime/universal/fs/universal-fs.runtime.d.ts +0 -5
- package/dist/runtime/universal/fs/universal-fs.runtime.js +1 -95
- package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -1
- package/dist/server/build.util.d.ts +38 -0
- package/dist/server/build.util.js +133 -0
- package/dist/server/build.util.js.map +1 -0
- package/dist/server/codegen.util.d.ts +3 -0
- package/dist/server/codegen.util.js +28 -10
- package/dist/server/codegen.util.js.map +1 -1
- package/dist/server/emroute.server.js +53 -29
- package/dist/server/emroute.server.js.map +1 -1
- package/dist/server/esbuild-manifest.plugin.js +6 -4
- package/dist/server/esbuild-manifest.plugin.js.map +1 -1
- package/dist/server/server-api.type.d.ts +6 -0
- package/dist/src/component/abstract.component.d.ts +5 -3
- package/dist/src/component/abstract.component.js.map +1 -1
- package/dist/src/element/component.element.js +5 -4
- package/dist/src/element/component.element.js.map +1 -1
- package/dist/src/renderer/spa/mod.d.ts +2 -3
- package/dist/src/renderer/spa/mod.js +2 -3
- package/dist/src/renderer/spa/mod.js.map +1 -1
- package/dist/src/renderer/spa/thin-client.d.ts +34 -0
- package/dist/src/renderer/spa/thin-client.js +138 -0
- package/dist/src/renderer/spa/thin-client.js.map +1 -0
- package/dist/src/renderer/ssr/html.renderer.d.ts +3 -3
- package/dist/src/renderer/ssr/html.renderer.js +6 -6
- package/dist/src/renderer/ssr/html.renderer.js.map +1 -1
- package/dist/src/renderer/ssr/md.renderer.d.ts +3 -3
- package/dist/src/renderer/ssr/md.renderer.js +12 -7
- package/dist/src/renderer/ssr/md.renderer.js.map +1 -1
- package/dist/src/renderer/ssr/ssr.renderer.d.ts +7 -6
- package/dist/src/renderer/ssr/ssr.renderer.js +42 -44
- package/dist/src/renderer/ssr/ssr.renderer.js.map +1 -1
- package/dist/src/route/route.core.d.ts +16 -6
- package/dist/src/route/route.core.js +44 -23
- package/dist/src/route/route.core.js.map +1 -1
- package/dist/src/type/route-tree.type.d.ts +2 -0
- package/dist/src/type/route.type.d.ts +6 -24
- package/dist/src/util/md.util.d.ts +8 -0
- package/dist/src/util/md.util.js +28 -0
- package/dist/src/util/md.util.js.map +1 -0
- package/dist/src/util/widget-resolve.util.js +6 -1
- package/dist/src/util/widget-resolve.util.js.map +1 -1
- package/dist/src/widget/breadcrumb.widget.d.ts +0 -1
- package/dist/src/widget/breadcrumb.widget.js +4 -15
- package/dist/src/widget/breadcrumb.widget.js.map +1 -1
- package/package.json +13 -2
- package/runtime/abstract.runtime.ts +9 -82
- package/runtime/bun/esbuild-runtime-loader.plugin.ts +2 -0
- package/runtime/bun/fs/bun-fs.runtime.ts +0 -109
- package/runtime/bun/sqlite/bun-sqlite.runtime.ts +1 -112
- package/runtime/fetch.runtime.ts +70 -0
- package/runtime/sitemap.generator.ts +37 -12
- package/runtime/universal/fs/universal-fs.runtime.ts +0 -109
- package/server/build.util.ts +168 -0
- package/server/codegen.util.ts +29 -11
- package/server/emroute.server.ts +50 -30
- package/server/esbuild-manifest.plugin.ts +5 -3
- package/server/server-api.type.ts +7 -0
- package/src/component/abstract.component.ts +5 -3
- package/src/element/component.element.ts +5 -4
- package/src/renderer/spa/mod.ts +2 -8
- package/src/renderer/spa/thin-client.ts +165 -0
- package/src/renderer/ssr/html.renderer.ts +6 -5
- package/src/renderer/ssr/md.renderer.ts +12 -6
- package/src/renderer/ssr/ssr.renderer.ts +54 -48
- package/src/route/route.core.ts +49 -28
- package/src/type/route-tree.type.ts +2 -0
- package/src/type/route.type.ts +7 -32
- package/src/util/md.util.ts +31 -0
- package/src/util/widget-resolve.util.ts +6 -1
- package/src/widget/breadcrumb.widget.ts +4 -16
- package/server/scanner.util.ts +0 -243
- package/src/renderer/spa/base.renderer.ts +0 -186
- package/src/renderer/spa/hash.renderer.ts +0 -238
- package/src/renderer/spa/html.renderer.ts +0 -399
- package/src/route/route.matcher.ts +0 -260
- package/src/web-doc/index.md +0 -15
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/// <reference path="../../type/navigation-api.d.ts" />
|
|
2
|
+
import { assertSafeRedirect, DEFAULT_BASE_PATH } from "../../route/route.core.js";
|
|
3
|
+
import { escapeHtml } from "../../util/html.util.js";
|
|
4
|
+
/** Browser app — Navigation API wired to an EmrouteServer. */
|
|
5
|
+
export class EmrouteApp {
|
|
6
|
+
server;
|
|
7
|
+
appBase;
|
|
8
|
+
slot = null;
|
|
9
|
+
abortController = null;
|
|
10
|
+
constructor(server, options) {
|
|
11
|
+
const bp = options?.basePath ?? DEFAULT_BASE_PATH;
|
|
12
|
+
this.server = server;
|
|
13
|
+
this.appBase = bp.app;
|
|
14
|
+
}
|
|
15
|
+
async initialize(slotSelector = 'router-slot') {
|
|
16
|
+
this.slot = document.querySelector(slotSelector);
|
|
17
|
+
if (!this.slot) {
|
|
18
|
+
console.error('[EmrouteApp] Slot not found:', slotSelector);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!('navigation' in globalThis)) {
|
|
22
|
+
console.warn('[EmrouteApp] Navigation API not available');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.abortController = new AbortController();
|
|
26
|
+
const { signal } = this.abortController;
|
|
27
|
+
navigation.addEventListener('navigate', (event) => {
|
|
28
|
+
if (!event.canIntercept)
|
|
29
|
+
return;
|
|
30
|
+
if (event.hashChange)
|
|
31
|
+
return;
|
|
32
|
+
if (event.downloadRequest !== null)
|
|
33
|
+
return;
|
|
34
|
+
const url = new URL(event.destination.url);
|
|
35
|
+
if (!this.isAppPath(url.pathname))
|
|
36
|
+
return;
|
|
37
|
+
event.intercept({
|
|
38
|
+
scroll: 'manual',
|
|
39
|
+
handler: async () => {
|
|
40
|
+
await this.handleNavigation(url, event.signal);
|
|
41
|
+
event.scroll();
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}, { signal });
|
|
45
|
+
// SSR adoption — server already rendered this page, skip re-render
|
|
46
|
+
const ssrRoute = this.slot.getAttribute('data-ssr-route');
|
|
47
|
+
if (ssrRoute && (location.pathname === ssrRoute || location.pathname === ssrRoute + '/')) {
|
|
48
|
+
this.slot.removeAttribute('data-ssr-route');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Initial render
|
|
52
|
+
await this.handleNavigation(new URL(location.href), this.abortController.signal);
|
|
53
|
+
}
|
|
54
|
+
dispose() {
|
|
55
|
+
this.abortController?.abort();
|
|
56
|
+
this.abortController = null;
|
|
57
|
+
this.slot = null;
|
|
58
|
+
}
|
|
59
|
+
async navigate(url, options = {}) {
|
|
60
|
+
try {
|
|
61
|
+
const { finished } = navigation.navigate(url, {
|
|
62
|
+
state: options.state,
|
|
63
|
+
history: options.replace ? 'replace' : 'auto',
|
|
64
|
+
});
|
|
65
|
+
await finished;
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
if (e instanceof DOMException && e.name === 'AbortError')
|
|
69
|
+
return;
|
|
70
|
+
throw e;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
isAppPath(pathname) {
|
|
74
|
+
return pathname === this.appBase || pathname.startsWith(this.appBase + '/');
|
|
75
|
+
}
|
|
76
|
+
stripAppBase(pathname) {
|
|
77
|
+
if (pathname === this.appBase)
|
|
78
|
+
return '/';
|
|
79
|
+
if (pathname.startsWith(this.appBase + '/'))
|
|
80
|
+
return pathname.slice(this.appBase.length);
|
|
81
|
+
return pathname;
|
|
82
|
+
}
|
|
83
|
+
async handleNavigation(url, signal) {
|
|
84
|
+
if (!this.slot || !this.server.htmlRouter)
|
|
85
|
+
return;
|
|
86
|
+
const routePath = this.stripAppBase(url.pathname);
|
|
87
|
+
const routeUrl = new URL(routePath + url.search, url.origin);
|
|
88
|
+
try {
|
|
89
|
+
const { content, title, redirect } = await this.server.htmlRouter.render(routeUrl, signal);
|
|
90
|
+
if (signal.aborted)
|
|
91
|
+
return;
|
|
92
|
+
if (redirect) {
|
|
93
|
+
assertSafeRedirect(redirect);
|
|
94
|
+
const target = redirect.startsWith('/') ? this.appBase + redirect : redirect;
|
|
95
|
+
navigation.navigate(target, { history: 'replace' });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (document.startViewTransition) {
|
|
99
|
+
const transition = document.startViewTransition(() => {
|
|
100
|
+
this.slot.setHTMLUnsafe(content);
|
|
101
|
+
});
|
|
102
|
+
signal.addEventListener('abort', () => transition.skipTransition(), { once: true });
|
|
103
|
+
await transition.updateCallbackDone;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
this.slot.setHTMLUnsafe(content);
|
|
107
|
+
}
|
|
108
|
+
if (title)
|
|
109
|
+
document.title = title;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (signal.aborted)
|
|
113
|
+
return;
|
|
114
|
+
console.error('[EmrouteApp] Navigation error:', error);
|
|
115
|
+
if (this.slot) {
|
|
116
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
117
|
+
this.slot.setHTMLUnsafe(`<h1>Error</h1><p>${escapeHtml(message)}</p>`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Create and initialize the browser app.
|
|
124
|
+
*
|
|
125
|
+
* Stored on `globalThis.__emroute_app` for programmatic access.
|
|
126
|
+
*/
|
|
127
|
+
export async function createEmrouteApp(server, options) {
|
|
128
|
+
const g = globalThis;
|
|
129
|
+
if (g.__emroute_app) {
|
|
130
|
+
console.warn('eMroute: App already initialized.');
|
|
131
|
+
return g.__emroute_app;
|
|
132
|
+
}
|
|
133
|
+
const app = new EmrouteApp(server, options);
|
|
134
|
+
await app.initialize();
|
|
135
|
+
g.__emroute_app = app;
|
|
136
|
+
return app;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=thin-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thin-client.js","sourceRoot":"","sources":["../../../../src/renderer/spa/thin-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,14 +28,14 @@ export declare class SsrHtmlRouter extends SsrRenderer {
|
|
|
28
28
|
/**
|
|
29
29
|
* Render a single route's content.
|
|
30
30
|
*/
|
|
31
|
-
protected renderRouteContent(routeInfo: RouteInfo, route: RouteConfig, isLeaf?: boolean): Promise<{
|
|
31
|
+
protected renderRouteContent(routeInfo: RouteInfo, route: RouteConfig, isLeaf?: boolean, signal?: AbortSignal): Promise<{
|
|
32
32
|
content: string;
|
|
33
33
|
title?: string;
|
|
34
34
|
}>;
|
|
35
35
|
protected renderContent(component: PageComponent, args: PageComponent['RenderArgs']): string;
|
|
36
36
|
protected renderRedirect(to: string): string;
|
|
37
|
-
protected renderStatusPage(status: number,
|
|
38
|
-
protected renderErrorPage(error: unknown,
|
|
37
|
+
protected renderStatusPage(status: number, url: URL): string;
|
|
38
|
+
protected renderErrorPage(error: unknown, url: URL): string;
|
|
39
39
|
/** Add pattern attribute to bare <router-slot> tags. */
|
|
40
40
|
private attributeSlots;
|
|
41
41
|
/**
|
|
@@ -33,11 +33,11 @@ export class SsrHtmlRouter extends SsrRenderer {
|
|
|
33
33
|
/**
|
|
34
34
|
* Render a single route's content.
|
|
35
35
|
*/
|
|
36
|
-
async renderRouteContent(routeInfo, route, isLeaf) {
|
|
36
|
+
async renderRouteContent(routeInfo, route, isLeaf, signal) {
|
|
37
37
|
if (route.modulePath === DEFAULT_ROOT_ROUTE.modulePath) {
|
|
38
38
|
return { content: `<router-slot pattern="${route.pattern}"></router-slot>` };
|
|
39
39
|
}
|
|
40
|
-
const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf);
|
|
40
|
+
const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf, signal);
|
|
41
41
|
let content = rawContent;
|
|
42
42
|
// Expand <mark-down> tags server-side
|
|
43
43
|
content = await this.expandMarkdown(content);
|
|
@@ -59,17 +59,17 @@ export class SsrHtmlRouter extends SsrRenderer {
|
|
|
59
59
|
renderRedirect(to) {
|
|
60
60
|
return `<meta http-equiv="refresh" content="0;url=${escapeHtml(to)}">`;
|
|
61
61
|
}
|
|
62
|
-
renderStatusPage(status,
|
|
62
|
+
renderStatusPage(status, url) {
|
|
63
63
|
return `
|
|
64
64
|
<h1>${STATUS_MESSAGES[status] ?? 'Error'}</h1>
|
|
65
|
-
<p>Path: ${escapeHtml(pathname)}</p>
|
|
65
|
+
<p>Path: ${escapeHtml(url.pathname)}</p>
|
|
66
66
|
`;
|
|
67
67
|
}
|
|
68
|
-
renderErrorPage(error,
|
|
68
|
+
renderErrorPage(error, url) {
|
|
69
69
|
const message = error instanceof Error ? error.message : String(error);
|
|
70
70
|
return `
|
|
71
71
|
<h1>Error</h1>
|
|
72
|
-
<p>Path: ${escapeHtml(pathname)}</p>
|
|
72
|
+
<p>Path: ${escapeHtml(url.pathname)}</p>
|
|
73
73
|
<p>${escapeHtml(message)}</p>
|
|
74
74
|
`;
|
|
75
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"html.renderer.js","sourceRoot":"","sources":["../../../../src/renderer/ssr/html.renderer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AAQzE;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,WAAW;IAChB,KAAK,GAAG,UAAU,CAAC;IACvC,gBAAgB,CAA0B;IAC1C,aAAa,GAAyB,IAAI,CAAC;IAEnD,YAAY,QAAuB,EAAE,UAAgC,EAAE;QACrE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzB,IAAI,CAAC,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;QAEzD,IAAI,IAAI,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACpD,CAAC;IACH,CAAC;IAEkB,UAAU,CAAC,MAAc,EAAE,KAAa,EAAE,aAAqB;QAChF,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QACrE,OAAO,MAAM,CAAC,OAAO,CACnB,IAAI,MAAM,CAAC,mCAAmC,OAAO,uBAAuB,CAAC,EAC7E,KAAK,CACN,CAAC;IACJ,CAAC;IAEkB,UAAU,CAAC,MAAc;QAC1C,OAAO,MAAM,CAAC,OAAO,CAAC,oCAAoC,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACgB,KAAK,CAAC,kBAAkB,CACzC,SAAoB,EACpB,KAAkB,EAClB,MAAgB;
|
|
1
|
+
{"version":3,"file":"html.renderer.js","sourceRoot":"","sources":["../../../../src/renderer/ssr/html.renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,14 +21,14 @@ export declare class SsrMdRouter extends SsrRenderer {
|
|
|
21
21
|
/**
|
|
22
22
|
* Render a single route's content to Markdown.
|
|
23
23
|
*/
|
|
24
|
-
protected renderRouteContent(routeInfo: RouteInfo, route: RouteConfig, isLeaf?: boolean): Promise<{
|
|
24
|
+
protected renderRouteContent(routeInfo: RouteInfo, route: RouteConfig, isLeaf?: boolean, signal?: AbortSignal): Promise<{
|
|
25
25
|
content: string;
|
|
26
26
|
title?: string;
|
|
27
27
|
}>;
|
|
28
28
|
protected renderContent(component: PageComponent, args: PageComponent['RenderArgs']): string;
|
|
29
29
|
protected renderRedirect(to: string): string;
|
|
30
|
-
protected renderStatusPage(status: number,
|
|
31
|
-
protected renderErrorPage(_error: unknown,
|
|
30
|
+
protected renderStatusPage(status: number, url: URL): string;
|
|
31
|
+
protected renderErrorPage(_error: unknown, url: URL): string;
|
|
32
32
|
/**
|
|
33
33
|
* Resolve fenced widget blocks in markdown content.
|
|
34
34
|
* Replaces ```widget:name blocks with rendered markdown output.
|
|
@@ -32,11 +32,11 @@ export class SsrMdRouter extends SsrRenderer {
|
|
|
32
32
|
/**
|
|
33
33
|
* Render a single route's content to Markdown.
|
|
34
34
|
*/
|
|
35
|
-
async renderRouteContent(routeInfo, route, isLeaf) {
|
|
35
|
+
async renderRouteContent(routeInfo, route, isLeaf, signal) {
|
|
36
36
|
if (route.modulePath === DEFAULT_ROOT_ROUTE.modulePath) {
|
|
37
37
|
return { content: routerSlotBlock(route.pattern) };
|
|
38
38
|
}
|
|
39
|
-
const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf);
|
|
39
|
+
const { content: rawContent, title } = await this.loadRouteContent(routeInfo, route, isLeaf, signal);
|
|
40
40
|
let content = rawContent;
|
|
41
41
|
// Attribute bare router-slot blocks with this route's pattern
|
|
42
42
|
// (before widget resolution so widget-internal blocks are not affected)
|
|
@@ -53,11 +53,11 @@ export class SsrMdRouter extends SsrRenderer {
|
|
|
53
53
|
renderRedirect(to) {
|
|
54
54
|
return `Redirect to: ${to}`;
|
|
55
55
|
}
|
|
56
|
-
renderStatusPage(status,
|
|
57
|
-
return `# ${STATUS_MESSAGES[status] ?? 'Error'}\n\nPath: \`${pathname}\``;
|
|
56
|
+
renderStatusPage(status, url) {
|
|
57
|
+
return `# ${STATUS_MESSAGES[status] ?? 'Error'}\n\nPath: \`${url.pathname}\``;
|
|
58
58
|
}
|
|
59
|
-
renderErrorPage(_error,
|
|
60
|
-
return `# Internal Server Error\n\nPath: \`${pathname}\``;
|
|
59
|
+
renderErrorPage(_error, url) {
|
|
60
|
+
return `# Internal Server Error\n\nPath: \`${url.pathname}\``;
|
|
61
61
|
}
|
|
62
62
|
/**
|
|
63
63
|
* Resolve fenced widget blocks in markdown content.
|
|
@@ -78,7 +78,12 @@ export class SsrMdRouter extends SsrRenderer {
|
|
|
78
78
|
if (filePaths) {
|
|
79
79
|
files = await this.core.loadWidgetFiles(filePaths);
|
|
80
80
|
}
|
|
81
|
-
const baseContext = {
|
|
81
|
+
const baseContext = {
|
|
82
|
+
...routeInfo,
|
|
83
|
+
pathname: routeInfo.url.pathname,
|
|
84
|
+
searchParams: routeInfo.url.searchParams,
|
|
85
|
+
files,
|
|
86
|
+
};
|
|
82
87
|
const context = this.core.contextProvider
|
|
83
88
|
? this.core.contextProvider(baseContext)
|
|
84
89
|
: baseContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"md.renderer.js","sourceRoot":"","sources":["../../../../src/renderer/ssr/md.renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAA2B,MAAM,mBAAmB,CAAC;AAEzE,MAAM,eAAe,GAAG,qBAAqB,CAAC;AAE9C,SAAS,eAAe,CAAC,OAAe;IACtC,OAAO,kCAAkC,OAAO,YAAY,CAAC;AAC/D,CAAC;AAKD;;GAEG;AACH,MAAM,OAAO,WAAY,SAAQ,WAAW;IACd,KAAK,GAAG,QAAQ,CAAC;IAE7C,YAAY,QAAuB,EAAE,UAA8B,EAAE;QACnE,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC;IAEkB,UAAU,CAAC,MAAc,EAAE,KAAa,EAAE,aAAqB;QAChF,OAAO,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC,CAAC;IAC/D,CAAC;IAEkB,UAAU,CAAC,MAAc;QAC1C,OAAO,MAAM;aACV,OAAO,CAAC,sCAAsC,EAAE,EAAE,CAAC;aACnD,IAAI,EAAE,CAAC;IACZ,CAAC;IAED;;OAEG;IACgB,KAAK,CAAC,kBAAkB,CACzC,SAAoB,EACpB,KAAkB,EAClB,MAAgB;
|
|
1
|
+
{"version":3,"file":"md.renderer.js","sourceRoot":"","sources":["../../../../src/renderer/ssr/md.renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,7 +37,7 @@ export declare abstract class SsrRenderer {
|
|
|
37
37
|
/**
|
|
38
38
|
* Render a URL to a content string.
|
|
39
39
|
*/
|
|
40
|
-
render(url:
|
|
40
|
+
render(url: URL, signal?: AbortSignal): Promise<{
|
|
41
41
|
content: string;
|
|
42
42
|
status: number;
|
|
43
43
|
title?: string;
|
|
@@ -46,16 +46,16 @@ export declare abstract class SsrRenderer {
|
|
|
46
46
|
/**
|
|
47
47
|
* Render a matched page by composing the route hierarchy.
|
|
48
48
|
*/
|
|
49
|
-
protected renderPage(routeInfo: RouteInfo, matched: MatchedRoute): Promise<{
|
|
49
|
+
protected renderPage(routeInfo: RouteInfo, matched: MatchedRoute, signal?: AbortSignal): Promise<{
|
|
50
50
|
content: string;
|
|
51
51
|
title?: string;
|
|
52
52
|
}>;
|
|
53
|
-
protected abstract renderRouteContent(routeInfo: RouteInfo, route: RouteConfig, isLeaf?: boolean): Promise<{
|
|
53
|
+
protected abstract renderRouteContent(routeInfo: RouteInfo, route: RouteConfig, isLeaf?: boolean, signal?: AbortSignal): Promise<{
|
|
54
54
|
content: string;
|
|
55
55
|
title?: string;
|
|
56
56
|
}>;
|
|
57
57
|
/** Load component, build context, get data, render content, get title. */
|
|
58
|
-
protected loadRouteContent(routeInfo: RouteInfo, route: RouteConfig, isLeaf?: boolean): Promise<{
|
|
58
|
+
protected loadRouteContent(routeInfo: RouteInfo, route: RouteConfig, isLeaf?: boolean, signal?: AbortSignal): Promise<{
|
|
59
59
|
content: string;
|
|
60
60
|
title?: string;
|
|
61
61
|
}>;
|
|
@@ -63,11 +63,12 @@ export declare abstract class SsrRenderer {
|
|
|
63
63
|
protected abstract renderContent(component: PageComponent, args: PageComponent['RenderArgs']): string;
|
|
64
64
|
/** Render a component for error boundary/handler with minimal context. */
|
|
65
65
|
protected renderComponent(component: PageComponent, data: unknown, context: ComponentContext): string;
|
|
66
|
+
private static readonly EMPTY_URL;
|
|
66
67
|
/** Try to load and render an error boundary or handler module. Returns null on failure. */
|
|
67
68
|
private tryRenderErrorModule;
|
|
68
69
|
protected abstract renderRedirect(to: string): string;
|
|
69
|
-
protected abstract renderStatusPage(status: number,
|
|
70
|
-
protected abstract renderErrorPage(error: unknown,
|
|
70
|
+
protected abstract renderStatusPage(status: number, url: URL): string;
|
|
71
|
+
protected abstract renderErrorPage(error: unknown, url: URL): string;
|
|
71
72
|
/** Inject child content into the slot owned by parentPattern. */
|
|
72
73
|
protected abstract injectSlot(parent: string, child: string, parentPattern: string): string;
|
|
73
74
|
/** Strip all unconsumed slot placeholders from the final result. */
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
import { logger } from "../../type/logger.type.js";
|
|
8
8
|
import defaultPageComponent from "../../component/page.component.js";
|
|
9
9
|
import { assertSafeRedirect, DEFAULT_ROOT_ROUTE, RouteCore, } from "../../route/route.core.js";
|
|
10
|
-
import { toUrl } from "../../route/route.matcher.js";
|
|
11
10
|
/**
|
|
12
11
|
* Abstract SSR renderer with shared routing pipeline.
|
|
13
12
|
*/
|
|
@@ -23,24 +22,21 @@ export class SsrRenderer {
|
|
|
23
22
|
/**
|
|
24
23
|
* Render a URL to a content string.
|
|
25
24
|
*/
|
|
26
|
-
async render(url) {
|
|
27
|
-
const
|
|
28
|
-
const pathname = urlObj.pathname;
|
|
29
|
-
const matched = this.core.match(urlObj);
|
|
30
|
-
const searchParams = urlObj.searchParams ?? new URLSearchParams();
|
|
25
|
+
async render(url, signal) {
|
|
26
|
+
const matched = this.core.match(url);
|
|
31
27
|
if (!matched) {
|
|
32
28
|
const statusPage = this.core.getStatusPage(404);
|
|
33
29
|
if (statusPage) {
|
|
34
30
|
try {
|
|
35
|
-
const ri = {
|
|
36
|
-
const result = await this.renderRouteContent(ri, statusPage);
|
|
31
|
+
const ri = { url, params: {} };
|
|
32
|
+
const result = await this.renderRouteContent(ri, statusPage, undefined, signal);
|
|
37
33
|
return { content: this.stripSlots(result.content), status: 404, title: result.title };
|
|
38
34
|
}
|
|
39
35
|
catch (e) {
|
|
40
|
-
logger.error(`[${this.label}] Failed to render 404 status page for ${pathname}`, e instanceof Error ? e : undefined);
|
|
36
|
+
logger.error(`[${this.label}] Failed to render 404 status page for ${url.pathname}`, e instanceof Error ? e : undefined);
|
|
41
37
|
}
|
|
42
38
|
}
|
|
43
|
-
return { content: this.renderStatusPage(404,
|
|
39
|
+
return { content: this.renderStatusPage(404, url), status: 404 };
|
|
44
40
|
}
|
|
45
41
|
// Handle redirect
|
|
46
42
|
if (matched.route.type === 'redirect') {
|
|
@@ -53,9 +49,9 @@ export class SsrRenderer {
|
|
|
53
49
|
redirect: redirectConfig.to,
|
|
54
50
|
};
|
|
55
51
|
}
|
|
56
|
-
const routeInfo = this.core.toRouteInfo(matched,
|
|
52
|
+
const routeInfo = this.core.toRouteInfo(matched, url);
|
|
57
53
|
try {
|
|
58
|
-
const { content, title } = await this.renderPage(routeInfo, matched);
|
|
54
|
+
const { content, title } = await this.renderPage(routeInfo, matched, signal);
|
|
59
55
|
return { content, status: 200, title };
|
|
60
56
|
}
|
|
61
57
|
catch (error) {
|
|
@@ -63,13 +59,8 @@ export class SsrRenderer {
|
|
|
63
59
|
const statusPage = this.core.getStatusPage(error.status);
|
|
64
60
|
if (statusPage) {
|
|
65
61
|
try {
|
|
66
|
-
const ri = {
|
|
67
|
-
|
|
68
|
-
pattern: statusPage.pattern,
|
|
69
|
-
params: {},
|
|
70
|
-
searchParams,
|
|
71
|
-
};
|
|
72
|
-
const result = await this.renderRouteContent(ri, statusPage);
|
|
62
|
+
const ri = { url, params: {} };
|
|
63
|
+
const result = await this.renderRouteContent(ri, statusPage, undefined, signal);
|
|
73
64
|
return {
|
|
74
65
|
content: this.stripSlots(result.content),
|
|
75
66
|
status: error.status,
|
|
@@ -77,35 +68,34 @@ export class SsrRenderer {
|
|
|
77
68
|
};
|
|
78
69
|
}
|
|
79
70
|
catch (e) {
|
|
80
|
-
logger.error(`[${this.label}] Failed to render ${error.status} status page for ${pathname}`, e instanceof Error ? e : undefined);
|
|
71
|
+
logger.error(`[${this.label}] Failed to render ${error.status} status page for ${url.pathname}`, e instanceof Error ? e : undefined);
|
|
81
72
|
}
|
|
82
73
|
}
|
|
83
|
-
return { content: this.renderStatusPage(error.status,
|
|
74
|
+
return { content: this.renderStatusPage(error.status, url), status: error.status };
|
|
84
75
|
}
|
|
85
|
-
logger.error(`[${this.label}] Error rendering ${pathname}:`, error instanceof Error ? error : undefined);
|
|
86
|
-
const boundary = this.core.findErrorBoundary(pathname);
|
|
76
|
+
logger.error(`[${this.label}] Error rendering ${url.pathname}:`, error instanceof Error ? error : undefined);
|
|
77
|
+
const boundary = this.core.findErrorBoundary(url.pathname);
|
|
87
78
|
if (boundary) {
|
|
88
|
-
const result = await this.tryRenderErrorModule(boundary.modulePath,
|
|
79
|
+
const result = await this.tryRenderErrorModule(boundary.modulePath, url, 'boundary');
|
|
89
80
|
if (result)
|
|
90
81
|
return result;
|
|
91
82
|
}
|
|
92
83
|
const errorHandler = this.core.getErrorHandler();
|
|
93
84
|
if (errorHandler) {
|
|
94
|
-
const result = await this.tryRenderErrorModule(errorHandler.modulePath,
|
|
85
|
+
const result = await this.tryRenderErrorModule(errorHandler.modulePath, url, 'handler');
|
|
95
86
|
if (result)
|
|
96
87
|
return result;
|
|
97
88
|
}
|
|
98
|
-
return { content: this.renderErrorPage(error,
|
|
89
|
+
return { content: this.renderErrorPage(error, url), status: 500 };
|
|
99
90
|
}
|
|
100
91
|
}
|
|
101
92
|
/**
|
|
102
93
|
* Render a matched page by composing the route hierarchy.
|
|
103
94
|
*/
|
|
104
|
-
async renderPage(routeInfo, matched) {
|
|
105
|
-
const hierarchy = this.core.buildRouteHierarchy(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
let lastRenderedPattern = '';
|
|
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)
|
|
98
|
+
const segments = [];
|
|
109
99
|
for (let i = 0; i < hierarchy.length; i++) {
|
|
110
100
|
const routePattern = hierarchy[i];
|
|
111
101
|
let route = this.core.findRoute(routePattern);
|
|
@@ -114,11 +104,18 @@ export class SsrRenderer {
|
|
|
114
104
|
}
|
|
115
105
|
if (!route)
|
|
116
106
|
continue;
|
|
117
|
-
// Skip wildcard route appearing as its own parent (prevents double-render)
|
|
118
107
|
if (route === matched.route && routePattern !== matched.route.pattern)
|
|
119
108
|
continue;
|
|
120
|
-
|
|
121
|
-
|
|
109
|
+
segments.push({ route, isLeaf: i === hierarchy.length - 1 });
|
|
110
|
+
}
|
|
111
|
+
// Fire all renderRouteContent calls in parallel
|
|
112
|
+
const results = await Promise.all(segments.map(({ route, isLeaf }) => this.renderRouteContent(routeInfo, route, isLeaf, signal)));
|
|
113
|
+
// Sequential slot injection
|
|
114
|
+
let result = '';
|
|
115
|
+
let pageTitle;
|
|
116
|
+
let lastRenderedPattern = '';
|
|
117
|
+
for (let i = 0; i < segments.length; i++) {
|
|
118
|
+
const { content, title } = results[i];
|
|
122
119
|
if (title) {
|
|
123
120
|
pageTitle = title;
|
|
124
121
|
}
|
|
@@ -129,25 +126,25 @@ export class SsrRenderer {
|
|
|
129
126
|
const injected = this.injectSlot(result, content, lastRenderedPattern);
|
|
130
127
|
if (injected === result) {
|
|
131
128
|
logger.warn(`[${this.label}] Route "${lastRenderedPattern}" has no <router-slot> ` +
|
|
132
|
-
`for child route "${
|
|
129
|
+
`for child route "${hierarchy[i]}" to render into. ` +
|
|
133
130
|
`Add <router-slot></router-slot> to the parent template.`);
|
|
134
131
|
}
|
|
135
132
|
result = injected;
|
|
136
133
|
}
|
|
137
|
-
lastRenderedPattern = route.pattern;
|
|
134
|
+
lastRenderedPattern = segments[i].route.pattern;
|
|
138
135
|
}
|
|
139
136
|
result = this.stripSlots(result);
|
|
140
137
|
return { content: result, title: pageTitle };
|
|
141
138
|
}
|
|
142
139
|
/** Load component, build context, get data, render content, get title. */
|
|
143
|
-
async loadRouteContent(routeInfo, route, isLeaf) {
|
|
140
|
+
async loadRouteContent(routeInfo, route, isLeaf, signal) {
|
|
144
141
|
const files = route.files ?? {};
|
|
145
|
-
const tsModule = files.ts;
|
|
142
|
+
const tsModule = files.ts ?? files.js;
|
|
146
143
|
const component = tsModule
|
|
147
144
|
? (await this.core.loadModule(tsModule)).default
|
|
148
145
|
: defaultPageComponent;
|
|
149
|
-
const context = await this.core.buildComponentContext(routeInfo, route,
|
|
150
|
-
const data = await component.getData({ params: routeInfo.params, context });
|
|
146
|
+
const context = await this.core.buildComponentContext(routeInfo, route, signal, isLeaf);
|
|
147
|
+
const data = await component.getData({ params: routeInfo.params, signal, context });
|
|
151
148
|
const content = this.renderContent(component, { data, params: routeInfo.params, context });
|
|
152
149
|
const title = component.getTitle({ data, params: routeInfo.params, context });
|
|
153
150
|
return { content, title };
|
|
@@ -156,15 +153,16 @@ export class SsrRenderer {
|
|
|
156
153
|
renderComponent(component, data, context) {
|
|
157
154
|
return this.renderContent(component, { data, params: {}, context });
|
|
158
155
|
}
|
|
156
|
+
static EMPTY_URL = new URL('http://error');
|
|
159
157
|
/** Try to load and render an error boundary or handler module. Returns null on failure. */
|
|
160
|
-
async tryRenderErrorModule(modulePath,
|
|
158
|
+
async tryRenderErrorModule(modulePath, url, kind) {
|
|
161
159
|
try {
|
|
162
160
|
const module = await this.core.loadModule(modulePath);
|
|
163
161
|
const component = module.default;
|
|
164
162
|
const minCtx = {
|
|
165
|
-
|
|
166
|
-
pattern: '',
|
|
163
|
+
url: SsrRenderer.EMPTY_URL,
|
|
167
164
|
params: {},
|
|
165
|
+
pathname: '',
|
|
168
166
|
searchParams: new URLSearchParams(),
|
|
169
167
|
};
|
|
170
168
|
const data = await component.getData({ params: {}, context: minCtx });
|
|
@@ -172,7 +170,7 @@ export class SsrRenderer {
|
|
|
172
170
|
return { content, status: 500 };
|
|
173
171
|
}
|
|
174
172
|
catch (e) {
|
|
175
|
-
logger.error(`[${this.label}] Error ${kind} failed for ${pathname}`, e instanceof Error ? e : undefined);
|
|
173
|
+
logger.error(`[${this.label}] Error ${kind} failed for ${url.pathname}`, e instanceof Error ? e : undefined);
|
|
176
174
|
return null;
|
|
177
175
|
}
|
|
178
176
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr.renderer.js","sourceRoot":"","sources":["../../../../src/renderer/ssr/ssr.renderer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AAEnD,OAAO,oBAA4C,MAAM,mCAAmC,CAAC;AAC7F,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,SAAS,GAEV,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"ssr.renderer.js","sourceRoot":"","sources":["../../../../src/renderer/ssr/ssr.renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -17,6 +17,8 @@ export interface BasePath {
|
|
|
17
17
|
html: string;
|
|
18
18
|
/** Base path for SSR Markdown rendering (default: '/md') */
|
|
19
19
|
md: string;
|
|
20
|
+
/** Base path for PWA/SPA rendering (default: '/app') */
|
|
21
|
+
app: string;
|
|
20
22
|
}
|
|
21
23
|
/** Default base paths — backward compatible with existing /html/ and /md/ prefixes. */
|
|
22
24
|
export declare const DEFAULT_BASE_PATH: BasePath;
|
|
@@ -34,8 +36,6 @@ export interface RouteCoreOptions {
|
|
|
34
36
|
fileReader?: (path: string) => Promise<string>;
|
|
35
37
|
/** Enriches every ComponentContext with app-level services before it reaches components. */
|
|
36
38
|
extendContext?: ContextProvider;
|
|
37
|
-
/** Base path stripped from URLs before matching (e.g. '/html'). No trailing slash. */
|
|
38
|
-
basePath?: string;
|
|
39
39
|
/** Module loaders keyed by path — server provides these for SSR imports. */
|
|
40
40
|
moduleLoaders?: Record<string, () => Promise<unknown>>;
|
|
41
41
|
}
|
|
@@ -46,8 +46,6 @@ export declare class RouteCore {
|
|
|
46
46
|
private readonly resolver;
|
|
47
47
|
/** Registered context provider (if any). Exposed so renderers can apply it to inline contexts. */
|
|
48
48
|
readonly contextProvider: ContextProvider | undefined;
|
|
49
|
-
/** Base path for URL matching (e.g. '/html'). Empty string when no basePath. */
|
|
50
|
-
readonly basePath: string;
|
|
51
49
|
private listeners;
|
|
52
50
|
private moduleCache;
|
|
53
51
|
private widgetFileCache;
|
|
@@ -71,7 +69,7 @@ export declare class RouteCore {
|
|
|
71
69
|
* Match a URL to a route.
|
|
72
70
|
* Falls back to the default root route for '/'.
|
|
73
71
|
*/
|
|
74
|
-
match(url: URL
|
|
72
|
+
match(url: URL): MatchedRoute | undefined;
|
|
75
73
|
/** Get status-specific page (404, 401, 403). */
|
|
76
74
|
getStatusPage(status: number): RouteConfig | undefined;
|
|
77
75
|
/** Get global error handler (root errorBoundary). */
|
|
@@ -127,9 +125,21 @@ export declare class RouteCore {
|
|
|
127
125
|
* Build a RouteInfo from a matched route and the resolved URL pathname.
|
|
128
126
|
* Called once per navigation; the result is reused across the route hierarchy.
|
|
129
127
|
*/
|
|
130
|
-
toRouteInfo(matched: MatchedRoute,
|
|
128
|
+
toRouteInfo(matched: MatchedRoute, url: URL): RouteInfo;
|
|
129
|
+
/**
|
|
130
|
+
* Get inlined `__files` from a cached module (merged module pattern).
|
|
131
|
+
* Returns undefined if the module isn't cached or has no __files.
|
|
132
|
+
*/
|
|
133
|
+
getModuleFiles(modulePath: string): {
|
|
134
|
+
html?: string;
|
|
135
|
+
md?: string;
|
|
136
|
+
css?: string;
|
|
137
|
+
} | undefined;
|
|
131
138
|
/**
|
|
132
139
|
* Build a ComponentContext by extending RouteInfo with loaded file contents.
|
|
140
|
+
*
|
|
141
|
+
* When the route module is a merged module (contains `__files`), uses
|
|
142
|
+
* inlined content directly. Otherwise falls back to reading companion files.
|
|
133
143
|
*/
|
|
134
144
|
buildComponentContext(routeInfo: RouteInfo, route: RouteConfig, signal?: AbortSignal, isLeaf?: boolean): Promise<ComponentContext>;
|
|
135
145
|
}
|