@vesk/adapter 0.2.94 → 0.2.95
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/client-bundle.d.ts.map +1 -1
- package/dist/client-bundle.js +48 -7
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +8 -1
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +13 -1
- package/dist/prod-server.d.ts.map +1 -1
- package/dist/prod-server.js +235 -193
- package/dist/ssr-function.d.ts.map +1 -1
- package/dist/ssr-function.js +18 -3
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-bundle.d.ts","sourceRoot":"","sources":["../src/client-bundle.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,kBAAkB,EAAmF,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"client-bundle.d.ts","sourceRoot":"","sources":["../src/client-bundle.ts"],"names":[],"mappings":"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"}
|
package/dist/client-bundle.js
CHANGED
|
@@ -59,12 +59,24 @@ function fileUnchanged(filePath, cached) {
|
|
|
59
59
|
return false;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
function
|
|
62
|
+
function hasServerMiddleware(nodes) {
|
|
63
|
+
for (const node of nodes) {
|
|
64
|
+
if (node.hasMiddleware)
|
|
65
|
+
return true;
|
|
66
|
+
if (node.children?.length && hasServerMiddleware(node.children))
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
function buildRouterOpts(options, serverMiddleware) {
|
|
63
72
|
const ttl = options?.routeDataCache;
|
|
73
|
+
const opts = [];
|
|
74
|
+
if (serverMiddleware)
|
|
75
|
+
opts.push('serverMiddleware: true');
|
|
64
76
|
if (typeof ttl === 'number' && ttl > 0) {
|
|
65
|
-
|
|
77
|
+
opts.push(`routeDataCache: ${ttl}`);
|
|
66
78
|
}
|
|
67
|
-
return '';
|
|
79
|
+
return opts.length ? `, { ${opts.join(', ')} }` : '';
|
|
68
80
|
}
|
|
69
81
|
function findRuntimeSrc(appDir) {
|
|
70
82
|
const monorepoRoot = resolve(__dirname, '..', '..', '..');
|
|
@@ -143,7 +155,7 @@ function isAnyImport(node) {
|
|
|
143
155
|
* map (registrations would land on a detached object).
|
|
144
156
|
*/
|
|
145
157
|
function isRuntimePreamble(node) {
|
|
146
|
-
if (node.type === 'FunctionDeclaration' && (node.id?.name === '__cleanup' || node.id?.name === '__place')) {
|
|
158
|
+
if (node.type === 'FunctionDeclaration' && (node.id?.name === '__cleanup' || node.id?.name === '__place' || node.id?.name === '__reconcileRegion')) {
|
|
147
159
|
return true;
|
|
148
160
|
}
|
|
149
161
|
if (node.type === 'VariableDeclaration') {
|
|
@@ -1920,6 +1932,31 @@ async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, impo
|
|
|
1920
1932
|
'\tfallback.appendChild(end);\n' +
|
|
1921
1933
|
'\tfor (let i = 0; i < nodes.length; i++) fallback.insertBefore(nodes[i], end);\n' +
|
|
1922
1934
|
'}\n';
|
|
1935
|
+
const reconcileRegionFn = 'function __reconcileRegion(parent, id, branch, walker) {\n' +
|
|
1936
|
+
'\tif (!parent) return;\n' +
|
|
1937
|
+
'\tlet start = null;\n' +
|
|
1938
|
+
'\tlet end = null;\n' +
|
|
1939
|
+
'\tfor (let n = parent.firstChild; n; n = n.nextSibling) {\n' +
|
|
1940
|
+
'\t\tif (n.nodeType !== 8) continue;\n' +
|
|
1941
|
+
"\t\tconst text = n.textContent || '';\n" +
|
|
1942
|
+
"\t\tif (text === 'vesk-r:' + id + ':0' || text === 'vesk-r:' + id + ':1') start = n;\n" +
|
|
1943
|
+
"\t\telse if (text === 'vesk-r-end:' + id) end = n;\n" +
|
|
1944
|
+
'\t\tif (start && end) break;\n' +
|
|
1945
|
+
'\t}\n' +
|
|
1946
|
+
'\tif (!start || !end) return;\n' +
|
|
1947
|
+
"\tconst ssrBranch = (start.textContent || '').slice(-2) === ':1' ? 1 : 0;\n" +
|
|
1948
|
+
'\tif (ssrBranch !== branch) {\n' +
|
|
1949
|
+
'\t\tlet n = start.nextSibling;\n' +
|
|
1950
|
+
'\t\twhile (n && n !== end) {\n' +
|
|
1951
|
+
'\t\t\tconst next = n.nextSibling;\n' +
|
|
1952
|
+
'\t\t\tn.remove();\n' +
|
|
1953
|
+
'\t\t\tn = next;\n' +
|
|
1954
|
+
'\t\t}\n' +
|
|
1955
|
+
'\t\tif (walker && walker.retireDetached) walker.retireDetached();\n' +
|
|
1956
|
+
'\t}\n' +
|
|
1957
|
+
'\tstart.remove();\n' +
|
|
1958
|
+
'\tend.remove();\n' +
|
|
1959
|
+
'}\n';
|
|
1923
1960
|
const updateComponentsFn = 'function __updateComponents(nodes) {\n' +
|
|
1924
1961
|
' for (const n of nodes) {\n' +
|
|
1925
1962
|
" if (n._pageName && __components[n._pageName]) n.page = __components[n._pageName];\n" +
|
|
@@ -1956,7 +1993,7 @@ async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, impo
|
|
|
1956
1993
|
' }\n' +
|
|
1957
1994
|
' }\n' +
|
|
1958
1995
|
'}\n';
|
|
1959
|
-
const routerOpts = buildRouterOpts({ routeDataCache });
|
|
1996
|
+
const routerOpts = buildRouterOpts({ routeDataCache }, hasServerMiddleware(routeTree));
|
|
1960
1997
|
const startRouterCode = 'const __startRouter = function() {\n' +
|
|
1961
1998
|
' __updateComponents(__routeTree);\n' +
|
|
1962
1999
|
` const __router = createFileRouter(__routeTree${routerOpts});\n` +
|
|
@@ -1989,7 +2026,8 @@ async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, impo
|
|
|
1989
2026
|
.join('') +
|
|
1990
2027
|
'globalThis.__runtime_comps = __runtime_comps;\n' +
|
|
1991
2028
|
'globalThis.__cleanup = __cleanup;\n' +
|
|
1992
|
-
'globalThis.__place = __place;\n
|
|
2029
|
+
'globalThis.__place = __place;\n' +
|
|
2030
|
+
'globalThis.__reconcileRegion = __reconcileRegion;\n\n';
|
|
1993
2031
|
const extraGlobals = [...(runtimeImportNames || [])]
|
|
1994
2032
|
.filter(n => n && n !== 'default')
|
|
1995
2033
|
.map(n => `globalThis.${n} = ${n};\n`)
|
|
@@ -2006,6 +2044,7 @@ async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, impo
|
|
|
2006
2044
|
(sharedModuleBundle ? sharedModuleBundle + '\n' : '') +
|
|
2007
2045
|
cleanupFn +
|
|
2008
2046
|
placeFn +
|
|
2047
|
+
reconcileRegionFn +
|
|
2009
2048
|
'globalThis.__components = __components;\n' +
|
|
2010
2049
|
resolveNamesFn +
|
|
2011
2050
|
updateComponentsFn +
|
|
@@ -2021,7 +2060,7 @@ async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, impo
|
|
|
2021
2060
|
const hydratorAliasLines = mono?.hydratorAliasLines || [];
|
|
2022
2061
|
const aliasCode = aliasLines.length > 0 ? aliasLines.join('\n') + '\n' : '';
|
|
2023
2062
|
const hydratorAliasCode = hydratorAliasLines.length > 0 ? hydratorAliasLines.join('\n') + '\n' : '';
|
|
2024
|
-
const routerOpts = buildRouterOpts({ routeDataCache });
|
|
2063
|
+
const routerOpts = buildRouterOpts({ routeDataCache }, hasServerMiddleware(routeTree));
|
|
2025
2064
|
const code = preamble +
|
|
2026
2065
|
'const __components = {};\n' +
|
|
2027
2066
|
'const __hydrators = {};\n' +
|
|
@@ -2032,10 +2071,12 @@ async function buildMainBundle(routeTree, runtimeDir, codeSplit, mono, hmr, impo
|
|
|
2032
2071
|
hydratorAliasCode +
|
|
2033
2072
|
cleanupFn +
|
|
2034
2073
|
placeFn +
|
|
2074
|
+
reconcileRegionFn +
|
|
2035
2075
|
'globalThis.__components = __components;\n' +
|
|
2036
2076
|
'globalThis.__runtime_comps = __runtime_comps;\n' +
|
|
2037
2077
|
'globalThis.__cleanup = __cleanup;\n' +
|
|
2038
2078
|
'globalThis.__place = __place;\n' +
|
|
2079
|
+
'globalThis.__reconcileRegion = __reconcileRegion;\n' +
|
|
2039
2080
|
allRuntimeImports.map(n => `globalThis.${n} = ${n};\n`).join('') +
|
|
2040
2081
|
'function __resolveNames(nodes) {\n' +
|
|
2041
2082
|
' for (const n of nodes) {\n' +
|
package/dist/dev-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;AASjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAO7C,OAAO,KAAK,EAAa,gBAAgB,EAAwB,MAAM,yBAAyB,CAAC;AAgBjG;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB;+EAC2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAwDD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mHAAmH;IACnH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B;;8BAE0B;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC;IAChC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAChH,CAUA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;AASjG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC;AAO7C,OAAO,KAAK,EAAa,gBAAgB,EAAwB,MAAM,yBAAyB,CAAC;AAgBjG;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACxD,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB;+EAC2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAwDD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mHAAmH;IACnH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B;;8BAE0B;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC;IAChC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAChH,CAUA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgBrD;AAUD,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA4sBvG"}
|
package/dist/dev-server.js
CHANGED
|
@@ -150,7 +150,14 @@ export function devBootstrapScript() {
|
|
|
150
150
|
export function injectDevScripts(html) {
|
|
151
151
|
if (!html.includes('</body>'))
|
|
152
152
|
return html;
|
|
153
|
-
|
|
153
|
+
// SSR already emits its own client script (hmr.ts bakes
|
|
154
|
+
// `clientScriptUrl: "/_vesk/static/client.js"`). Injecting a second copy at
|
|
155
|
+
// `/_vesk/client.js` loads the runtime module twice, giving the page two
|
|
156
|
+
// routers and two sets of event listeners — every SPA click then runs
|
|
157
|
+
// navigate() twice and pushes a duplicate history entry. Only add the
|
|
158
|
+
// fallback client script for HTML that has none.
|
|
159
|
+
const hasClientScript = html.includes('/_vesk/static/client.js') || html.includes('/_vesk/client.js');
|
|
160
|
+
const scripts = (hasClientScript ? '' : '\t<script type="module" src="/_vesk/client.js"></script>\n') +
|
|
154
161
|
'\t<script type="module" src="/_vesk/hmr.js"></script>\n' +
|
|
155
162
|
devBootstrapScript() +
|
|
156
163
|
'\n';
|
package/dist/middleware.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,yBAAyB,CAAC;AAS5F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAA2B,MAAM,yBAAyB,CAAC;AAS5F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAuFhG;AAED,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAqF5E"}
|
package/dist/middleware.js
CHANGED
|
@@ -4,18 +4,22 @@ function extractMiddlewareBody(src) {
|
|
|
4
4
|
const parts = extractMiddlewareParts(src);
|
|
5
5
|
if (!parts)
|
|
6
6
|
return null;
|
|
7
|
-
return { params: parts.params, body: parts.body };
|
|
7
|
+
return { params: parts.params, body: parts.body, imports: parts.imports };
|
|
8
8
|
}
|
|
9
9
|
export function compileMiddleware(mwChain, _appDir) {
|
|
10
10
|
if (mwChain.length === 0)
|
|
11
11
|
return null;
|
|
12
12
|
const parts = [];
|
|
13
|
+
const imports = [];
|
|
13
14
|
for (let i = 0; i < mwChain.length; i++) {
|
|
14
15
|
const { sourcePath } = mwChain[i];
|
|
15
16
|
const src = readFileSync(sourcePath, 'utf-8');
|
|
16
17
|
const extracted = extractMiddlewareBody(src);
|
|
17
18
|
if (!extracted)
|
|
18
19
|
continue;
|
|
20
|
+
for (const line of extracted.imports)
|
|
21
|
+
if (!imports.includes(line))
|
|
22
|
+
imports.push(line);
|
|
19
23
|
parts.push(`async function mw_${i}(${extracted.params}) {\n${extracted.body}\n}`);
|
|
20
24
|
}
|
|
21
25
|
if (parts.length === 0)
|
|
@@ -23,6 +27,8 @@ export function compileMiddleware(mwChain, _appDir) {
|
|
|
23
27
|
const code = [
|
|
24
28
|
'// Auto-generated middleware chain — do not edit',
|
|
25
29
|
'',
|
|
30
|
+
...imports,
|
|
31
|
+
...(imports.length ? [''] : []),
|
|
26
32
|
parts.join('\n\n'),
|
|
27
33
|
'',
|
|
28
34
|
`const chain = [${parts.map((_, i) => `mw_${i}`).join(', ')}];`,
|
|
@@ -93,10 +99,14 @@ export function compileMiddlewareCode(mwSourceTexts) {
|
|
|
93
99
|
if (!mwSourceTexts || mwSourceTexts.length === 0)
|
|
94
100
|
return null;
|
|
95
101
|
const parts = [];
|
|
102
|
+
const imports = [];
|
|
96
103
|
for (let i = 0; i < mwSourceTexts.length; i++) {
|
|
97
104
|
const extracted = extractMiddlewareBody(mwSourceTexts[i]);
|
|
98
105
|
if (!extracted)
|
|
99
106
|
continue;
|
|
107
|
+
for (const line of extracted.imports)
|
|
108
|
+
if (!imports.includes(line))
|
|
109
|
+
imports.push(line);
|
|
100
110
|
parts.push(`async function mw_${i}(${extracted.params}) {\n${extracted.body}\n}`);
|
|
101
111
|
}
|
|
102
112
|
if (parts.length === 0)
|
|
@@ -104,6 +114,8 @@ export function compileMiddlewareCode(mwSourceTexts) {
|
|
|
104
114
|
const code = [
|
|
105
115
|
'// ── Middleware chain (inline) ──',
|
|
106
116
|
'',
|
|
117
|
+
...imports,
|
|
118
|
+
...(imports.length ? [''] : []),
|
|
107
119
|
parts.join('\n\n'),
|
|
108
120
|
'',
|
|
109
121
|
`const __mwChain = [${parts.map((_, i) => `mw_${i}`).join(', ')}];`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prod-server.d.ts","sourceRoot":"","sources":["../src/prod-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAuB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAejG,OAAO,KAAK,EAAkB,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAIpG,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;AAuIrD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,GAAG,CAY9F;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"prod-server.d.ts","sourceRoot":"","sources":["../src/prod-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,eAAe,EAAuB,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAejG,OAAO,KAAK,EAAkB,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAIpG,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,CAAC;AAuIrD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,GAAG,CAY9F;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6rBlG"}
|
package/dist/prod-server.js
CHANGED
|
@@ -480,6 +480,37 @@ export async function startProdServer(outDir, options) {
|
|
|
480
480
|
}
|
|
481
481
|
}
|
|
482
482
|
}
|
|
483
|
+
if (url.pathname === '/_vesk/middleware' && middlewareMod) {
|
|
484
|
+
const targetPath = url.searchParams.get('path') || '/';
|
|
485
|
+
const targetUrl = new URL(targetPath, url.origin);
|
|
486
|
+
const middlewareRequest = new Request(targetUrl.href, {
|
|
487
|
+
method: 'GET',
|
|
488
|
+
headers: req.headers,
|
|
489
|
+
});
|
|
490
|
+
const mwEndpointCtx = {
|
|
491
|
+
request: middlewareRequest,
|
|
492
|
+
params: {},
|
|
493
|
+
url: targetUrl,
|
|
494
|
+
locals: Object.assign({}, globalThis.__vesk_server_ctx || {}),
|
|
495
|
+
cookies: {},
|
|
496
|
+
set(key, value) { this.locals[key] = value; },
|
|
497
|
+
get(key) { return this.locals[key]; },
|
|
498
|
+
};
|
|
499
|
+
const mwResult = await middlewareMod.execute(mwEndpointCtx);
|
|
500
|
+
res.writeHead(200, {
|
|
501
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
502
|
+
'Cache-Control': 'no-store',
|
|
503
|
+
});
|
|
504
|
+
if (mwResult.response) {
|
|
505
|
+
const location = mwResult.response.headers.get('location') || mwResult.response.headers.get('Location');
|
|
506
|
+
if (location) {
|
|
507
|
+
res.end(JSON.stringify({ redirect: location }));
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
res.end(JSON.stringify(mwResult.rewriteUrl ? { rewrite: mwResult.rewriteUrl } : { allow: true }));
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
483
514
|
let mwCtx;
|
|
484
515
|
const serverStore = globalThis.__vesk_server_ctx;
|
|
485
516
|
if (middlewareMod) {
|
|
@@ -526,221 +557,232 @@ export async function startProdServer(outDir, options) {
|
|
|
526
557
|
}
|
|
527
558
|
// Expose root middleware locals to API/SSR handlers (which seed their own
|
|
528
559
|
// ctx.locals from this before running route-level middleware).
|
|
560
|
+
//
|
|
561
|
+
// Scoped to this request: an SSR render can `fetch()` its own API route,
|
|
562
|
+
// which re-enters this handler. Without restoring, that nested request's
|
|
563
|
+
// context (params: {}) stays installed and every later pass of the outer
|
|
564
|
+
// render reads the wrong params.
|
|
565
|
+
const __outerRequest = globalThis.__vesk_request;
|
|
529
566
|
globalThis.__vesk_request = mwCtx;
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
567
|
+
try {
|
|
568
|
+
if (url.pathname.startsWith('/_vesk/action/')) {
|
|
569
|
+
const actionId = url.pathname.replace('/_vesk/action/', '');
|
|
570
|
+
const actionEntry = buildConfig.actions && buildConfig.actions.find(a => a.id === actionId);
|
|
571
|
+
if (!actionEntry) {
|
|
572
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
573
|
+
res.end(JSON.stringify({ ok: false, error: 'Action not found' }));
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
const mod = await loadFunction(actionEntry.function);
|
|
577
|
+
if (!mod || !mod.handleAction) {
|
|
578
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
579
|
+
res.end(JSON.stringify({ ok: false, error: 'Action not found' }));
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
try {
|
|
583
|
+
const webRequest = makeWebRequest(req, url.href, maxBodyBytes);
|
|
584
|
+
const handleAction = mod.handleAction.bind(mod);
|
|
585
|
+
const response = await withSecurityScope(() => handleAction(webRequest, actionId));
|
|
586
|
+
await deliverResponse(res, response);
|
|
587
|
+
}
|
|
588
|
+
catch (e) {
|
|
589
|
+
const status = errorStatus(e, 500);
|
|
590
|
+
const message = status === 500 && process.env.NODE_ENV === 'production'
|
|
591
|
+
? 'Internal Server Error'
|
|
592
|
+
: e instanceof Error ? e.message : String(e);
|
|
593
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
594
|
+
res.end(JSON.stringify({ ok: false, error: message }));
|
|
595
|
+
}
|
|
542
596
|
return;
|
|
543
597
|
}
|
|
544
|
-
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
571
|
-
res.end(JSON.stringify({ error: 'Internal Server Error' }));
|
|
598
|
+
if (url.pathname.startsWith('/api')) {
|
|
599
|
+
for (const route of buildConfig.routes) {
|
|
600
|
+
if (route.type === 'api') {
|
|
601
|
+
const params = matchPath(route.path, url.pathname);
|
|
602
|
+
if (params) {
|
|
603
|
+
const mod = await loadFunction(route.function);
|
|
604
|
+
if (!mod) {
|
|
605
|
+
// The route matched, so a 404 would be a lie: the handler is
|
|
606
|
+
// there and could not be loaded.
|
|
607
|
+
if (functionFailure(route.function)) {
|
|
608
|
+
res.writeHead(500, { 'Content-Type': 'application/json' });
|
|
609
|
+
res.end(JSON.stringify({ error: 'Internal Server Error' }));
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
try {
|
|
615
|
+
const webRequest = makeWebRequest(req, url.href, maxBodyBytes);
|
|
616
|
+
const response = await withSecurityScope(() => mod.handle(webRequest));
|
|
617
|
+
await deliverResponse(res, response);
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
catch (e) {
|
|
621
|
+
const status = errorStatus(e, 500);
|
|
622
|
+
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
623
|
+
res.end(JSON.stringify({ error: status === 500 ? 'Internal Server Error' : e instanceof Error ? e.message : String(e) }));
|
|
572
624
|
return;
|
|
573
625
|
}
|
|
574
|
-
continue;
|
|
575
|
-
}
|
|
576
|
-
try {
|
|
577
|
-
const webRequest = makeWebRequest(req, url.href, maxBodyBytes);
|
|
578
|
-
const response = await withSecurityScope(() => mod.handle(webRequest));
|
|
579
|
-
await deliverResponse(res, response);
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
582
|
-
catch (e) {
|
|
583
|
-
const status = errorStatus(e, 500);
|
|
584
|
-
res.writeHead(status, { 'Content-Type': 'application/json' });
|
|
585
|
-
res.end(JSON.stringify({ error: status === 500 ? 'Internal Server Error' : e instanceof Error ? e.message : String(e) }));
|
|
586
|
-
return;
|
|
587
626
|
}
|
|
588
627
|
}
|
|
589
628
|
}
|
|
590
629
|
}
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
if (!boundaryPath)
|
|
611
|
-
return null;
|
|
612
|
-
const key = `${file}:${boundaryPath}`;
|
|
613
|
-
let html = boundaryCache.has(key) ? boundaryCache.get(key) : null;
|
|
614
|
-
if (html === null) {
|
|
615
|
-
try {
|
|
616
|
-
const runtimePath = resolve(outDir, 'server', 'runtime.js');
|
|
617
|
-
const { renderFullPage, storeDataScriptGlobal } = await import(runtimePath);
|
|
618
|
-
const src = readFileSync(boundaryPath, 'utf-8');
|
|
619
|
-
const compName = resolveComponentName(src) || (file === 'error.vsk' ? 'Error' : 'NotFound');
|
|
620
|
-
html = await renderFullPage(src, compName, props, new Map(), { hydrate: true, cssUrls: pageCssUrls, clientScriptUrl: buildConfig?.assets?.client?.url || '/_vesk/static/client.js', clientScriptIntegrity: buildConfig?.assets?.client?.integrity, security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: boundaryPath, headExtra: bakedHeadExtra });
|
|
621
|
-
}
|
|
622
|
-
catch {
|
|
630
|
+
const appDir = resolve(projectDir, 'app');
|
|
631
|
+
const pageCssUrls = resolveCssUrls({
|
|
632
|
+
enabled: hasBuiltGlobalCss(outDir),
|
|
633
|
+
});
|
|
634
|
+
/**
|
|
635
|
+
* Render the boundary that owns `url.pathname`.
|
|
636
|
+
*
|
|
637
|
+
* Deepest-match over the URL's directories, not a hard read of the root
|
|
638
|
+
* file: `app/admin/not-found.vsk` is the boundary for `/admin/*`, and the
|
|
639
|
+
* root one is the fallback. The generated SSR function does the same walk at
|
|
640
|
+
* build time (`resolveNotFoundFile`) and renders the boundary itself inside
|
|
641
|
+
* the layout stack; this path is what remains for an unmatched URL, for a
|
|
642
|
+
* route with no layout (which streams, so its status is already committed),
|
|
643
|
+
* and for an error thrown outside a page's own try block.
|
|
644
|
+
*/
|
|
645
|
+
const boundaryCache = new Map();
|
|
646
|
+
async function renderBoundaryFile(file, pathname, props) {
|
|
647
|
+
const boundaryPath = resolveBoundaryFileForUrl(pathname, appDir, file);
|
|
648
|
+
if (!boundaryPath)
|
|
623
649
|
return null;
|
|
650
|
+
const key = `${file}:${boundaryPath}`;
|
|
651
|
+
let html = boundaryCache.has(key) ? boundaryCache.get(key) : null;
|
|
652
|
+
if (html === null) {
|
|
653
|
+
try {
|
|
654
|
+
const runtimePath = resolve(outDir, 'server', 'runtime.js');
|
|
655
|
+
const { renderFullPage, storeDataScriptGlobal } = await import(runtimePath);
|
|
656
|
+
const src = readFileSync(boundaryPath, 'utf-8');
|
|
657
|
+
const compName = resolveComponentName(src) || (file === 'error.vsk' ? 'Error' : 'NotFound');
|
|
658
|
+
html = await renderFullPage(src, compName, props, new Map(), { hydrate: true, cssUrls: pageCssUrls, clientScriptUrl: buildConfig?.assets?.client?.url || '/_vesk/static/client.js', clientScriptIntegrity: buildConfig?.assets?.client?.integrity, security: securityConfig?.security || {}, externalDataScript: storeDataScriptGlobal, sourcePath: boundaryPath, headExtra: bakedHeadExtra });
|
|
659
|
+
}
|
|
660
|
+
catch {
|
|
661
|
+
return null;
|
|
662
|
+
}
|
|
624
663
|
}
|
|
664
|
+
return html;
|
|
625
665
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
input
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
res.
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
res.end(body);
|
|
690
|
-
}
|
|
691
|
-
return;
|
|
692
|
-
}
|
|
693
|
-
catch (e) {
|
|
694
|
-
const err = e instanceof Error ? e : new Error(String(e));
|
|
695
|
-
if (err.name === 'Redirect') {
|
|
696
|
-
const redirect = err;
|
|
697
|
-
res.writeHead(Number(redirect.status) || 302, { Location: typeof redirect.url === 'string' ? redirect.url : '/' });
|
|
698
|
-
res.end();
|
|
666
|
+
let notFoundHtml = null;
|
|
667
|
+
{
|
|
668
|
+
const rendered = await renderBoundaryFile('not-found.vsk', url.pathname, { params: {}, url: url.pathname });
|
|
669
|
+
notFoundHtml = rendered;
|
|
670
|
+
}
|
|
671
|
+
for (const route of buildConfig.routes) {
|
|
672
|
+
if (route.type === 'ssr') {
|
|
673
|
+
const params = matchPath(route.path, url.pathname);
|
|
674
|
+
if (params) {
|
|
675
|
+
const mod = await loadFunction(route.function);
|
|
676
|
+
if (mod) {
|
|
677
|
+
const webRequest = makeWebRequest(req, url.href, maxBodyBytes);
|
|
678
|
+
// During SSR, fetch() with a relative URL (e.g. '/api/student') throws
|
|
679
|
+
// because undici requires an absolute URL and there is no browser
|
|
680
|
+
// origin to resolve against. Wrap globalThis.fetch for the duration
|
|
681
|
+
// of the SSR render so relative API calls resolve against the
|
|
682
|
+
// request's origin — matching what the client does automatically.
|
|
683
|
+
const origin = new URL(url.href).origin;
|
|
684
|
+
const origFetch = globalThis.fetch;
|
|
685
|
+
globalThis.fetch = async (input, init) => {
|
|
686
|
+
if (typeof input === 'string' && input.startsWith('/')) {
|
|
687
|
+
input = origin + input;
|
|
688
|
+
}
|
|
689
|
+
return origFetch(input, init);
|
|
690
|
+
};
|
|
691
|
+
try {
|
|
692
|
+
let cachedResult = null;
|
|
693
|
+
if (route.revalidate && route.revalidate > 0) {
|
|
694
|
+
const { pageIsr } = await import('@vesk/runtime/src/index-server');
|
|
695
|
+
cachedResult = await pageIsr(url.pathname, async () => {
|
|
696
|
+
const response = await withSecurityScope(() => mod.handle(webRequest));
|
|
697
|
+
return { html: await response.text(), headers: Object.fromEntries(response.headers) };
|
|
698
|
+
}, { revalidate: route.revalidate, tags: route.tags || [] });
|
|
699
|
+
}
|
|
700
|
+
if (cachedResult) {
|
|
701
|
+
res.writeHead(200, cachedResult.headers || { 'Content-Type': 'text/html' });
|
|
702
|
+
res.end(cachedResult.html);
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
const response = await withSecurityScope(() => mod.handle(webRequest));
|
|
706
|
+
const headers = Object.fromEntries(response.headers);
|
|
707
|
+
if (!headers['content-type'] && !headers['Content-Type'])
|
|
708
|
+
headers['Content-Type'] = 'text/html';
|
|
709
|
+
if (response.body && typeof response.body.getReader === 'function') {
|
|
710
|
+
res.writeHead(response.status, headers);
|
|
711
|
+
const reader = response.body.getReader();
|
|
712
|
+
const pump = () => {
|
|
713
|
+
reader.read().then(({ done, value }) => {
|
|
714
|
+
if (done) {
|
|
715
|
+
res.end();
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
res.write(value);
|
|
719
|
+
pump();
|
|
720
|
+
}).catch(() => res.end());
|
|
721
|
+
};
|
|
722
|
+
pump();
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
const body = await response.text();
|
|
726
|
+
res.writeHead(response.status, headers);
|
|
727
|
+
res.end(body);
|
|
728
|
+
}
|
|
699
729
|
return;
|
|
700
730
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
731
|
+
catch (e) {
|
|
732
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
733
|
+
if (err.name === 'Redirect') {
|
|
734
|
+
const redirect = err;
|
|
735
|
+
res.writeHead(Number(redirect.status) || 302, { Location: typeof redirect.url === 'string' ? redirect.url : '/' });
|
|
736
|
+
res.end();
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
if (err.name === 'NotFoundError') {
|
|
740
|
+
res.writeHead(404, { 'Content-Type': 'text/html' });
|
|
741
|
+
res.end(notFoundHtml || renderDefaultNotFoundPage({ url: url.pathname, headExtra: bakedHeadExtra }));
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
console.error('vesk ssr error:', err.message);
|
|
745
|
+
// Two seams, both best-effort: a plugin's `onError` (dev-style
|
|
746
|
+
// plugin objects don't exist here) and `_events.ts`'s, which IS
|
|
747
|
+
// baked into the production build.
|
|
748
|
+
await reportServerError(err, {
|
|
749
|
+
url: url.pathname + url.search,
|
|
750
|
+
routePath: route.path,
|
|
751
|
+
target: 'node',
|
|
752
|
+
status: 500,
|
|
753
|
+
buildConfig,
|
|
754
|
+
});
|
|
755
|
+
if (eventsMod) {
|
|
756
|
+
await executeError(err, { url: url.href, routePath: route.path, target: 'node', status: 500 }, eventsMod);
|
|
757
|
+
}
|
|
758
|
+
// Same nearest-boundary walk as not-found above. This is the last resort for a
|
|
759
|
+
// throw the generated function could not absorb — a layout render
|
|
760
|
+
// failure, or the error boundary itself failing — and it must pick
|
|
761
|
+
// the boundary that owns the URL, not the root one.
|
|
762
|
+
const expose = process.env.NODE_ENV !== 'production';
|
|
763
|
+
const errorHtml = await renderBoundaryFile('error.vsk', url.pathname, {
|
|
764
|
+
error: expose ? err.message : 'Internal Server Error',
|
|
765
|
+
stack: expose ? err.stack : '',
|
|
766
|
+
statusCode: 500,
|
|
767
|
+
url: url.pathname,
|
|
768
|
+
});
|
|
769
|
+
res.writeHead(500, { 'Content-Type': 'text/html' });
|
|
770
|
+
res.end(errorHtml || renderDefaultErrorPage({ message: process.env.NODE_ENV !== 'production' ? err.message : undefined, url: url.pathname, headExtra: bakedHeadExtra }));
|
|
704
771
|
return;
|
|
705
772
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
// plugin objects don't exist here) and `_events.ts`'s, which IS
|
|
709
|
-
// baked into the production build.
|
|
710
|
-
await reportServerError(err, {
|
|
711
|
-
url: url.pathname + url.search,
|
|
712
|
-
routePath: route.path,
|
|
713
|
-
target: 'node',
|
|
714
|
-
status: 500,
|
|
715
|
-
buildConfig,
|
|
716
|
-
});
|
|
717
|
-
if (eventsMod) {
|
|
718
|
-
await executeError(err, { url: url.href, routePath: route.path, target: 'node', status: 500 }, eventsMod);
|
|
773
|
+
finally {
|
|
774
|
+
globalThis.fetch = origFetch;
|
|
719
775
|
}
|
|
720
|
-
// Same nearest-boundary walk as not-found above. This is the last resort for a
|
|
721
|
-
// throw the generated function could not absorb — a layout render
|
|
722
|
-
// failure, or the error boundary itself failing — and it must pick
|
|
723
|
-
// the boundary that owns the URL, not the root one.
|
|
724
|
-
const expose = process.env.NODE_ENV !== 'production';
|
|
725
|
-
const errorHtml = await renderBoundaryFile('error.vsk', url.pathname, {
|
|
726
|
-
error: expose ? err.message : 'Internal Server Error',
|
|
727
|
-
stack: expose ? err.stack : '',
|
|
728
|
-
statusCode: 500,
|
|
729
|
-
url: url.pathname,
|
|
730
|
-
});
|
|
731
|
-
res.writeHead(500, { 'Content-Type': 'text/html' });
|
|
732
|
-
res.end(errorHtml || renderDefaultErrorPage({ message: process.env.NODE_ENV !== 'production' ? err.message : undefined, url: url.pathname, headExtra: bakedHeadExtra }));
|
|
733
|
-
return;
|
|
734
|
-
}
|
|
735
|
-
finally {
|
|
736
|
-
globalThis.fetch = origFetch;
|
|
737
776
|
}
|
|
738
777
|
}
|
|
739
778
|
}
|
|
740
779
|
}
|
|
780
|
+
res.writeHead(404, { 'Content-Type': 'text/html' });
|
|
781
|
+
res.end(notFoundHtml || renderDefaultNotFoundPage({ url: url.pathname, headExtra: bakedHeadExtra }));
|
|
782
|
+
}
|
|
783
|
+
finally {
|
|
784
|
+
globalThis.__vesk_request = __outerRequest;
|
|
741
785
|
}
|
|
742
|
-
res.writeHead(404, { 'Content-Type': 'text/html' });
|
|
743
|
-
res.end(notFoundHtml || renderDefaultNotFoundPage({ url: url.pathname, headExtra: bakedHeadExtra }));
|
|
744
786
|
});
|
|
745
787
|
try {
|
|
746
788
|
await eventsMod?.executeStart?.({ server, port, host });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-function.d.ts","sourceRoot":"","sources":["../src/ssr-function.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAkB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7F;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlG;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjF;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpF;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQvG;AAgED;;;2EAG2E;AAC3E,wBAAgB,qBAAqB,IAAI,MAAM,CA4C9C;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,kBAAkB,EAC5B,QAAQ,CAAC,EAAE,cAAc,GACxB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"ssr-function.d.ts","sourceRoot":"","sources":["../src/ssr-function.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAkB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7F;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlG;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjF;AAED,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpF;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQvG;AAgED;;;2EAG2E;AAC3E,wBAAgB,qBAAqB,IAAI,MAAM,CA4C9C;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,OAAO,CAAC,EAAE,kBAAkB,EAC5B,QAAQ,CAAC,EAAE,cAAc,GACxB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAsgBtD"}
|
package/dist/ssr-function.js
CHANGED
|
@@ -428,7 +428,10 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
|
|
|
428
428
|
// its own request scope — otherwise its renderPage mints a token that is
|
|
429
429
|
// still live when the full-page render starts and the two share a data slot.
|
|
430
430
|
const dataNavWrap = (body) => [
|
|
431
|
-
|
|
431
|
+
// Awaited for the same reason as the main render below: the caller restores
|
|
432
|
+
// `__vesk_request` in a finally, and that must happen only after the async
|
|
433
|
+
// data render (which reads params through useParams) has fully resolved.
|
|
434
|
+
' return await withSsrStore(async () => {',
|
|
432
435
|
...body.map((l) => (l ? ' ' + l : l)),
|
|
433
436
|
' });',
|
|
434
437
|
];
|
|
@@ -456,7 +459,13 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
|
|
|
456
459
|
...dataNavCleanup,
|
|
457
460
|
]),
|
|
458
461
|
' }',
|
|
459
|
-
|
|
462
|
+
// Awaited so the surrounding try/finally keeps `__vesk_request` installed
|
|
463
|
+
// for the whole async render. Without the await the finally restores the
|
|
464
|
+
// previous context synchronously, while the async page body is still
|
|
465
|
+
// suspended on its SSR fetches; every render pass after the first `await`
|
|
466
|
+
// then reads an empty params object and `useParams()`-derived keys/URLs
|
|
467
|
+
// collapse (e.g. a verify page rendering its not-found branch).
|
|
468
|
+
' return await __renderHtml(params, url.href);',
|
|
460
469
|
].join('\n');
|
|
461
470
|
}
|
|
462
471
|
else {
|
|
@@ -478,7 +487,13 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
|
|
|
478
487
|
...dataNavCleanup,
|
|
479
488
|
]),
|
|
480
489
|
' }',
|
|
481
|
-
|
|
490
|
+
// Awaited so the surrounding try/finally keeps `__vesk_request` installed
|
|
491
|
+
// for the whole async render. Without the await the finally restores the
|
|
492
|
+
// previous context synchronously, while the async page body is still
|
|
493
|
+
// suspended on its SSR fetches; every render pass after the first `await`
|
|
494
|
+
// then reads an empty params object and `useParams()`-derived keys/URLs
|
|
495
|
+
// collapse (e.g. a verify page rendering its not-found branch).
|
|
496
|
+
' return await __renderHtml(params, url.href);',
|
|
482
497
|
].join('\n');
|
|
483
498
|
}
|
|
484
499
|
const hasMiddleware = !!middlewareCode;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vesk/adapter",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.95",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vesk adapter — builds deployable .vesk/ output for Deno and Node serverless",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,9 +23,9 @@
|
|
|
23
23
|
"sharp": "^0.35.3"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@vesk/compiler": "^0.2.
|
|
27
|
-
"@vesk/runtime": "^0.2.
|
|
28
|
-
"@vesk/types": "^0.2.
|
|
26
|
+
"@vesk/compiler": "^0.2.95",
|
|
27
|
+
"@vesk/runtime": "^0.2.95",
|
|
28
|
+
"@vesk/types": "^0.2.95"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/ws": "^8.18.1",
|