@jay-framework/dev-server 0.25.1 → 0.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +7 -0
- package/dist/index.js +117 -16
- package/package.json +15 -15
package/dist/index.d.ts
CHANGED
|
@@ -186,6 +186,13 @@ interface DevServer {
|
|
|
186
186
|
freezeStore?: FreezeStore;
|
|
187
187
|
/** Public API for design board applications and CLI (DL#128) */
|
|
188
188
|
service: DevServerService;
|
|
189
|
+
/**
|
|
190
|
+
* Express handler that renders the designed error page for a status (DL#218). Mount
|
|
191
|
+
* `errorPageHandler(404)` as a catch-all **after** all route registrations so unmatched paths
|
|
192
|
+
* get the branded 404 instead of Express's default. Falls back to plain text when no error page
|
|
193
|
+
* matches the status.
|
|
194
|
+
*/
|
|
195
|
+
errorPageHandler: (status: number) => RequestHandler;
|
|
189
196
|
}
|
|
190
197
|
declare function mkDevServer(rawOptions: DevServerOptions): Promise<DevServer>;
|
|
191
198
|
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { createRequire as createRequire$1 } from "node:module";
|
|
|
13
13
|
import * as fs from "node:fs";
|
|
14
14
|
import fs__default$1 from "node:fs";
|
|
15
15
|
import { scanRoutes, createRoute, routeToExpressRoute } from "@jay-framework/stack-route-scanner";
|
|
16
|
-
import { makePassthroughInstanceComponent, actionRegistry, scanPlugins, serializeHeadTags, mergeHeadTags, serializeScripts, discoverPluginsWithInit, sortPluginsByDependencies, executePluginServerInits, runInitCallbacks, runShutdownCallbacks, clearLifecycleCallbacks, clearServiceRegistry, clearClientInitData, runLoadParams, DevSlowlyChangingPhase, preparePluginClientInits, registerService, getServiceRegistry, parseCookies, renderFastChangingData, getClientInitData, slowRenderInstances, normalizeInstancePropNames } from "@jay-framework/stack-server-runtime";
|
|
16
|
+
import { makePassthroughInstanceComponent, actionRegistry, scanPlugins, serializeHeadTags, mergeHeadTags, serializeScripts, discoverPluginsWithInit, sortPluginsByDependencies, executePluginServerInits, runInitCallbacks, runShutdownCallbacks, clearLifecycleCallbacks, clearServiceRegistry, clearClientInitData, runLoadParams, DevSlowlyChangingPhase, preparePluginClientInits, registerService, getServiceRegistry, parseCookies, renderFastChangingData, getClientInitData, slowRenderInstances, normalizeInstancePropNames, resolveErrorPageToken, buildErrorViewState } from "@jay-framework/stack-server-runtime";
|
|
17
17
|
import * as fs$1 from "node:fs/promises";
|
|
18
18
|
import fs__default from "node:fs/promises";
|
|
19
19
|
import jsBeautify from "js-beautify";
|
|
@@ -4405,10 +4405,22 @@ class DevServerService {
|
|
|
4405
4405
|
let _watchLinkedFiles = () => {
|
|
4406
4406
|
};
|
|
4407
4407
|
async function initRoutes(pagesBaseFolder) {
|
|
4408
|
-
|
|
4408
|
+
const { routes } = await scanRoutes(pagesBaseFolder, {
|
|
4409
4409
|
jayHtmlFilename: "page.jay-html",
|
|
4410
4410
|
compFilename: "page.ts"
|
|
4411
4411
|
});
|
|
4412
|
+
return routes;
|
|
4413
|
+
}
|
|
4414
|
+
async function initErrorPages(pagesBaseFolder) {
|
|
4415
|
+
const { errorPages } = await scanRoutes(pagesBaseFolder, {
|
|
4416
|
+
jayHtmlFilename: "page.jay-html",
|
|
4417
|
+
compFilename: "page.ts"
|
|
4418
|
+
});
|
|
4419
|
+
const map = /* @__PURE__ */ new Map();
|
|
4420
|
+
for (const ep of errorPages) {
|
|
4421
|
+
map.set(ep.token, createRoute(`/_errors/${ep.token}`, ep.jayHtmlPath, ep.compPath));
|
|
4422
|
+
}
|
|
4423
|
+
return map;
|
|
4412
4424
|
}
|
|
4413
4425
|
async function scanPluginRoutes(projectRoot, projectRoutes) {
|
|
4414
4426
|
const plugins = await scanPlugins({ projectRoot, includeDevDeps: true });
|
|
@@ -4538,12 +4550,81 @@ function defaults(options) {
|
|
|
4538
4550
|
httpServer: options.httpServer
|
|
4539
4551
|
};
|
|
4540
4552
|
}
|
|
4541
|
-
|
|
4542
|
-
if (
|
|
4543
|
-
res.status(
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4553
|
+
let _renderDevErrorPage = async (res, info) => {
|
|
4554
|
+
if (!res.headersSent)
|
|
4555
|
+
res.status(info.status).type("text/plain").send(info.message || info.title || "Error");
|
|
4556
|
+
};
|
|
4557
|
+
async function renderDevErrorPage(vite, options, errorRoutes, projectInit, allPluginsWithInit, allPluginClientInits, res, info) {
|
|
4558
|
+
const plainText = () => {
|
|
4559
|
+
if (!res.headersSent)
|
|
4560
|
+
res.status(info.status).type("text/plain").send(info.message || info.title || "Error");
|
|
4561
|
+
};
|
|
4562
|
+
try {
|
|
4563
|
+
const token = resolveErrorPageToken(errorRoutes.keys(), info.status);
|
|
4564
|
+
if (!token) return plainText();
|
|
4565
|
+
const route = errorRoutes.get(token);
|
|
4566
|
+
const partsResult = await loadPageParts(
|
|
4567
|
+
vite,
|
|
4568
|
+
route,
|
|
4569
|
+
options.pagesRootFolder,
|
|
4570
|
+
options.projectRootFolder,
|
|
4571
|
+
options.jayRollupConfig
|
|
4572
|
+
);
|
|
4573
|
+
if (!partsResult.val) {
|
|
4574
|
+
getLogger().warn(
|
|
4575
|
+
`[DevServer] Error page "${token}" failed to load: ${partsResult.validations.join("; ")}`
|
|
4576
|
+
);
|
|
4577
|
+
return plainText();
|
|
4578
|
+
}
|
|
4579
|
+
const { parts, clientTrackByMap, usedPackages, scripts } = partsResult.val;
|
|
4580
|
+
const pluginsForPage = filterPluginsForPage(
|
|
4581
|
+
allPluginClientInits,
|
|
4582
|
+
allPluginsWithInit,
|
|
4583
|
+
usedPackages
|
|
4584
|
+
);
|
|
4585
|
+
const fullViewState = buildErrorViewState(info, {});
|
|
4586
|
+
await sendResponse(
|
|
4587
|
+
vite,
|
|
4588
|
+
res,
|
|
4589
|
+
info.url,
|
|
4590
|
+
route.jayHtmlPath,
|
|
4591
|
+
route.jayHtmlPath,
|
|
4592
|
+
parts,
|
|
4593
|
+
fullViewState,
|
|
4594
|
+
{},
|
|
4595
|
+
clientTrackByMap,
|
|
4596
|
+
projectInit,
|
|
4597
|
+
pluginsForPage,
|
|
4598
|
+
options,
|
|
4599
|
+
routeToExpressRoute(route),
|
|
4600
|
+
getRouteDir(route),
|
|
4601
|
+
{},
|
|
4602
|
+
void 0,
|
|
4603
|
+
void 0,
|
|
4604
|
+
void 0,
|
|
4605
|
+
scripts,
|
|
4606
|
+
info.status
|
|
4607
|
+
);
|
|
4608
|
+
} catch (err) {
|
|
4609
|
+
getLogger().error(
|
|
4610
|
+
`[DevServer] Error page render failed (${info.status} ${info.url}): ${err?.message}`
|
|
4611
|
+
);
|
|
4612
|
+
plainText();
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
async function handleOtherResponseCodes(res, renderedResult, url) {
|
|
4616
|
+
if (renderedResult.kind === `Redirect`) {
|
|
4617
|
+
res.status(renderedResult.status).end("redirect to " + renderedResult.location);
|
|
4618
|
+
return;
|
|
4619
|
+
}
|
|
4620
|
+
await _renderDevErrorPage(res, {
|
|
4621
|
+
status: renderedResult.status,
|
|
4622
|
+
url,
|
|
4623
|
+
message: renderedResult.message,
|
|
4624
|
+
title: renderedResult.title,
|
|
4625
|
+
code: renderedResult.code,
|
|
4626
|
+
details: renderedResult.details
|
|
4627
|
+
});
|
|
4547
4628
|
}
|
|
4548
4629
|
function filterPluginsForPage(allPluginClientInits, allPluginsWithInit, usedPackages) {
|
|
4549
4630
|
const pluginsByPackage = /* @__PURE__ */ new Map();
|
|
@@ -4671,7 +4752,12 @@ function mkRoute(route, vite, slowlyPhase, options, slowRenderCache, freezeStore
|
|
|
4671
4752
|
} catch (e2) {
|
|
4672
4753
|
vite?.ssrFixStacktrace(e2);
|
|
4673
4754
|
getLogger().error(e2.stack);
|
|
4674
|
-
|
|
4755
|
+
const errUrl = (req.originalUrl || req.url || "/").split("?")[0];
|
|
4756
|
+
await _renderDevErrorPage(res, {
|
|
4757
|
+
status: 500,
|
|
4758
|
+
url: errUrl,
|
|
4759
|
+
message: e2.message
|
|
4760
|
+
});
|
|
4675
4761
|
timing?.end();
|
|
4676
4762
|
}
|
|
4677
4763
|
};
|
|
@@ -4734,7 +4820,7 @@ async function handleCachedRequest(vite, route, options, cachedEntry, pageParams
|
|
|
4734
4820
|
);
|
|
4735
4821
|
timing?.recordFastRender(Date.now() - fastStart);
|
|
4736
4822
|
if (renderedFast.kind !== "PhaseOutput") {
|
|
4737
|
-
handleOtherResponseCodes(res, renderedFast);
|
|
4823
|
+
await handleOtherResponseCodes(res, renderedFast, url);
|
|
4738
4824
|
timing?.end();
|
|
4739
4825
|
return;
|
|
4740
4826
|
}
|
|
@@ -4810,7 +4896,7 @@ async function handlePreRenderRequest(vite, route, options, slowlyPhase, slowRen
|
|
|
4810
4896
|
);
|
|
4811
4897
|
if (renderedSlowly.kind !== "PhaseOutput") {
|
|
4812
4898
|
timing?.recordSlowRender(Date.now() - slowStart);
|
|
4813
|
-
handleOtherResponseCodes(res, renderedSlowly);
|
|
4899
|
+
await handleOtherResponseCodes(res, renderedSlowly, url);
|
|
4814
4900
|
timing?.end();
|
|
4815
4901
|
return;
|
|
4816
4902
|
}
|
|
@@ -4920,7 +5006,7 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
|
|
|
4920
5006
|
);
|
|
4921
5007
|
if (renderedSlowly.kind !== "PhaseOutput") {
|
|
4922
5008
|
timing?.recordSlowRender(Date.now() - slowStart);
|
|
4923
|
-
handleOtherResponseCodes(res, renderedSlowly);
|
|
5009
|
+
await handleOtherResponseCodes(res, renderedSlowly, url);
|
|
4924
5010
|
timing?.end();
|
|
4925
5011
|
return;
|
|
4926
5012
|
}
|
|
@@ -4941,7 +5027,7 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
|
|
|
4941
5027
|
);
|
|
4942
5028
|
timing?.recordFastRender(Date.now() - fastStart);
|
|
4943
5029
|
if (renderedFast.kind !== "PhaseOutput") {
|
|
4944
|
-
handleOtherResponseCodes(res, renderedFast);
|
|
5030
|
+
await handleOtherResponseCodes(res, renderedFast, url);
|
|
4945
5031
|
timing?.end();
|
|
4946
5032
|
return;
|
|
4947
5033
|
}
|
|
@@ -4985,7 +5071,7 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
|
|
|
4985
5071
|
res.status(200).set({ "Content-Type": "text/html" }).send(compiledPageHtml);
|
|
4986
5072
|
timing?.end();
|
|
4987
5073
|
}
|
|
4988
|
-
async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, pageParts, viewState, carryForward, clientTrackByMap, projectInit, pluginsForPage, options, routePattern, routeDir, slowViewState, timing, preLoadedContent, headTags, scripts) {
|
|
5074
|
+
async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, pageParts, viewState, carryForward, clientTrackByMap, projectInit, pluginsForPage, options, routePattern, routeDir, slowViewState, timing, preLoadedContent, headTags, scripts, statusCode = 200) {
|
|
4989
5075
|
let pageHtml;
|
|
4990
5076
|
try {
|
|
4991
5077
|
const jayHtmlDir = path__default.dirname(jayHtmlPath);
|
|
@@ -5048,7 +5134,7 @@ async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, page
|
|
|
5048
5134
|
const viteStart = Date.now();
|
|
5049
5135
|
const compiledPageHtml = await vite.transformIndexHtml(!!url ? url : "/", pageHtml);
|
|
5050
5136
|
timing?.recordViteClient(Date.now() - viteStart);
|
|
5051
|
-
res.status(
|
|
5137
|
+
res.status(statusCode).set({ "Content-Type": "text/html" }).send(compiledPageHtml);
|
|
5052
5138
|
timing?.end();
|
|
5053
5139
|
}
|
|
5054
5140
|
async function handleFrozenRequest(vite, route, options, freezeStore, slowRenderCache, freezeId, pageParams, format, res, url, timing) {
|
|
@@ -5230,6 +5316,7 @@ async function mkDevServer(rawOptions) {
|
|
|
5230
5316
|
setupActionRouter(vite, buildFolder);
|
|
5231
5317
|
const projectRoutes = await initRoutes(pagesRootFolder);
|
|
5232
5318
|
const filteredProjectRoutes = buildFolder ? projectRoutes.filter((route) => !route.jayHtmlPath.startsWith(buildFolder)) : projectRoutes;
|
|
5319
|
+
const errorRoutes = await initErrorPages(pagesRootFolder);
|
|
5233
5320
|
const pluginRoutes = await scanPluginRoutes(projectRootFolder, filteredProjectRoutes);
|
|
5234
5321
|
const routes = [...filteredProjectRoutes, ...pluginRoutes];
|
|
5235
5322
|
const slowlyPhase = new DevSlowlyChangingPhase();
|
|
@@ -5243,6 +5330,16 @@ async function mkDevServer(rawOptions) {
|
|
|
5243
5330
|
const projectInit = lifecycleManager.getProjectInit() ?? void 0;
|
|
5244
5331
|
const pluginsWithInit = lifecycleManager.getPluginsWithInit();
|
|
5245
5332
|
const pluginClientInits = preparePluginClientInits(pluginsWithInit);
|
|
5333
|
+
_renderDevErrorPage = (res, info) => renderDevErrorPage(
|
|
5334
|
+
vite,
|
|
5335
|
+
options,
|
|
5336
|
+
errorRoutes,
|
|
5337
|
+
projectInit,
|
|
5338
|
+
pluginsWithInit,
|
|
5339
|
+
pluginClientInits,
|
|
5340
|
+
res,
|
|
5341
|
+
info
|
|
5342
|
+
);
|
|
5246
5343
|
const freezeStore = buildFolder ? new FreezeStore(buildFolder) : void 0;
|
|
5247
5344
|
if (freezeStore) {
|
|
5248
5345
|
setupFreezeEndpoint(vite, freezeStore);
|
|
@@ -5314,7 +5411,11 @@ async function mkDevServer(rawOptions) {
|
|
|
5314
5411
|
routes: devServerRoutes,
|
|
5315
5412
|
lifecycleManager,
|
|
5316
5413
|
freezeStore,
|
|
5317
|
-
service
|
|
5414
|
+
service,
|
|
5415
|
+
errorPageHandler: (status) => async (req, res) => {
|
|
5416
|
+
const url = (req.originalUrl || req.url || "/").split("?")[0];
|
|
5417
|
+
await _renderDevErrorPage(res, { status, url });
|
|
5418
|
+
}
|
|
5318
5419
|
};
|
|
5319
5420
|
}
|
|
5320
5421
|
function setupGracefulShutdown(lifecycleManager) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/dev-server",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -23,24 +23,24 @@
|
|
|
23
23
|
"test:watch": "vitest"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@jay-framework/compiler-jay-stack": "^0.25.
|
|
27
|
-
"@jay-framework/compiler-shared": "^0.25.
|
|
28
|
-
"@jay-framework/component": "^0.25.
|
|
29
|
-
"@jay-framework/fullstack-component": "^0.25.
|
|
30
|
-
"@jay-framework/logger": "^0.25.
|
|
31
|
-
"@jay-framework/runtime": "^0.25.
|
|
32
|
-
"@jay-framework/stack-client-runtime": "^0.25.
|
|
33
|
-
"@jay-framework/stack-route-scanner": "^0.25.
|
|
34
|
-
"@jay-framework/stack-server-build": "^0.25.
|
|
35
|
-
"@jay-framework/stack-server-runtime": "^0.25.
|
|
36
|
-
"@jay-framework/view-state-merge": "^0.25.
|
|
26
|
+
"@jay-framework/compiler-jay-stack": "^0.25.2",
|
|
27
|
+
"@jay-framework/compiler-shared": "^0.25.2",
|
|
28
|
+
"@jay-framework/component": "^0.25.2",
|
|
29
|
+
"@jay-framework/fullstack-component": "^0.25.2",
|
|
30
|
+
"@jay-framework/logger": "^0.25.2",
|
|
31
|
+
"@jay-framework/runtime": "^0.25.2",
|
|
32
|
+
"@jay-framework/stack-client-runtime": "^0.25.2",
|
|
33
|
+
"@jay-framework/stack-route-scanner": "^0.25.2",
|
|
34
|
+
"@jay-framework/stack-server-build": "^0.25.2",
|
|
35
|
+
"@jay-framework/stack-server-runtime": "^0.25.2",
|
|
36
|
+
"@jay-framework/view-state-merge": "^0.25.2",
|
|
37
37
|
"busboy": "^1.6.0",
|
|
38
38
|
"vite": "^5.0.11"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@jay-framework/dev-environment": "^0.25.
|
|
42
|
-
"@jay-framework/jay-cli": "^0.25.
|
|
43
|
-
"@jay-framework/stack-client-runtime": "^0.25.
|
|
41
|
+
"@jay-framework/dev-environment": "^0.25.2",
|
|
42
|
+
"@jay-framework/jay-cli": "^0.25.2",
|
|
43
|
+
"@jay-framework/stack-client-runtime": "^0.25.2",
|
|
44
44
|
"@playwright/test": "^1.58.2",
|
|
45
45
|
"@types/busboy": "^1.5.4",
|
|
46
46
|
"@types/express": "^5.0.2",
|