@vesk/adapter 0.2.69 → 0.2.70
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/manifest.d.ts.map +1 -1
- package/dist/manifest.js +7 -0
- package/dist/prod-server.d.ts.map +1 -1
- package/dist/prod-server.js +47 -24
- package/dist/ssr-function.d.ts +20 -0
- package/dist/ssr-function.d.ts.map +1 -1
- package/dist/ssr-function.js +99 -20
- package/package.json +4 -4
package/dist/manifest.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAqE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAiCpK,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EAAE,EACnB,SAAS,EAAE,SAAS,EAAE,EACtB,SAAS,EAAE,YAAY,EAAE,EACzB,YAAY,EAAE,cAAc,EAAE,EAC9B,iBAAiB,EAAE,OAAO,EAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,UAAQ,GACpB,QAAQ,
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAqE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAiCpK,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,SAAS,EAAE,EACnB,SAAS,EAAE,SAAS,EAAE,EACtB,SAAS,EAAE,YAAY,EAAE,EACzB,YAAY,EAAE,cAAc,EAAE,EAC9B,iBAAiB,EAAE,OAAO,EAC1B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,SAAS,CAAC,EAAE,MAAM,EAClB,aAAa,UAAQ,GACpB,QAAQ,CA8EV"}
|
package/dist/manifest.js
CHANGED
|
@@ -44,6 +44,13 @@ export function generateManifest(routes, ssrRoutes, apiRoutes, staticRoutes, mid
|
|
|
44
44
|
entry.tags = r._isrTags;
|
|
45
45
|
routeEntries.push(entry);
|
|
46
46
|
}
|
|
47
|
+
// Same precedence rule as the API entries below, and for the same reason:
|
|
48
|
+
// every consumer takes the FIRST exact-length match, so directory-scan order
|
|
49
|
+
// decides. `app/docs/[slug]/page.vsk` scanned before `app/docs/boom/page.vsk`
|
|
50
|
+
// left `/docs/boom` permanently served by the dynamic route — a static page
|
|
51
|
+
// that 404s or, worse, renders the wrong page's content. The API half of this
|
|
52
|
+
// fix landed earlier; SSR entries had the identical defect.
|
|
53
|
+
routeEntries.sort((a, b) => compareSpecificity(a.path, b.path));
|
|
47
54
|
const apiEntries = [];
|
|
48
55
|
for (const r of apiRoutes) {
|
|
49
56
|
const urlParts = r.fullPath.split('/').filter(Boolean);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prod-server.d.ts","sourceRoot":"","sources":["../src/prod-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"prod-server.d.ts","sourceRoot":"","sources":["../src/prod-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAcjG,OAAO,KAAK,EAAkB,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAuFpG,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAIzE;AA0FD,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG;IAAE,WAAW,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA6mBvK"}
|
package/dist/prod-server.js
CHANGED
|
@@ -12,6 +12,7 @@ import { resolveCssUrls, hasBuiltGlobalCss } from '@vesk/adapter/src/css';
|
|
|
12
12
|
import { loadVeskConfig } from '@vesk/adapter/src/load-config';
|
|
13
13
|
import { renderDefaultNotFoundPage, renderDefaultErrorPage } from '@vesk/adapter/src/default-pages';
|
|
14
14
|
import { installResponsePipeline } from '@vesk/adapter/src/response-pipeline';
|
|
15
|
+
import { resolveBoundaryFileForUrl } from '@vesk/adapter/src/ssr-function';
|
|
15
16
|
import { mimeFor } from '@vesk/adapter/src/platform-output';
|
|
16
17
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
17
18
|
async function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
@@ -600,17 +601,42 @@ export async function startProdServer(outDir, options) {
|
|
|
600
601
|
const pageCssUrls = resolveCssUrls({
|
|
601
602
|
enabled: hasBuiltGlobalCss(outDir),
|
|
602
603
|
});
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
604
|
+
/**
|
|
605
|
+
* Render the boundary that owns `url.pathname`.
|
|
606
|
+
*
|
|
607
|
+
* Deepest-match over the URL's directories, not a hard read of the root
|
|
608
|
+
* file: `app/admin/not-found.vsk` is the boundary for `/admin/*`, and the
|
|
609
|
+
* root one is the fallback. The generated SSR function does the same walk at
|
|
610
|
+
* build time (`resolveNotFoundFile`) and renders the boundary itself inside
|
|
611
|
+
* the layout stack; this path is what remains for an unmatched URL, for a
|
|
612
|
+
* route with no layout (which streams, so its status is already committed),
|
|
613
|
+
* and for an error thrown outside a page's own try block.
|
|
614
|
+
*/
|
|
615
|
+
const boundaryCache = new Map();
|
|
616
|
+
async function renderBoundaryFile(file, pathname, props) {
|
|
617
|
+
const boundaryPath = resolveBoundaryFileForUrl(pathname, appDir, file);
|
|
618
|
+
if (!boundaryPath)
|
|
619
|
+
return null;
|
|
620
|
+
const key = `${file}:${boundaryPath}`;
|
|
621
|
+
let html = boundaryCache.has(key) ? boundaryCache.get(key) : null;
|
|
622
|
+
if (html === null) {
|
|
623
|
+
try {
|
|
624
|
+
const runtimePath = resolve(outDir, 'server', 'runtime.js');
|
|
625
|
+
const { renderFullPage, storeDataScriptGlobal } = await import(runtimePath);
|
|
626
|
+
const src = readFileSync(boundaryPath, 'utf-8');
|
|
627
|
+
const compName = resolveComponentName(src) || (file === 'error.vsk' ? 'Error' : 'NotFound');
|
|
628
|
+
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 });
|
|
629
|
+
}
|
|
630
|
+
catch {
|
|
631
|
+
return null;
|
|
632
|
+
}
|
|
612
633
|
}
|
|
613
|
-
|
|
634
|
+
return html;
|
|
635
|
+
}
|
|
636
|
+
let notFoundHtml = null;
|
|
637
|
+
{
|
|
638
|
+
const rendered = await renderBoundaryFile('not-found.vsk', url.pathname, { params: {}, url: url.pathname });
|
|
639
|
+
notFoundHtml = rendered;
|
|
614
640
|
}
|
|
615
641
|
for (const route of buildConfig.routes) {
|
|
616
642
|
if (route.type === 'ssr') {
|
|
@@ -686,20 +712,17 @@ export async function startProdServer(outDir, options) {
|
|
|
686
712
|
if (eventsMod) {
|
|
687
713
|
await executeError(err, { url: url.href, routePath: route.path, target: 'node', status: 500 }, eventsMod);
|
|
688
714
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
}
|
|
701
|
-
catch { }
|
|
702
|
-
}
|
|
715
|
+
// Same nearest-boundary walk as not-found above. This is the last resort for a
|
|
716
|
+
// throw the generated function could not absorb — a layout render
|
|
717
|
+
// failure, or the error boundary itself failing — and it must pick
|
|
718
|
+
// the boundary that owns the URL, not the root one.
|
|
719
|
+
const expose = process.env.NODE_ENV !== 'production';
|
|
720
|
+
const errorHtml = await renderBoundaryFile('error.vsk', url.pathname, {
|
|
721
|
+
error: expose ? err.message : 'Internal Server Error',
|
|
722
|
+
stack: expose ? err.stack : '',
|
|
723
|
+
statusCode: 500,
|
|
724
|
+
url: url.pathname,
|
|
725
|
+
});
|
|
703
726
|
res.writeHead(500, { 'Content-Type': 'text/html' });
|
|
704
727
|
res.end(errorHtml || renderDefaultErrorPage({ message: process.env.NODE_ENV !== 'production' ? err.message : undefined, url: url.pathname, headExtra: bakedHeadExtra }));
|
|
705
728
|
return;
|
package/dist/ssr-function.d.ts
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import type { RouteNode, SsrFunctionOptions } from '@vesk/adapter/src/types';
|
|
2
|
+
/**
|
|
3
|
+
* The nearest `<file>` walking up from a route's own directory to the app root.
|
|
4
|
+
*
|
|
5
|
+
* This is the server-side twin of the client router's `findErrorComponent` /
|
|
6
|
+
* `findNotFoundComponent`, which walk the matched chain deepest-first. Same rule,
|
|
7
|
+
* same reason: an `error.vsk` (or `not-found.vsk`) inside `app/admin/` is the
|
|
8
|
+
* boundary for `/admin/*` and nothing else — the root file is the fallback, not
|
|
9
|
+
* the implementation.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveBoundaryFile(sourceDir: string, appDir: string, file: string): string | null;
|
|
2
12
|
export declare function resolveErrorFile(sourceDir: string, appDir: string): string | null;
|
|
13
|
+
export declare function resolveNotFoundFile(sourceDir: string, appDir: string): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* The nearest `<file>` for a REQUESTED URL, used by the server when no SSR
|
|
16
|
+
* function ran (an unmatched path) or when one gave up.
|
|
17
|
+
*
|
|
18
|
+
* The walk is over URL segments, so a dynamic segment cannot be mapped back to a
|
|
19
|
+
* directory — `/users/42/edit` stops at `/users`. Static paths, which is what a
|
|
20
|
+
* `not-found.vsk` is written for, resolve exactly.
|
|
21
|
+
*/
|
|
22
|
+
export declare function resolveBoundaryFileForUrl(pathname: string, appDir: string, file: string): string | null;
|
|
3
23
|
/** Shared persisted-store SSR helper block emitted into every generated SSR
|
|
4
24
|
* function (prod via ssr-function.ts, dev via hmr.ts — keep the two callers
|
|
5
25
|
* in sync by calling this). Emit it AFTER the function declarations so the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-function.d.ts","sourceRoot":"","sources":["../src/ssr-function.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAkB,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"ssr-function.d.ts","sourceRoot":"","sources":["../src/ssr-function.ts"],"names":[],"mappings":"AAKA,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,GAC3B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CA6etD"}
|
package/dist/ssr-function.js
CHANGED
|
@@ -3,13 +3,44 @@ import { resolve, relative, join } from 'node:path';
|
|
|
3
3
|
import { resolveComponentName, precompileFile } from '@vesk/compiler/src/server-codegen';
|
|
4
4
|
import { resolveCssUrls, hasBuiltGlobalCss } from '@vesk/adapter/src/css';
|
|
5
5
|
import { renderDefaultErrorFragment } from '@vesk/adapter/src/default-pages';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
* The nearest `<file>` walking up from a route's own directory to the app root.
|
|
8
|
+
*
|
|
9
|
+
* This is the server-side twin of the client router's `findErrorComponent` /
|
|
10
|
+
* `findNotFoundComponent`, which walk the matched chain deepest-first. Same rule,
|
|
11
|
+
* same reason: an `error.vsk` (or `not-found.vsk`) inside `app/admin/` is the
|
|
12
|
+
* boundary for `/admin/*` and nothing else — the root file is the fallback, not
|
|
13
|
+
* the implementation.
|
|
14
|
+
*/
|
|
15
|
+
export function resolveBoundaryFile(sourceDir, appDir, file) {
|
|
9
16
|
const rel = relative(appDir, sourceDir).split('/').filter(Boolean);
|
|
10
17
|
for (let depth = rel.length; depth >= 0; depth--) {
|
|
11
18
|
const dir = depth === 0 ? appDir : join(appDir, ...rel.slice(0, depth));
|
|
12
|
-
const p = join(dir,
|
|
19
|
+
const p = join(dir, file);
|
|
20
|
+
if (existsSync(p))
|
|
21
|
+
return p;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
export function resolveErrorFile(sourceDir, appDir) {
|
|
26
|
+
return resolveBoundaryFile(sourceDir, appDir, 'error.vsk');
|
|
27
|
+
}
|
|
28
|
+
export function resolveNotFoundFile(sourceDir, appDir) {
|
|
29
|
+
return resolveBoundaryFile(sourceDir, appDir, 'not-found.vsk');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The nearest `<file>` for a REQUESTED URL, used by the server when no SSR
|
|
33
|
+
* function ran (an unmatched path) or when one gave up.
|
|
34
|
+
*
|
|
35
|
+
* The walk is over URL segments, so a dynamic segment cannot be mapped back to a
|
|
36
|
+
* directory — `/users/42/edit` stops at `/users`. Static paths, which is what a
|
|
37
|
+
* `not-found.vsk` is written for, resolve exactly.
|
|
38
|
+
*/
|
|
39
|
+
export function resolveBoundaryFileForUrl(pathname, appDir, file) {
|
|
40
|
+
const segments = pathname.split('/').filter(Boolean);
|
|
41
|
+
for (let depth = segments.length; depth >= 0; depth--) {
|
|
42
|
+
const dir = join(appDir, ...segments.slice(0, depth));
|
|
43
|
+
const p = join(dir, file);
|
|
13
44
|
if (existsSync(p))
|
|
14
45
|
return p;
|
|
15
46
|
}
|
|
@@ -168,18 +199,30 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
|
|
|
168
199
|
const errorVars = errorPath
|
|
169
200
|
? `const _errorComp = ${JSON.stringify(errorComp)};\nconst _errorCompiled = ${hydrateInvoke(precompilePlan(errorPath))};\n`
|
|
170
201
|
: 'const _errorComp = null;\nconst _errorCompiled = null;\n';
|
|
202
|
+
// Not-found used to have no server-side resolution at all: a NotFoundError was
|
|
203
|
+
// re-thrown out of the function and the prod server answered with the ROOT
|
|
204
|
+
// not-found.vsk. A nested `app/admin/not-found.vsk` therefore did nothing on a
|
|
205
|
+
// hard load, while the client router — which walks the matched chain
|
|
206
|
+
// deepest-first — honoured it on SPA navigation. Same URL, two different
|
|
207
|
+
// pages depending on how you arrived.
|
|
208
|
+
const notFoundPath = resolveNotFoundFile(routeNode.sourceDir, appDir);
|
|
209
|
+
const notFoundSrc = notFoundPath ? readFileSync(notFoundPath, 'utf-8') : null;
|
|
210
|
+
const notFoundComp = notFoundPath ? (extractCompName(notFoundSrc) || 'NotFound') : null;
|
|
211
|
+
const notFoundVars = notFoundPath
|
|
212
|
+
? `const _notFoundComp = ${JSON.stringify(notFoundComp)};\nconst _notFoundCompiled = ${hydrateInvoke(precompilePlan(notFoundPath))};\n`
|
|
213
|
+
: 'const _notFoundComp = null;\nconst _notFoundCompiled = null;\n';
|
|
171
214
|
let src = '';
|
|
172
215
|
if (layoutDecls.length > 0) {
|
|
173
216
|
src = `const _pageComp = ${JSON.stringify(pageComp)};\n`;
|
|
174
217
|
src += `const _pageCompiled = (() => { try { return hydratePrecompile(${pagePlan}); } catch { return null; } })();\n`;
|
|
175
218
|
src += `const _layoutCompList = [${layoutDecls.map((d) => d.comp).join(', ')}];\n`;
|
|
176
219
|
src += `const _layoutCompiledList = [\n${layoutDecls.map((d) => ' ' + d.compiled + ',').join('\n')}\n];\n`;
|
|
177
|
-
src += errorVars;
|
|
220
|
+
src += errorVars + notFoundVars;
|
|
178
221
|
}
|
|
179
222
|
else {
|
|
180
223
|
src = `const _comp = ${JSON.stringify(pageComp)};\n`;
|
|
181
224
|
src += `const _compiled = (() => { try { return hydratePrecompile(${pagePlan}); } catch { return null; } })();\n`;
|
|
182
|
-
src += errorVars;
|
|
225
|
+
src += errorVars + notFoundVars;
|
|
183
226
|
}
|
|
184
227
|
const urlParts = routeNode.fullPath.split('/').filter(Boolean);
|
|
185
228
|
const paramExprs = buildParamExtraction(routeNode, urlParts);
|
|
@@ -215,30 +258,66 @@ export function generateSsrFunction(routeNode, appDir, outDir, componentMap, opt
|
|
|
215
258
|
' }',
|
|
216
259
|
'}',
|
|
217
260
|
'',
|
|
261
|
+
// Returns null rather than throwing when there is no boundary, so the
|
|
262
|
+
// caller can re-throw the original NotFoundError and let the server answer
|
|
263
|
+
// — a page with no not-found.vsk anywhere must still get a 404.
|
|
264
|
+
'async function __renderNotFoundBody(props) {',
|
|
265
|
+
' if (!_notFoundComp) return null;',
|
|
266
|
+
' try {',
|
|
267
|
+
' const result = await renderPage(\'\', _notFoundComp, props, __componentRegistry, { hydrate: true, cached: _notFoundCompiled });',
|
|
268
|
+
' return result.body;',
|
|
269
|
+
' } catch {',
|
|
270
|
+
' return null;',
|
|
271
|
+
' }',
|
|
272
|
+
'}',
|
|
273
|
+
'',
|
|
274
|
+
// The layout wrap, shared by the page / error / not-found paths. Extracted
|
|
275
|
+
// because three call sites that each re-implemented it is three chances to
|
|
276
|
+
// forget the head merge.
|
|
277
|
+
'async function __wrapLayouts(params, body, head) {',
|
|
278
|
+
' let _b = body;',
|
|
279
|
+
' let _h = head || "";',
|
|
280
|
+
' for (let _i = _layoutCompList.length - 1; _i > 0; _i--) {',
|
|
281
|
+
" const _inner = await renderPage('', _layoutCompList[_i], { params, children: _b }, __componentRegistry, { hydrate: true, cached: _layoutCompiledList[_i] });",
|
|
282
|
+
' _b = _inner.body;',
|
|
283
|
+
' if (_inner.head) _h = _inner.head + _h;',
|
|
284
|
+
' }',
|
|
285
|
+
" return renderFullPage('', _layoutCompList[0], { params, children: _b }, __componentRegistry, { hydrate: true, cached: _layoutCompiledList[0]" + bakedOptions + clientScriptOption + dataScriptOption + ", pageHead: _h });",
|
|
286
|
+
'}',
|
|
287
|
+
'',
|
|
218
288
|
'async function __renderHtml(params, requestUrl) {',
|
|
219
289
|
' return withSsrStore(async () => {',
|
|
220
290
|
' resetPersistedStoreKeys();',
|
|
221
291
|
' let page;',
|
|
222
292
|
' let caughtError = null;',
|
|
293
|
+
' let notFound = false;',
|
|
223
294
|
" const __expose = process.env.NODE_ENV !== 'production';",
|
|
224
295
|
' try {',
|
|
225
296
|
' page = await renderPage(\'\', _pageComp, { params }, __componentRegistry, { hydrate: true, cached: _pageCompiled });',
|
|
226
297
|
' } catch (err) {',
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
'
|
|
233
|
-
'
|
|
234
|
-
'
|
|
235
|
-
'
|
|
236
|
-
|
|
237
|
-
'
|
|
238
|
-
'
|
|
298
|
+
" if (err && err.name === 'Redirect') throw err;",
|
|
299
|
+
" if (err && err.name === 'NotFoundError') {",
|
|
300
|
+
// The boundary is chosen per-route at build time (resolveNotFoundFile walks
|
|
301
|
+
// this route's own directory up to the app root), so a nested
|
|
302
|
+
// app/admin/not-found.vsk answers /admin/* and the root one answers the
|
|
303
|
+
// rest — matching the client router's deepest-first chain walk.
|
|
304
|
+
' const nfBody = await __renderNotFoundBody({ params, url: requestUrl || \'\' });',
|
|
305
|
+
' if (nfBody !== null) {',
|
|
306
|
+
' notFound = true;',
|
|
307
|
+
' page = { body: nfBody, head: \'\' };',
|
|
308
|
+
' } else {',
|
|
309
|
+
' throw err;',
|
|
310
|
+
' }',
|
|
311
|
+
' } else {',
|
|
312
|
+
' caughtError = err;',
|
|
313
|
+
" const message = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);",
|
|
314
|
+
" const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
|
|
315
|
+
" page = { body: await __renderErrorBody({ params, statusCode: 500, error: __expose ? message : 'Internal Server Error', stack: __expose ? stack : '', url: requestUrl || '' }), head: '' };",
|
|
316
|
+
' }',
|
|
239
317
|
' }',
|
|
240
|
-
"
|
|
241
|
-
|
|
318
|
+
" let _body = (caughtError ? '<!--vesk-ssr-error:' + (caughtError && typeof caughtError === 'object' && 'message' in caughtError ? encodeURIComponent(__expose ? String(caughtError.message) : 'Internal Server Error') : '') + '-->' : '') + page.body;",
|
|
319
|
+
' const html = await __wrapLayouts(params, _body, page.head || \'\');',
|
|
320
|
+
" return new Response(__injectStoreInit(html), { headers: { 'Content-Type': 'text/html' }, status: notFound ? 404 : (caughtError ? 500 : 200) });",
|
|
242
321
|
' });',
|
|
243
322
|
'}',
|
|
244
323
|
'',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vesk/adapter",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.70",
|
|
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.70",
|
|
27
|
+
"@vesk/runtime": "^0.2.70",
|
|
28
|
+
"@vesk/types": "^0.2.70"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/ws": "^8.18.1",
|