@vertz/ui-server 0.2.30 → 0.2.31
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/dom-shim/index.js +1 -1
- package/dist/index.d.ts +338 -335
- package/dist/index.js +9 -3
- package/dist/node-handler.d.ts +170 -0
- package/dist/node-handler.js +8 -0
- package/dist/shared/{chunk-bd0sgykf.js → chunk-34fexgex.js} +247 -431
- package/dist/shared/chunk-es0406qq.js +227 -0
- package/dist/shared/chunk-wb5fv233.js +216 -0
- package/dist/shared/{chunk-gcwqkynf.js → chunk-ybftdw1r.js} +1 -1
- package/dist/ssr/index.d.ts +27 -27
- package/dist/ssr/index.js +5 -3
- package/package.json +9 -5
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import {
|
|
2
|
+
escapeAttr,
|
|
3
|
+
injectIntoTemplate,
|
|
4
|
+
precomputeHandlerState,
|
|
5
|
+
resolveRouteModulepreload,
|
|
6
|
+
resolveSession,
|
|
7
|
+
safeSerialize,
|
|
8
|
+
ssrRenderProgressive,
|
|
9
|
+
ssrRenderSinglePass,
|
|
10
|
+
ssrStreamNavQueries
|
|
11
|
+
} from "./chunk-34fexgex.js";
|
|
12
|
+
|
|
13
|
+
// src/node-handler.ts
|
|
14
|
+
function createNodeHandler(options) {
|
|
15
|
+
const {
|
|
16
|
+
module,
|
|
17
|
+
ssrTimeout,
|
|
18
|
+
nonce,
|
|
19
|
+
fallbackMetrics,
|
|
20
|
+
routeChunkManifest,
|
|
21
|
+
cacheControl,
|
|
22
|
+
sessionResolver,
|
|
23
|
+
manifest,
|
|
24
|
+
progressiveHTML
|
|
25
|
+
} = options;
|
|
26
|
+
const { template, linkHeader, modulepreloadTags, splitResult } = precomputeHandlerState(options);
|
|
27
|
+
const useProgressive = progressiveHTML && splitResult && !(manifest?.routeEntries && Object.keys(manifest.routeEntries).length > 0);
|
|
28
|
+
return (req, res) => {
|
|
29
|
+
(async () => {
|
|
30
|
+
try {
|
|
31
|
+
const url = req.url ?? "/";
|
|
32
|
+
if (req.headers["x-vertz-nav"] === "1") {
|
|
33
|
+
const pathname = url.split("?")[0];
|
|
34
|
+
await handleNavRequest(req, res, module, pathname, ssrTimeout);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
let sessionScript = "";
|
|
38
|
+
let ssrAuth;
|
|
39
|
+
if (sessionResolver) {
|
|
40
|
+
const fullUrl = `http://${req.headers.host ?? "localhost"}${url}`;
|
|
41
|
+
const webRequest = new Request(fullUrl, {
|
|
42
|
+
method: req.method ?? "GET",
|
|
43
|
+
headers: req.headers
|
|
44
|
+
});
|
|
45
|
+
const result2 = await resolveSession(webRequest, sessionResolver, nonce);
|
|
46
|
+
sessionScript = result2.sessionScript;
|
|
47
|
+
ssrAuth = result2.ssrAuth;
|
|
48
|
+
}
|
|
49
|
+
if (useProgressive) {
|
|
50
|
+
await handleProgressiveRequest(req, res, module, splitResult, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, modulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const result = await ssrRenderSinglePass(module, url, {
|
|
54
|
+
ssrTimeout,
|
|
55
|
+
fallbackMetrics,
|
|
56
|
+
ssrAuth,
|
|
57
|
+
manifest
|
|
58
|
+
});
|
|
59
|
+
if (result.redirect) {
|
|
60
|
+
res.writeHead(302, { Location: result.redirect.to });
|
|
61
|
+
res.end();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const resolvedModulepreloadTags = resolveRouteModulepreload(routeChunkManifest, result.matchedRoutePatterns, modulepreloadTags);
|
|
65
|
+
const allHeadTags = [result.headTags, resolvedModulepreloadTags].filter(Boolean).join(`
|
|
66
|
+
`);
|
|
67
|
+
const html = injectIntoTemplate({
|
|
68
|
+
template,
|
|
69
|
+
appHtml: result.html,
|
|
70
|
+
appCss: result.css,
|
|
71
|
+
ssrData: result.ssrData,
|
|
72
|
+
nonce,
|
|
73
|
+
headTags: allHeadTags || undefined,
|
|
74
|
+
sessionScript
|
|
75
|
+
});
|
|
76
|
+
const headers = {
|
|
77
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
78
|
+
};
|
|
79
|
+
if (linkHeader)
|
|
80
|
+
headers.Link = linkHeader;
|
|
81
|
+
if (cacheControl)
|
|
82
|
+
headers["Cache-Control"] = cacheControl;
|
|
83
|
+
res.writeHead(200, headers);
|
|
84
|
+
res.end(html);
|
|
85
|
+
} catch (err) {
|
|
86
|
+
console.error("[SSR] Render failed:", err instanceof Error ? err.message : err);
|
|
87
|
+
if (!res.headersSent) {
|
|
88
|
+
res.writeHead(500, { "Content-Type": "text/plain" });
|
|
89
|
+
}
|
|
90
|
+
res.end("Internal Server Error");
|
|
91
|
+
}
|
|
92
|
+
})();
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async function handleProgressiveRequest(req, res, module, split, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, staticModulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest) {
|
|
96
|
+
const result = await ssrRenderProgressive(module, url, {
|
|
97
|
+
ssrTimeout,
|
|
98
|
+
fallbackMetrics,
|
|
99
|
+
ssrAuth,
|
|
100
|
+
manifest
|
|
101
|
+
});
|
|
102
|
+
if (result.redirect) {
|
|
103
|
+
res.writeHead(302, { Location: result.redirect.to });
|
|
104
|
+
res.end();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const resolvedModulepreloadTags = resolveRouteModulepreload(routeChunkManifest, result.matchedRoutePatterns, staticModulepreloadTags);
|
|
108
|
+
let headChunk = split.headTemplate;
|
|
109
|
+
const headCloseIdx = headChunk.lastIndexOf("</head>");
|
|
110
|
+
if (headCloseIdx !== -1) {
|
|
111
|
+
const injections = [];
|
|
112
|
+
if (result.css)
|
|
113
|
+
injections.push(result.css);
|
|
114
|
+
if (result.headTags)
|
|
115
|
+
injections.push(result.headTags);
|
|
116
|
+
if (resolvedModulepreloadTags)
|
|
117
|
+
injections.push(resolvedModulepreloadTags);
|
|
118
|
+
if (sessionScript)
|
|
119
|
+
injections.push(sessionScript);
|
|
120
|
+
if (injections.length > 0) {
|
|
121
|
+
headChunk = headChunk.slice(0, headCloseIdx) + injections.join(`
|
|
122
|
+
`) + `
|
|
123
|
+
` + headChunk.slice(headCloseIdx);
|
|
124
|
+
}
|
|
125
|
+
} else {
|
|
126
|
+
if (result.css)
|
|
127
|
+
headChunk += result.css;
|
|
128
|
+
if (result.headTags)
|
|
129
|
+
headChunk += result.headTags;
|
|
130
|
+
if (resolvedModulepreloadTags)
|
|
131
|
+
headChunk += resolvedModulepreloadTags;
|
|
132
|
+
if (sessionScript)
|
|
133
|
+
headChunk += sessionScript;
|
|
134
|
+
}
|
|
135
|
+
const headers = {
|
|
136
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
137
|
+
};
|
|
138
|
+
if (linkHeader)
|
|
139
|
+
headers.Link = linkHeader;
|
|
140
|
+
if (cacheControl)
|
|
141
|
+
headers["Cache-Control"] = cacheControl;
|
|
142
|
+
res.writeHead(200, headers);
|
|
143
|
+
res.write(headChunk);
|
|
144
|
+
let clientDisconnected = false;
|
|
145
|
+
req.on("close", () => {
|
|
146
|
+
clientDisconnected = true;
|
|
147
|
+
});
|
|
148
|
+
if (result.renderStream) {
|
|
149
|
+
const reader = result.renderStream.getReader();
|
|
150
|
+
let renderError;
|
|
151
|
+
try {
|
|
152
|
+
for (;; ) {
|
|
153
|
+
if (clientDisconnected) {
|
|
154
|
+
reader.cancel();
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
const { done, value } = await reader.read();
|
|
158
|
+
if (done)
|
|
159
|
+
break;
|
|
160
|
+
const canContinue = res.write(value);
|
|
161
|
+
if (!canContinue && !clientDisconnected) {
|
|
162
|
+
await new Promise((resolve) => res.once("drain", resolve));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
} catch (err) {
|
|
166
|
+
renderError = err instanceof Error ? err : new Error(String(err));
|
|
167
|
+
} finally {
|
|
168
|
+
reader.releaseLock();
|
|
169
|
+
}
|
|
170
|
+
if (renderError && !clientDisconnected) {
|
|
171
|
+
console.error("[SSR] Render error after head sent:", renderError.message);
|
|
172
|
+
const nonceAttr = nonce != null ? ` nonce="${escapeAttr(nonce)}"` : "";
|
|
173
|
+
const errorScript = `<script${nonceAttr}>document.dispatchEvent(new CustomEvent('vertz:ssr-error',` + `{detail:{message:${safeSerialize(renderError.message)}}}))</script>`;
|
|
174
|
+
res.write(errorScript);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (clientDisconnected)
|
|
178
|
+
return;
|
|
179
|
+
let tail = "";
|
|
180
|
+
if (result.ssrData.length > 0) {
|
|
181
|
+
const nonceAttr = nonce != null ? ` nonce="${escapeAttr(nonce)}"` : "";
|
|
182
|
+
tail += `<script${nonceAttr}>window.__VERTZ_SSR_DATA__=${safeSerialize(result.ssrData)};</script>`;
|
|
183
|
+
}
|
|
184
|
+
tail += split.tailTemplate;
|
|
185
|
+
res.end(tail);
|
|
186
|
+
}
|
|
187
|
+
async function handleNavRequest(req, res, module, url, ssrTimeout) {
|
|
188
|
+
res.writeHead(200, {
|
|
189
|
+
"Content-Type": "text/event-stream",
|
|
190
|
+
"Cache-Control": "no-cache"
|
|
191
|
+
});
|
|
192
|
+
try {
|
|
193
|
+
const stream = await ssrStreamNavQueries(module, url, { ssrTimeout });
|
|
194
|
+
let clientDisconnected = false;
|
|
195
|
+
req.on("close", () => {
|
|
196
|
+
clientDisconnected = true;
|
|
197
|
+
});
|
|
198
|
+
const reader = stream.getReader();
|
|
199
|
+
try {
|
|
200
|
+
for (;; ) {
|
|
201
|
+
if (clientDisconnected) {
|
|
202
|
+
reader.cancel();
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
const { done, value } = await reader.read();
|
|
206
|
+
if (done)
|
|
207
|
+
break;
|
|
208
|
+
const canContinue = res.write(value);
|
|
209
|
+
if (!canContinue && !clientDisconnected) {
|
|
210
|
+
await new Promise((resolve) => res.once("drain", resolve));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
} finally {
|
|
214
|
+
reader.releaseLock();
|
|
215
|
+
}
|
|
216
|
+
} catch {
|
|
217
|
+
res.write(`event: done
|
|
218
|
+
data: {}
|
|
219
|
+
|
|
220
|
+
`);
|
|
221
|
+
}
|
|
222
|
+
if (!res.writableEnded) {
|
|
223
|
+
res.end();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export { createNodeHandler };
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import {
|
|
2
|
+
encodeChunk,
|
|
3
|
+
escapeAttr,
|
|
4
|
+
injectIntoTemplate,
|
|
5
|
+
precomputeHandlerState,
|
|
6
|
+
resolveRouteModulepreload,
|
|
7
|
+
resolveSession,
|
|
8
|
+
safeSerialize,
|
|
9
|
+
ssrRenderProgressive,
|
|
10
|
+
ssrRenderSinglePass,
|
|
11
|
+
ssrStreamNavQueries
|
|
12
|
+
} from "./chunk-34fexgex.js";
|
|
13
|
+
|
|
14
|
+
// src/ssr-progressive-response.ts
|
|
15
|
+
function buildProgressiveResponse(options) {
|
|
16
|
+
const { headChunk, renderStream, tailChunk, ssrData, nonce, headers } = options;
|
|
17
|
+
const stream = new ReadableStream({
|
|
18
|
+
async start(controller) {
|
|
19
|
+
controller.enqueue(encodeChunk(headChunk));
|
|
20
|
+
const reader = renderStream.getReader();
|
|
21
|
+
let renderError;
|
|
22
|
+
try {
|
|
23
|
+
for (;; ) {
|
|
24
|
+
const { done, value } = await reader.read();
|
|
25
|
+
if (done)
|
|
26
|
+
break;
|
|
27
|
+
controller.enqueue(value);
|
|
28
|
+
}
|
|
29
|
+
} catch (err) {
|
|
30
|
+
renderError = err instanceof Error ? err : new Error(String(err));
|
|
31
|
+
}
|
|
32
|
+
if (renderError) {
|
|
33
|
+
console.error("[SSR] Render error after head sent:", renderError.message);
|
|
34
|
+
const nonceAttr = nonce != null ? ` nonce="${escapeAttr(nonce)}"` : "";
|
|
35
|
+
const errorScript = `<script${nonceAttr}>document.dispatchEvent(new CustomEvent('vertz:ssr-error',` + `{detail:{message:${safeSerialize(renderError.message)}}}))</script>`;
|
|
36
|
+
controller.enqueue(encodeChunk(errorScript));
|
|
37
|
+
}
|
|
38
|
+
let tail = "";
|
|
39
|
+
if (ssrData.length > 0) {
|
|
40
|
+
const nonceAttr = nonce != null ? ` nonce="${escapeAttr(nonce)}"` : "";
|
|
41
|
+
tail += `<script${nonceAttr}>window.__VERTZ_SSR_DATA__=${safeSerialize(ssrData)};</script>`;
|
|
42
|
+
}
|
|
43
|
+
tail += tailChunk;
|
|
44
|
+
controller.enqueue(encodeChunk(tail));
|
|
45
|
+
controller.close();
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const responseHeaders = {
|
|
49
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
50
|
+
...headers
|
|
51
|
+
};
|
|
52
|
+
return new Response(stream, { status: 200, headers: responseHeaders });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/ssr-handler.ts
|
|
56
|
+
function createSSRHandler(options) {
|
|
57
|
+
const {
|
|
58
|
+
module,
|
|
59
|
+
ssrTimeout,
|
|
60
|
+
nonce,
|
|
61
|
+
fallbackMetrics,
|
|
62
|
+
routeChunkManifest,
|
|
63
|
+
cacheControl,
|
|
64
|
+
sessionResolver,
|
|
65
|
+
manifest,
|
|
66
|
+
progressiveHTML
|
|
67
|
+
} = options;
|
|
68
|
+
const { template, linkHeader, modulepreloadTags, splitResult } = precomputeHandlerState(options);
|
|
69
|
+
return async (request) => {
|
|
70
|
+
const url = new URL(request.url);
|
|
71
|
+
const pathname = url.pathname;
|
|
72
|
+
if (request.headers.get("x-vertz-nav") === "1") {
|
|
73
|
+
return handleNavRequest(module, pathname, ssrTimeout);
|
|
74
|
+
}
|
|
75
|
+
let sessionScript = "";
|
|
76
|
+
let ssrAuth;
|
|
77
|
+
if (sessionResolver) {
|
|
78
|
+
const result = await resolveSession(request, sessionResolver, nonce);
|
|
79
|
+
sessionScript = result.sessionScript;
|
|
80
|
+
ssrAuth = result.ssrAuth;
|
|
81
|
+
}
|
|
82
|
+
const useProgressive = progressiveHTML && splitResult && !(manifest?.routeEntries && Object.keys(manifest.routeEntries).length > 0);
|
|
83
|
+
if (useProgressive) {
|
|
84
|
+
return handleProgressiveHTMLRequest(module, splitResult, pathname + url.search, ssrTimeout, nonce, fallbackMetrics, linkHeader, modulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest);
|
|
85
|
+
}
|
|
86
|
+
return handleHTMLRequest(module, template, pathname + url.search, ssrTimeout, nonce, fallbackMetrics, linkHeader, modulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest);
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
async function handleNavRequest(module, url, ssrTimeout) {
|
|
90
|
+
try {
|
|
91
|
+
const stream = await ssrStreamNavQueries(module, url, { ssrTimeout });
|
|
92
|
+
return new Response(stream, {
|
|
93
|
+
status: 200,
|
|
94
|
+
headers: {
|
|
95
|
+
"Content-Type": "text/event-stream",
|
|
96
|
+
"Cache-Control": "no-cache"
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
} catch {
|
|
100
|
+
return new Response(`event: done
|
|
101
|
+
data: {}
|
|
102
|
+
|
|
103
|
+
`, {
|
|
104
|
+
status: 200,
|
|
105
|
+
headers: {
|
|
106
|
+
"Content-Type": "text/event-stream",
|
|
107
|
+
"Cache-Control": "no-cache"
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
async function handleProgressiveHTMLRequest(module, split, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, staticModulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest) {
|
|
113
|
+
try {
|
|
114
|
+
const result = await ssrRenderProgressive(module, url, {
|
|
115
|
+
ssrTimeout,
|
|
116
|
+
fallbackMetrics,
|
|
117
|
+
ssrAuth,
|
|
118
|
+
manifest
|
|
119
|
+
});
|
|
120
|
+
if (result.redirect) {
|
|
121
|
+
return new Response(null, {
|
|
122
|
+
status: 302,
|
|
123
|
+
headers: { Location: result.redirect.to }
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
const modulepreloadTags = resolveRouteModulepreload(routeChunkManifest, result.matchedRoutePatterns, staticModulepreloadTags);
|
|
127
|
+
let headChunk = split.headTemplate;
|
|
128
|
+
const headCloseIdx = headChunk.lastIndexOf("</head>");
|
|
129
|
+
if (headCloseIdx !== -1) {
|
|
130
|
+
const injections = [];
|
|
131
|
+
if (result.css)
|
|
132
|
+
injections.push(result.css);
|
|
133
|
+
if (result.headTags)
|
|
134
|
+
injections.push(result.headTags);
|
|
135
|
+
if (modulepreloadTags)
|
|
136
|
+
injections.push(modulepreloadTags);
|
|
137
|
+
if (sessionScript)
|
|
138
|
+
injections.push(sessionScript);
|
|
139
|
+
if (injections.length > 0) {
|
|
140
|
+
headChunk = headChunk.slice(0, headCloseIdx) + injections.join(`
|
|
141
|
+
`) + `
|
|
142
|
+
` + headChunk.slice(headCloseIdx);
|
|
143
|
+
}
|
|
144
|
+
} else {
|
|
145
|
+
if (result.css)
|
|
146
|
+
headChunk += result.css;
|
|
147
|
+
if (result.headTags)
|
|
148
|
+
headChunk += result.headTags;
|
|
149
|
+
if (modulepreloadTags)
|
|
150
|
+
headChunk += modulepreloadTags;
|
|
151
|
+
if (sessionScript)
|
|
152
|
+
headChunk += sessionScript;
|
|
153
|
+
}
|
|
154
|
+
const headers = {};
|
|
155
|
+
if (linkHeader)
|
|
156
|
+
headers.Link = linkHeader;
|
|
157
|
+
if (cacheControl)
|
|
158
|
+
headers["Cache-Control"] = cacheControl;
|
|
159
|
+
return buildProgressiveResponse({
|
|
160
|
+
headChunk,
|
|
161
|
+
renderStream: result.renderStream,
|
|
162
|
+
tailChunk: split.tailTemplate,
|
|
163
|
+
ssrData: result.ssrData,
|
|
164
|
+
nonce,
|
|
165
|
+
headers
|
|
166
|
+
});
|
|
167
|
+
} catch (err) {
|
|
168
|
+
console.error("[SSR] Render failed:", err instanceof Error ? err.message : err);
|
|
169
|
+
return new Response("Internal Server Error", {
|
|
170
|
+
status: 500,
|
|
171
|
+
headers: { "Content-Type": "text/plain" }
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async function handleHTMLRequest(module, template, url, ssrTimeout, nonce, fallbackMetrics, linkHeader, staticModulepreloadTags, routeChunkManifest, cacheControl, sessionScript, ssrAuth, manifest) {
|
|
176
|
+
try {
|
|
177
|
+
const result = await ssrRenderSinglePass(module, url, {
|
|
178
|
+
ssrTimeout,
|
|
179
|
+
fallbackMetrics,
|
|
180
|
+
ssrAuth,
|
|
181
|
+
manifest
|
|
182
|
+
});
|
|
183
|
+
if (result.redirect) {
|
|
184
|
+
return new Response(null, {
|
|
185
|
+
status: 302,
|
|
186
|
+
headers: { Location: result.redirect.to }
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
const modulepreloadTags = resolveRouteModulepreload(routeChunkManifest, result.matchedRoutePatterns, staticModulepreloadTags);
|
|
190
|
+
const allHeadTags = [result.headTags, modulepreloadTags].filter(Boolean).join(`
|
|
191
|
+
`);
|
|
192
|
+
const html = injectIntoTemplate({
|
|
193
|
+
template,
|
|
194
|
+
appHtml: result.html,
|
|
195
|
+
appCss: result.css,
|
|
196
|
+
ssrData: result.ssrData,
|
|
197
|
+
nonce,
|
|
198
|
+
headTags: allHeadTags || undefined,
|
|
199
|
+
sessionScript
|
|
200
|
+
});
|
|
201
|
+
const headers = { "Content-Type": "text/html; charset=utf-8" };
|
|
202
|
+
if (linkHeader)
|
|
203
|
+
headers.Link = linkHeader;
|
|
204
|
+
if (cacheControl)
|
|
205
|
+
headers["Cache-Control"] = cacheControl;
|
|
206
|
+
return new Response(html, { status: 200, headers });
|
|
207
|
+
} catch (err) {
|
|
208
|
+
console.error("[SSR] Render failed:", err instanceof Error ? err.message : err);
|
|
209
|
+
return new Response("Internal Server Error", {
|
|
210
|
+
status: 500,
|
|
211
|
+
headers: { "Content-Type": "text/plain" }
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export { createSSRHandler };
|
|
@@ -707,4 +707,4 @@ function toVNode(element) {
|
|
|
707
707
|
return { tag: "span", attrs: {}, children: [String(element)] };
|
|
708
708
|
}
|
|
709
709
|
|
|
710
|
-
export {
|
|
710
|
+
export { SSRNode, SSRComment, rawHtml, SSRTextNode, SSRDocumentFragment, SSRElement, createSSRAdapter, ssrStorage, isInSSR, getSSRUrl, registerSSRQuery, getSSRQueries, setGlobalSSRTimeout, clearGlobalSSRTimeout, getGlobalSSRTimeout, installDomShim, removeDomShim, toVNode };
|
package/dist/ssr/index.d.ts
CHANGED
|
@@ -129,33 +129,6 @@ declare function stripScriptsFromStaticHTML(html: string): string;
|
|
|
129
129
|
*/
|
|
130
130
|
declare function collectPrerenderPaths(routes: CompiledRoute2[], prefix?: string): Promise<string[]>;
|
|
131
131
|
import { FontFallbackMetrics as FontFallbackMetrics4 } from "@vertz/ui";
|
|
132
|
-
import { AccessSet } from "@vertz/ui/auth";
|
|
133
|
-
interface SessionData {
|
|
134
|
-
user: {
|
|
135
|
-
id: string;
|
|
136
|
-
email: string;
|
|
137
|
-
role: string;
|
|
138
|
-
[key: string]: unknown;
|
|
139
|
-
};
|
|
140
|
-
/** Unix timestamp in milliseconds (JWT exp * 1000). */
|
|
141
|
-
expiresAt: number;
|
|
142
|
-
}
|
|
143
|
-
/** Resolved session data for SSR injection. */
|
|
144
|
-
interface SSRSessionInfo {
|
|
145
|
-
session: SessionData;
|
|
146
|
-
/**
|
|
147
|
-
* Access set from JWT acl claim.
|
|
148
|
-
* - Present (object): inline access set (no overflow)
|
|
149
|
-
* - null: access control is configured but the set overflowed the JWT
|
|
150
|
-
* - undefined: access control is not configured
|
|
151
|
-
*/
|
|
152
|
-
accessSet?: AccessSet | null;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Callback that extracts session data from a request.
|
|
156
|
-
* Returns null when no valid session exists (expired, missing, or invalid cookie).
|
|
157
|
-
*/
|
|
158
|
-
type SessionResolver = (request: Request) => Promise<SSRSessionInfo | null>;
|
|
159
132
|
import { ExtractedQuery } from "@vertz/ui-compiler";
|
|
160
133
|
/**
|
|
161
134
|
* SSR prefetch access rule evaluator.
|
|
@@ -208,6 +181,33 @@ interface SSRPrefetchManifest {
|
|
|
208
181
|
queries: ExtractedQuery[];
|
|
209
182
|
}>;
|
|
210
183
|
}
|
|
184
|
+
import { AccessSet } from "@vertz/ui/auth";
|
|
185
|
+
interface SessionData {
|
|
186
|
+
user: {
|
|
187
|
+
id: string;
|
|
188
|
+
email: string;
|
|
189
|
+
role: string;
|
|
190
|
+
[key: string]: unknown;
|
|
191
|
+
};
|
|
192
|
+
/** Unix timestamp in milliseconds (JWT exp * 1000). */
|
|
193
|
+
expiresAt: number;
|
|
194
|
+
}
|
|
195
|
+
/** Resolved session data for SSR injection. */
|
|
196
|
+
interface SSRSessionInfo {
|
|
197
|
+
session: SessionData;
|
|
198
|
+
/**
|
|
199
|
+
* Access set from JWT acl claim.
|
|
200
|
+
* - Present (object): inline access set (no overflow)
|
|
201
|
+
* - null: access control is configured but the set overflowed the JWT
|
|
202
|
+
* - undefined: access control is not configured
|
|
203
|
+
*/
|
|
204
|
+
accessSet?: AccessSet | null;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Callback that extracts session data from a request.
|
|
208
|
+
* Returns null when no valid session exists (expired, missing, or invalid cookie).
|
|
209
|
+
*/
|
|
210
|
+
type SessionResolver = (request: Request) => Promise<SSRSessionInfo | null>;
|
|
211
211
|
interface SSRHandlerOptions {
|
|
212
212
|
/** The loaded SSR module (import('./dist/server/index.js')) */
|
|
213
213
|
module: SSRModule;
|
package/dist/ssr/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createSSRHandler
|
|
2
|
+
createSSRHandler
|
|
3
|
+
} from "../shared/chunk-wb5fv233.js";
|
|
4
|
+
import {
|
|
3
5
|
injectIntoTemplate,
|
|
4
6
|
ssrDiscoverQueries,
|
|
5
7
|
ssrRenderToString
|
|
6
|
-
} from "../shared/chunk-
|
|
7
|
-
import"../shared/chunk-
|
|
8
|
+
} from "../shared/chunk-34fexgex.js";
|
|
9
|
+
import"../shared/chunk-ybftdw1r.js";
|
|
8
10
|
|
|
9
11
|
// src/prerender.ts
|
|
10
12
|
async function discoverRoutes(module) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vertz/ui-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.31",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Vertz UI server-side rendering runtime",
|
|
@@ -43,6 +43,10 @@
|
|
|
43
43
|
"./fetch-scope": {
|
|
44
44
|
"import": "./dist/fetch-scope.js",
|
|
45
45
|
"types": "./dist/fetch-scope.d.ts"
|
|
46
|
+
},
|
|
47
|
+
"./node": {
|
|
48
|
+
"import": "./dist/node-handler.js",
|
|
49
|
+
"types": "./dist/node-handler.d.ts"
|
|
46
50
|
}
|
|
47
51
|
},
|
|
48
52
|
"files": [
|
|
@@ -58,15 +62,15 @@
|
|
|
58
62
|
"@ampproject/remapping": "^2.3.0",
|
|
59
63
|
"@capsizecss/unpack": "^4.0.0",
|
|
60
64
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
61
|
-
"@vertz/core": "^0.2.
|
|
62
|
-
"@vertz/ui": "^0.2.
|
|
63
|
-
"@vertz/ui-compiler": "^0.2.
|
|
65
|
+
"@vertz/core": "^0.2.30",
|
|
66
|
+
"@vertz/ui": "^0.2.30",
|
|
67
|
+
"@vertz/ui-compiler": "^0.2.30",
|
|
64
68
|
"magic-string": "^0.30.0",
|
|
65
69
|
"sharp": "^0.34.5",
|
|
66
70
|
"ts-morph": "^27.0.2"
|
|
67
71
|
},
|
|
68
72
|
"devDependencies": {
|
|
69
|
-
"@vertz/codegen": "^0.2.
|
|
73
|
+
"@vertz/codegen": "^0.2.30",
|
|
70
74
|
"@vertz/ui-auth": "^0.2.19",
|
|
71
75
|
"bun-types": "^1.3.10",
|
|
72
76
|
"bunup": "^0.16.31",
|