@jay-framework/dev-server 0.25.5 → 0.26.0
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 +30 -1
- package/dist/index.js +103 -50
- package/package.json +17 -17
package/dist/index.d.ts
CHANGED
|
@@ -186,6 +186,35 @@ declare class DevServerService {
|
|
|
186
186
|
loadRouteParams(routePath: string): AsyncGenerator<Record<string, string>[]>;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/**
|
|
190
|
+
* Percent-encode `[`/`]` in the path of asset URLs (`href`/`src`) in served HTML.
|
|
191
|
+
*
|
|
192
|
+
* Dynamic routes produce asset paths with literal brackets (e.g.
|
|
193
|
+
* `.../pre-rendered/products/[slug]/page.css`), whether Vite serves them as
|
|
194
|
+
* `/@fs/…` or root-relative. Bare brackets in a URL are rejected by some
|
|
195
|
+
* dev-machine hosting proxies — the browser then sees an empty MIME type
|
|
196
|
+
* ("Refused to apply style … MIME type ('')"). This mirrors the production fix
|
|
197
|
+
* (DL#144/R7), which encodes brackets in *all* frontend asset paths; it is
|
|
198
|
+
* deliberately NOT `/@fs/`-specific (production has no `@fs`).
|
|
199
|
+
*
|
|
200
|
+
* Encoding only the emitted URL is sufficient and safe: the dev servers that
|
|
201
|
+
* handle these requests — Vite (`decodeURI`) and serve-static/express
|
|
202
|
+
* (`decodeURIComponent`) — decode `%5B` back to `[`, and CSS/module loading
|
|
203
|
+
* resolves via the plugin's `meta.originId` (not the id), so the encoded URL
|
|
204
|
+
* still maps to the literal on-disk file. Only the path (before `?`) is touched,
|
|
205
|
+
* so query strings (e.g. `?a[]=1`) are intact. In practice only asset URLs carry
|
|
206
|
+
* brackets — resolved navigation hrefs do not — so real links are unaffected.
|
|
207
|
+
* Exported so the dev-serving test guards the real behavior rather than a copy.
|
|
208
|
+
*/
|
|
209
|
+
declare function encodeBracketsInAssetUrls(html: string): string;
|
|
210
|
+
/**
|
|
211
|
+
* Filesystem-safe name for the per-route debug artifact, derived from the route
|
|
212
|
+
* path only (DL#229). The query string is dropped — otherwise a long query
|
|
213
|
+
* (e.g. an ~800-char auth token passed by a hosting proxy) pushes the filename
|
|
214
|
+
* past `NAME_MAX` (255) and `fs.writeFile` throws `ENAMETOOLONG`. Also strips
|
|
215
|
+
* non-fs-safe characters and length-caps as defense-in-depth. Pure → unit-tested.
|
|
216
|
+
*/
|
|
217
|
+
declare function debugPageName(url: string | undefined): string;
|
|
189
218
|
interface DevServerRoute {
|
|
190
219
|
path: string;
|
|
191
220
|
handler: RequestHandler;
|
|
@@ -324,4 +353,4 @@ declare function createViteForCli(options: {
|
|
|
324
353
|
tsConfigFilePath?: string;
|
|
325
354
|
}): Promise<ViteDevServer>;
|
|
326
355
|
|
|
327
|
-
export { ACTION_ENDPOINT_BASE, type ActionBodyParserOptions, type ActionRouterOptions, type CreateViteServerOptions, DEV_SERVER_SERVICE, type DevServer, type DevServerOptions, type DevServerRoute, type DevServerRouteRegistrar, DevServerService, type FreezeEntry, FreezeStore, type RouteInfo, actionBodyParser, createActionRouter, createViteForCli, createViteServer, mkDevServer, resolveAllowedHosts };
|
|
356
|
+
export { ACTION_ENDPOINT_BASE, type ActionBodyParserOptions, type ActionRouterOptions, type CreateViteServerOptions, DEV_SERVER_SERVICE, type DevServer, type DevServerOptions, type DevServerRoute, type DevServerRouteRegistrar, DevServerService, type FreezeEntry, FreezeStore, type RouteInfo, actionBodyParser, createActionRouter, createViteForCli, createViteServer, debugPageName, encodeBracketsInAssetUrls, mkDevServer, resolveAllowedHosts };
|
package/dist/index.js
CHANGED
|
@@ -11,11 +11,11 @@ import { parseJayFile, JAY_IMPORT_RESOLVER, discoverHeadlessInstances, assignCoo
|
|
|
11
11
|
import { getLogger, getDevLogger } from "@jay-framework/logger";
|
|
12
12
|
import { createRequire as createRequire$1 } from "node:module";
|
|
13
13
|
import * as fs from "node:fs";
|
|
14
|
-
import fs__default
|
|
14
|
+
import fs__default 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,
|
|
16
|
+
import { makePassthroughInstanceComponent, actionRegistry, scanPlugins, serializeHeadTags, mergeHeadTags, serializeScripts, discoverPluginsWithInit, sortPluginsByDependencies, executePluginServerInits, runInitCallbacks, runShutdownCallbacks, clearLifecycleCallbacks, clearServiceRegistry, clearClientInitData, crossOriginErrorResponse, needsSameOriginCheck, isCrossOriginRequest, isSecureRequest, parseCookies, runLoadParams, DevSlowlyChangingPhase, preparePluginClientInits, registerService, getServiceRegistry, renderFastChangingData, getClientInitData, slowRenderInstances, normalizeInstancePropNames, resolveErrorPageToken, buildErrorViewState } from "@jay-framework/stack-server-runtime";
|
|
17
17
|
import * as fs$1 from "node:fs/promises";
|
|
18
|
-
import
|
|
18
|
+
import fs$1__default from "node:fs/promises";
|
|
19
19
|
import jsBeautify from "js-beautify";
|
|
20
20
|
import fs$2 from "fs";
|
|
21
21
|
import path$1 from "path";
|
|
@@ -1052,7 +1052,9 @@ function extractActionFromExpression(node) {
|
|
|
1052
1052
|
current = expr.expression;
|
|
1053
1053
|
continue;
|
|
1054
1054
|
}
|
|
1055
|
-
if (c$1.isPropertyAccessExpression(expr) && ["withServices", "withCaching", "withHandler", "withTimeout"].includes(
|
|
1055
|
+
if (c$1.isPropertyAccessExpression(expr) && ["withServices", "withCaching", "withHandler", "withTimeout", "withRequest"].includes(
|
|
1056
|
+
expr.name.text
|
|
1057
|
+
)) {
|
|
1056
1058
|
current = expr.expression;
|
|
1057
1059
|
continue;
|
|
1058
1060
|
}
|
|
@@ -1637,7 +1639,7 @@ function resolveClientImportPath(route) {
|
|
|
1637
1639
|
return route.compPath;
|
|
1638
1640
|
}
|
|
1639
1641
|
async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfig, options) {
|
|
1640
|
-
const exists = await
|
|
1642
|
+
const exists = await fs$1__default.access(route.compPath, fs$1__default.constants.F_OK).then(() => true).catch(() => false);
|
|
1641
1643
|
const parts = [];
|
|
1642
1644
|
const validations = [];
|
|
1643
1645
|
if (exists) {
|
|
@@ -1657,7 +1659,7 @@ async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfi
|
|
|
1657
1659
|
}
|
|
1658
1660
|
}
|
|
1659
1661
|
const jayHtmlFilePath = options?.preRenderedPath ?? route.jayHtmlPath;
|
|
1660
|
-
const jayHtmlSource = options?.preRenderedContent ?? (await
|
|
1662
|
+
const jayHtmlSource = options?.preRenderedContent ?? (await fs$1__default.readFile(jayHtmlFilePath)).toString();
|
|
1661
1663
|
const fileName = path__default.basename(route.jayHtmlPath);
|
|
1662
1664
|
const dirName = path__default.dirname(route.jayHtmlPath);
|
|
1663
1665
|
const jayHtmlWithValidations = await parseJayFile(
|
|
@@ -2512,7 +2514,7 @@ async function generateFrozenPageHtml(vite, jayHtmlContent, jayHtmlFilename, jay
|
|
|
2512
2514
|
if (cached.cssHref) {
|
|
2513
2515
|
try {
|
|
2514
2516
|
const cssPath = cached.cssHref.replace(/^\/@fs/, "").replace(/\?.*$/, "");
|
|
2515
|
-
const cssContent = await
|
|
2517
|
+
const cssContent = await fs$1__default.readFile(cssPath, "utf-8");
|
|
2516
2518
|
inlineCss = `<style>${cssContent}</style>`;
|
|
2517
2519
|
} catch {
|
|
2518
2520
|
inlineCss = `<link rel="stylesheet" href="${cached.cssHref}" />`;
|
|
@@ -2591,11 +2593,11 @@ async function compileAndLoadServerElement(vite, jayHtmlContent, jayHtmlFilename
|
|
|
2591
2593
|
generateServerElementFile(parsedJayFile, serverElementOptions)
|
|
2592
2594
|
);
|
|
2593
2595
|
const serverElementDir = path__default.join(buildFolder, "pre-rendered", routeDir);
|
|
2594
|
-
await
|
|
2596
|
+
await fs$1__default.mkdir(serverElementDir, { recursive: true });
|
|
2595
2597
|
const adjustedCode = rebaseRelativeImports(serverElementCode, jayHtmlDir, serverElementDir);
|
|
2596
2598
|
const serverElementFilename = jayHtmlFilename.replace(".jay-html", ".server-element.ts");
|
|
2597
2599
|
const serverElementPath = path__default.join(serverElementDir, serverElementFilename);
|
|
2598
|
-
await
|
|
2600
|
+
await fs$1__default.writeFile(serverElementPath, adjustedCode, "utf-8");
|
|
2599
2601
|
const existingModule = vite.moduleGraph.getModuleById(serverElementPath);
|
|
2600
2602
|
if (existingModule) {
|
|
2601
2603
|
vite.moduleGraph.invalidateModule(existingModule);
|
|
@@ -2607,7 +2609,7 @@ async function compileAndLoadServerElement(vite, jayHtmlContent, jayHtmlFilename
|
|
|
2607
2609
|
if (parsedJayFile.css) {
|
|
2608
2610
|
const cssFilename = jayHtmlFilename.replace(".jay-html", ".css");
|
|
2609
2611
|
const cssPath = path__default.join(serverElementDir, cssFilename);
|
|
2610
|
-
await
|
|
2612
|
+
await fs$1__default.writeFile(cssPath, parsedJayFile.css, "utf-8");
|
|
2611
2613
|
const cssModules = vite.moduleGraph.getModulesByFile(cssPath);
|
|
2612
2614
|
if (cssModules) {
|
|
2613
2615
|
for (const mod of cssModules) {
|
|
@@ -3684,7 +3686,7 @@ class SlowRenderCache {
|
|
|
3684
3686
|
const preRenderedPath = this.computeCachePath(jayHtmlPath, params, routeDir);
|
|
3685
3687
|
let fileContent;
|
|
3686
3688
|
try {
|
|
3687
|
-
fileContent = await
|
|
3689
|
+
fileContent = await fs$1__default.readFile(preRenderedPath, "utf-8");
|
|
3688
3690
|
} catch {
|
|
3689
3691
|
return void 0;
|
|
3690
3692
|
}
|
|
@@ -3712,8 +3714,8 @@ class SlowRenderCache {
|
|
|
3712
3714
|
carryForward,
|
|
3713
3715
|
jayHtmlPath
|
|
3714
3716
|
);
|
|
3715
|
-
await
|
|
3716
|
-
await
|
|
3717
|
+
await fs$1__default.mkdir(path__default.dirname(preRenderedPath), { recursive: true });
|
|
3718
|
+
await fs$1__default.writeFile(preRenderedPath, fileContent, "utf-8");
|
|
3717
3719
|
this.trackFile(jayHtmlPath, preRenderedPath);
|
|
3718
3720
|
return {
|
|
3719
3721
|
preRenderedPath,
|
|
@@ -3729,7 +3731,7 @@ class SlowRenderCache {
|
|
|
3729
3731
|
async has(jayHtmlPath, params, routeDir) {
|
|
3730
3732
|
const preRenderedPath = this.computeCachePath(jayHtmlPath, params, routeDir);
|
|
3731
3733
|
try {
|
|
3732
|
-
await
|
|
3734
|
+
await fs$1__default.access(preRenderedPath);
|
|
3733
3735
|
return true;
|
|
3734
3736
|
} catch {
|
|
3735
3737
|
return false;
|
|
@@ -3744,7 +3746,7 @@ class SlowRenderCache {
|
|
|
3744
3746
|
if (files) {
|
|
3745
3747
|
for (const filePath of files) {
|
|
3746
3748
|
try {
|
|
3747
|
-
await
|
|
3749
|
+
await fs$1__default.unlink(filePath);
|
|
3748
3750
|
} catch {
|
|
3749
3751
|
}
|
|
3750
3752
|
}
|
|
@@ -3781,14 +3783,14 @@ class SlowRenderCache {
|
|
|
3781
3783
|
for (const files of this.pathToFiles.values()) {
|
|
3782
3784
|
for (const filePath of files) {
|
|
3783
3785
|
try {
|
|
3784
|
-
await
|
|
3786
|
+
await fs$1__default.unlink(filePath);
|
|
3785
3787
|
} catch {
|
|
3786
3788
|
}
|
|
3787
3789
|
}
|
|
3788
3790
|
}
|
|
3789
3791
|
this.pathToFiles.clear();
|
|
3790
3792
|
try {
|
|
3791
|
-
await
|
|
3793
|
+
await fs$1__default.rm(this.cacheDir, { recursive: true, force: true });
|
|
3792
3794
|
} catch {
|
|
3793
3795
|
}
|
|
3794
3796
|
}
|
|
@@ -3839,11 +3841,11 @@ class SlowRenderCache {
|
|
|
3839
3841
|
const basename = path__default.basename(jayHtmlPath, ".jay-html");
|
|
3840
3842
|
const cacheSubDir = path__default.join(this.cacheDir, dir);
|
|
3841
3843
|
try {
|
|
3842
|
-
const files = await
|
|
3844
|
+
const files = await fs$1__default.readdir(cacheSubDir);
|
|
3843
3845
|
for (const file of files) {
|
|
3844
3846
|
if (file.startsWith(basename)) {
|
|
3845
3847
|
try {
|
|
3846
|
-
await
|
|
3848
|
+
await fs$1__default.unlink(path__default.join(cacheSubDir, file));
|
|
3847
3849
|
} catch {
|
|
3848
3850
|
}
|
|
3849
3851
|
}
|
|
@@ -4159,6 +4161,10 @@ function createActionRouter(options) {
|
|
|
4159
4161
|
});
|
|
4160
4162
|
return;
|
|
4161
4163
|
}
|
|
4164
|
+
if (isRejectedCrossOrigin(action, req)) {
|
|
4165
|
+
res.status(403).json(crossOriginErrorResponse(actionName));
|
|
4166
|
+
return;
|
|
4167
|
+
}
|
|
4162
4168
|
let input;
|
|
4163
4169
|
try {
|
|
4164
4170
|
if (requestMethod === "GET") {
|
|
@@ -4190,11 +4196,15 @@ function createActionRouter(options) {
|
|
|
4190
4196
|
const cleanup = () => {
|
|
4191
4197
|
if (tempDir) cleanupTempDir(tempDir);
|
|
4192
4198
|
};
|
|
4199
|
+
const incoming = action.needsRequest ? readIncomingRequest(req) : void 0;
|
|
4200
|
+
if (action.needsRequest) {
|
|
4201
|
+
res.set("Cache-Control", registry.getCacheHeaders(actionName));
|
|
4202
|
+
}
|
|
4193
4203
|
if (registry.isStreaming(actionName)) {
|
|
4194
4204
|
res.setHeader("Content-Type", "application/x-ndjson");
|
|
4195
4205
|
res.setHeader("Transfer-Encoding", "chunked");
|
|
4196
4206
|
try {
|
|
4197
|
-
const generator = registry.executeStream(actionName, input);
|
|
4207
|
+
const generator = registry.executeStream(actionName, input, incoming);
|
|
4198
4208
|
for await (const chunk of generator) {
|
|
4199
4209
|
res.write(JSON.stringify({ chunk }) + "\n");
|
|
4200
4210
|
}
|
|
@@ -4207,7 +4217,7 @@ function createActionRouter(options) {
|
|
|
4207
4217
|
timing?.end();
|
|
4208
4218
|
return;
|
|
4209
4219
|
}
|
|
4210
|
-
const result = await registry.execute(actionName, input);
|
|
4220
|
+
const result = await registry.execute(actionName, input, incoming);
|
|
4211
4221
|
cleanup();
|
|
4212
4222
|
if (requestMethod === "GET" && result.success) {
|
|
4213
4223
|
const cacheHeaders = registry.getCacheHeaders(actionName);
|
|
@@ -4216,6 +4226,9 @@ function createActionRouter(options) {
|
|
|
4216
4226
|
}
|
|
4217
4227
|
}
|
|
4218
4228
|
if (result.success) {
|
|
4229
|
+
for (const setCookie of result.setCookies ?? []) {
|
|
4230
|
+
res.append("Set-Cookie", setCookie);
|
|
4231
|
+
}
|
|
4219
4232
|
res.status(200).json({
|
|
4220
4233
|
success: true,
|
|
4221
4234
|
data: result.data
|
|
@@ -4230,6 +4243,19 @@ function createActionRouter(options) {
|
|
|
4230
4243
|
timing?.end();
|
|
4231
4244
|
};
|
|
4232
4245
|
}
|
|
4246
|
+
function isRejectedCrossOrigin(action, req) {
|
|
4247
|
+
return needsSameOriginCheck(action) && isCrossOriginRequest({
|
|
4248
|
+
secFetchSite: req.headers["sec-fetch-site"],
|
|
4249
|
+
origin: req.headers.origin,
|
|
4250
|
+
requestOrigin: `${req.protocol}://${req.headers.host}`
|
|
4251
|
+
});
|
|
4252
|
+
}
|
|
4253
|
+
function readIncomingRequest(req) {
|
|
4254
|
+
return {
|
|
4255
|
+
cookies: parseCookies(req.headers.cookie),
|
|
4256
|
+
secure: isSecureRequest(req.protocol, req.headers["x-forwarded-proto"])
|
|
4257
|
+
};
|
|
4258
|
+
}
|
|
4233
4259
|
function getStatusCodeForError(code, isActionError) {
|
|
4234
4260
|
if (isActionError) {
|
|
4235
4261
|
return 422;
|
|
@@ -4360,6 +4386,11 @@ function actionBodyParser(options) {
|
|
|
4360
4386
|
next();
|
|
4361
4387
|
return;
|
|
4362
4388
|
}
|
|
4389
|
+
const routedAction = registryToUse.get(req.path.slice(ACTION_ENDPOINT_BASE.length + 1));
|
|
4390
|
+
if (routedAction && isRejectedCrossOrigin(routedAction, req)) {
|
|
4391
|
+
next();
|
|
4392
|
+
return;
|
|
4393
|
+
}
|
|
4363
4394
|
const contentType = req.headers["content-type"] || "";
|
|
4364
4395
|
if (contentType.startsWith("multipart/form-data")) {
|
|
4365
4396
|
const actionName = req.path.slice(ACTION_ENDPOINT_BASE.length + 1);
|
|
@@ -4556,6 +4587,30 @@ class DevServerService {
|
|
|
4556
4587
|
yield* runLoadParams(loaded.val.parts);
|
|
4557
4588
|
}
|
|
4558
4589
|
}
|
|
4590
|
+
function encodeBracketsInAssetUrls(html) {
|
|
4591
|
+
return html.replace(/\b(href|src)="([^"]*)"/g, (whole, attr, value) => {
|
|
4592
|
+
const q = value.indexOf("?");
|
|
4593
|
+
const pathPart = q === -1 ? value : value.slice(0, q);
|
|
4594
|
+
if (!pathPart.includes("[") && !pathPart.includes("]")) return whole;
|
|
4595
|
+
const encodedPath = pathPart.replace(/\[/g, "%5B").replace(/\]/g, "%5D");
|
|
4596
|
+
return `${attr}="${encodedPath}${q === -1 ? "" : value.slice(q)}"`;
|
|
4597
|
+
});
|
|
4598
|
+
}
|
|
4599
|
+
function debugPageName(url) {
|
|
4600
|
+
const routePath = (url || "/").split("?")[0];
|
|
4601
|
+
if (routePath === "/" || routePath === "") return "index";
|
|
4602
|
+
return routePath.replace(/^\//, "").replace(/\//g, "-").replace(/[^\w.-]/g, "_").slice(0, 200) || "index";
|
|
4603
|
+
}
|
|
4604
|
+
async function writeDebugPage(options, url, html) {
|
|
4605
|
+
if (options.logLevel !== "verbose" || !options.buildFolder) return;
|
|
4606
|
+
try {
|
|
4607
|
+
const clientScriptDir = path__default.join(options.buildFolder, "debug", "client-entry");
|
|
4608
|
+
await fs$1__default.mkdir(clientScriptDir, { recursive: true });
|
|
4609
|
+
await fs$1__default.writeFile(path__default.join(clientScriptDir, `${debugPageName(url)}.html`), html, "utf-8");
|
|
4610
|
+
} catch (e2) {
|
|
4611
|
+
getLogger().info(`[dev] debug page write skipped: ${e2.message}`);
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4559
4614
|
let _watchLinkedFiles = () => {
|
|
4560
4615
|
};
|
|
4561
4616
|
async function initRoutes(pagesBaseFolder) {
|
|
@@ -4623,7 +4678,7 @@ function resolvePluginExport(pluginPath, exportSubpath) {
|
|
|
4623
4678
|
const normalized = exportSubpath.replace(/^\.\//, "");
|
|
4624
4679
|
const packageJsonPath = path__default.join(pluginPath, "package.json");
|
|
4625
4680
|
try {
|
|
4626
|
-
const packageJson = JSON.parse(fs__default
|
|
4681
|
+
const packageJson = JSON.parse(fs__default.readFileSync(packageJsonPath, "utf-8"));
|
|
4627
4682
|
if (packageJson.exports) {
|
|
4628
4683
|
const exportKey = "./" + normalized;
|
|
4629
4684
|
const exportValue = packageJson.exports[exportKey];
|
|
@@ -4640,7 +4695,7 @@ function resolvePluginExport(pluginPath, exportSubpath) {
|
|
|
4640
4695
|
for (const dir of ["dist", "lib", ""]) {
|
|
4641
4696
|
const candidate = path__default.join(pluginPath, dir, normalized);
|
|
4642
4697
|
try {
|
|
4643
|
-
fs__default
|
|
4698
|
+
fs__default.accessSync(candidate);
|
|
4644
4699
|
return candidate;
|
|
4645
4700
|
} catch {
|
|
4646
4701
|
}
|
|
@@ -4649,14 +4704,14 @@ function resolvePluginExport(pluginPath, exportSubpath) {
|
|
|
4649
4704
|
}
|
|
4650
4705
|
function resolvePluginModule(plugin, exportKey = ".") {
|
|
4651
4706
|
const pkgJsonPath = path__default.join(plugin.pluginPath, "package.json");
|
|
4652
|
-
if (fs__default
|
|
4707
|
+
if (fs__default.existsSync(pkgJsonPath)) {
|
|
4653
4708
|
try {
|
|
4654
|
-
const pkg = JSON.parse(fs__default
|
|
4709
|
+
const pkg = JSON.parse(fs__default.readFileSync(pkgJsonPath, "utf-8"));
|
|
4655
4710
|
const mainExport = pkg.exports?.[exportKey];
|
|
4656
4711
|
const mainPath = typeof mainExport === "string" ? mainExport : mainExport?.default || mainExport?.import || pkg.main;
|
|
4657
4712
|
if (mainPath) {
|
|
4658
4713
|
const resolved = path__default.join(plugin.pluginPath, mainPath);
|
|
4659
|
-
if (fs__default
|
|
4714
|
+
if (fs__default.existsSync(resolved)) return resolved;
|
|
4660
4715
|
}
|
|
4661
4716
|
} catch {
|
|
4662
4717
|
}
|
|
@@ -4665,7 +4720,7 @@ function resolvePluginModule(plugin, exportKey = ".") {
|
|
|
4665
4720
|
for (const ext of [".ts", ".js", "/index.ts", "/index.js"]) {
|
|
4666
4721
|
const candidate = path__default.join(plugin.pluginPath, modulePath + ext);
|
|
4667
4722
|
try {
|
|
4668
|
-
fs__default
|
|
4723
|
+
fs__default.accessSync(candidate);
|
|
4669
4724
|
return candidate;
|
|
4670
4725
|
} catch {
|
|
4671
4726
|
}
|
|
@@ -4673,7 +4728,7 @@ function resolvePluginModule(plugin, exportKey = ".") {
|
|
|
4673
4728
|
for (const ext of [".ts", ".js"]) {
|
|
4674
4729
|
const candidate = path__default.join(plugin.pluginPath, "lib", path__default.basename(modulePath) + ext);
|
|
4675
4730
|
try {
|
|
4676
|
-
fs__default
|
|
4731
|
+
fs__default.accessSync(candidate);
|
|
4677
4732
|
return candidate;
|
|
4678
4733
|
} catch {
|
|
4679
4734
|
}
|
|
@@ -5217,14 +5272,11 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
|
|
|
5217
5272
|
sourceFile: path__default.relative(options.projectRootFolder, route.jayHtmlPath)
|
|
5218
5273
|
}
|
|
5219
5274
|
);
|
|
5220
|
-
|
|
5221
|
-
const pageName = !url || url === "/" ? "index" : url.replace(/^\//, "").replace(/\//g, "-");
|
|
5222
|
-
const clientScriptDir = path__default.join(options.buildFolder, "debug", "client-entry");
|
|
5223
|
-
await fs__default.mkdir(clientScriptDir, { recursive: true });
|
|
5224
|
-
await fs__default.writeFile(path__default.join(clientScriptDir, `${pageName}.html`), pageHtml, "utf-8");
|
|
5225
|
-
}
|
|
5275
|
+
await writeDebugPage(options, url, pageHtml);
|
|
5226
5276
|
const viteStart = Date.now();
|
|
5227
|
-
const compiledPageHtml =
|
|
5277
|
+
const compiledPageHtml = encodeBracketsInAssetUrls(
|
|
5278
|
+
await vite.transformIndexHtml(url?.split("?")[0] || "/", pageHtml)
|
|
5279
|
+
);
|
|
5228
5280
|
timing?.recordViteClient(Date.now() - viteStart);
|
|
5229
5281
|
res.status(200).set({ "Content-Type": "text/html" }).send(compiledPageHtml);
|
|
5230
5282
|
timing?.end();
|
|
@@ -5234,7 +5286,7 @@ async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, page
|
|
|
5234
5286
|
const sourceFile = path__default.relative(options.projectRootFolder, sourceJayHtmlPath);
|
|
5235
5287
|
try {
|
|
5236
5288
|
const jayHtmlDir = path__default.dirname(jayHtmlPath);
|
|
5237
|
-
const rawContent = preLoadedContent ?? await
|
|
5289
|
+
const rawContent = preLoadedContent ?? await fs$1__default.readFile(jayHtmlPath, "utf-8");
|
|
5238
5290
|
const jayHtmlContent = options.sourceEditing ? injectDevMarkers(rawContent) : rawContent;
|
|
5239
5291
|
pageHtml = await generateSSRPageHtml(
|
|
5240
5292
|
vite,
|
|
@@ -5282,19 +5334,16 @@ async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, page
|
|
|
5282
5334
|
}
|
|
5283
5335
|
);
|
|
5284
5336
|
}
|
|
5285
|
-
|
|
5286
|
-
const pageName = !url || url === "/" ? "index" : url.replace(/^\//, "").replace(/\//g, "-");
|
|
5287
|
-
const clientScriptDir = path__default.join(options.buildFolder, "debug", "client-entry");
|
|
5288
|
-
await fs__default.mkdir(clientScriptDir, { recursive: true });
|
|
5289
|
-
await fs__default.writeFile(path__default.join(clientScriptDir, `${pageName}.html`), pageHtml, "utf-8");
|
|
5290
|
-
}
|
|
5337
|
+
await writeDebugPage(options, url, pageHtml);
|
|
5291
5338
|
for (const [id, mod] of vite.moduleGraph.idToModuleMap) {
|
|
5292
5339
|
if (id.includes("html-proxy")) {
|
|
5293
5340
|
vite.moduleGraph.invalidateModule(mod);
|
|
5294
5341
|
}
|
|
5295
5342
|
}
|
|
5296
5343
|
const viteStart = Date.now();
|
|
5297
|
-
const compiledPageHtml =
|
|
5344
|
+
const compiledPageHtml = encodeBracketsInAssetUrls(
|
|
5345
|
+
await vite.transformIndexHtml(url?.split("?")[0] || "/", pageHtml)
|
|
5346
|
+
);
|
|
5298
5347
|
timing?.recordViteClient(Date.now() - viteStart);
|
|
5299
5348
|
res.status(statusCode).set({ "Content-Type": "text/html" }).send(compiledPageHtml);
|
|
5300
5349
|
timing?.end();
|
|
@@ -5313,7 +5362,7 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
|
|
|
5313
5362
|
const routeDir = getRouteDir(route);
|
|
5314
5363
|
const cachedEntry = await slowRenderCache.get(route.jayHtmlPath, pageParams, routeDir);
|
|
5315
5364
|
const jayHtmlPath = cachedEntry?.preRenderedPath ?? route.jayHtmlPath;
|
|
5316
|
-
const jayHtmlContent = cachedEntry?.preRenderedContent ?? await
|
|
5365
|
+
const jayHtmlContent = cachedEntry?.preRenderedContent ?? await fs$1__default.readFile(jayHtmlPath, "utf-8");
|
|
5317
5366
|
const jayHtmlFilename = path__default.basename(jayHtmlPath);
|
|
5318
5367
|
const jayHtmlDir = path__default.dirname(jayHtmlPath);
|
|
5319
5368
|
const sourceDir = path__default.dirname(route.jayHtmlPath);
|
|
@@ -5338,7 +5387,9 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
|
|
|
5338
5387
|
headers["Access-Control-Allow-Origin"] = "*";
|
|
5339
5388
|
}
|
|
5340
5389
|
if (injectDevHmr) {
|
|
5341
|
-
const compiledHtml =
|
|
5390
|
+
const compiledHtml = encodeBracketsInAssetUrls(
|
|
5391
|
+
await vite.transformIndexHtml(url?.split("?")[0] || "/", html)
|
|
5392
|
+
);
|
|
5342
5393
|
res.status(200).set(headers).send(compiledHtml);
|
|
5343
5394
|
} else {
|
|
5344
5395
|
res.status(200).set(headers).send(html);
|
|
@@ -5350,13 +5401,13 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
|
|
|
5350
5401
|
timing?.end();
|
|
5351
5402
|
}
|
|
5352
5403
|
async function preRenderJayHtml(route, slowViewState, headlessContracts, headlessInstanceComponents, partKeys = [], pageParams = {}, pageProps = { language: "en", url: "" }, sourceEditing = false) {
|
|
5353
|
-
const rawJayHtml = await
|
|
5404
|
+
const rawJayHtml = await fs$1__default.readFile(route.jayHtmlPath, "utf-8");
|
|
5354
5405
|
const jayHtmlWithTemplates = sourceEditing ? injectDevMarkers(rawJayHtml) : rawJayHtml;
|
|
5355
5406
|
const sourceDir = path__default.dirname(route.jayHtmlPath);
|
|
5356
5407
|
let contract;
|
|
5357
5408
|
const contractPath = route.jayHtmlPath.replace(".jay-html", ".jay-contract");
|
|
5358
5409
|
try {
|
|
5359
|
-
const contractContent = await
|
|
5410
|
+
const contractContent = await fs$1__default.readFile(contractPath, "utf-8");
|
|
5360
5411
|
const parseResult = parseContract(contractContent, path__default.basename(contractPath));
|
|
5361
5412
|
if (parseResult.val) contract = parseResult.val;
|
|
5362
5413
|
} catch {
|
|
@@ -5453,10 +5504,10 @@ async function mkDevServer(rawOptions) {
|
|
|
5453
5504
|
const { publicBaseUrlPath, pagesRootFolder, projectRootFolder, buildFolder, jayRollupConfig } = options;
|
|
5454
5505
|
if (buildFolder) {
|
|
5455
5506
|
try {
|
|
5456
|
-
const entries = await
|
|
5507
|
+
const entries = await fs$1__default.readdir(buildFolder).catch(() => []);
|
|
5457
5508
|
for (const entry of entries) {
|
|
5458
5509
|
if (entry === "freezes") continue;
|
|
5459
|
-
await
|
|
5510
|
+
await fs$1__default.rm(path__default.join(buildFolder, entry), { recursive: true, force: true });
|
|
5460
5511
|
}
|
|
5461
5512
|
} catch {
|
|
5462
5513
|
}
|
|
@@ -5533,7 +5584,7 @@ async function mkDevServer(rawOptions) {
|
|
|
5533
5584
|
for (let i = devServerRoutes.length - 1; i >= 0; i--) {
|
|
5534
5585
|
const route = devServerRoutes[i];
|
|
5535
5586
|
const fsPath = route.fsRoute.jayHtmlPath;
|
|
5536
|
-
const stillOnDisk = scannedRawRoutes.has(route.fsRoute.rawRoute) && fs__default
|
|
5587
|
+
const stillOnDisk = scannedRawRoutes.has(route.fsRoute.rawRoute) && fs__default.existsSync(fsPath);
|
|
5537
5588
|
if (!stillOnDisk) {
|
|
5538
5589
|
devServerRoutes.splice(i, 1);
|
|
5539
5590
|
}
|
|
@@ -5763,6 +5814,8 @@ export {
|
|
|
5763
5814
|
createActionRouter,
|
|
5764
5815
|
createViteForCli,
|
|
5765
5816
|
createViteServer,
|
|
5817
|
+
debugPageName,
|
|
5818
|
+
encodeBracketsInAssetUrls,
|
|
5766
5819
|
mkDevServer,
|
|
5767
5820
|
resolveAllowedHosts
|
|
5768
5821
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/dev-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
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.
|
|
27
|
-
"@jay-framework/compiler-shared": "^0.
|
|
28
|
-
"@jay-framework/component": "^0.
|
|
29
|
-
"@jay-framework/fullstack-component": "^0.
|
|
30
|
-
"@jay-framework/logger": "^0.
|
|
31
|
-
"@jay-framework/runtime": "^0.
|
|
32
|
-
"@jay-framework/stack-client-runtime": "^0.
|
|
33
|
-
"@jay-framework/stack-route-scanner": "^0.
|
|
34
|
-
"@jay-framework/stack-server-build": "^0.
|
|
35
|
-
"@jay-framework/stack-server-runtime": "^0.
|
|
36
|
-
"@jay-framework/view-state-merge": "^0.
|
|
26
|
+
"@jay-framework/compiler-jay-stack": "^0.26.0",
|
|
27
|
+
"@jay-framework/compiler-shared": "^0.26.0",
|
|
28
|
+
"@jay-framework/component": "^0.26.0",
|
|
29
|
+
"@jay-framework/fullstack-component": "^0.26.0",
|
|
30
|
+
"@jay-framework/logger": "^0.26.0",
|
|
31
|
+
"@jay-framework/runtime": "^0.26.0",
|
|
32
|
+
"@jay-framework/stack-client-runtime": "^0.26.0",
|
|
33
|
+
"@jay-framework/stack-route-scanner": "^0.26.0",
|
|
34
|
+
"@jay-framework/stack-server-build": "^0.26.0",
|
|
35
|
+
"@jay-framework/stack-server-runtime": "^0.26.0",
|
|
36
|
+
"@jay-framework/view-state-merge": "^0.26.0",
|
|
37
37
|
"busboy": "^1.6.0",
|
|
38
|
-
"vite": "^
|
|
38
|
+
"vite": "^6.4.4"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@jay-framework/dev-environment": "^0.
|
|
42
|
-
"@jay-framework/jay-cli": "^0.
|
|
43
|
-
"@jay-framework/stack-client-runtime": "^0.
|
|
41
|
+
"@jay-framework/dev-environment": "^0.26.0",
|
|
42
|
+
"@jay-framework/jay-cli": "^0.26.0",
|
|
43
|
+
"@jay-framework/stack-client-runtime": "^0.26.0",
|
|
44
44
|
"@playwright/test": "^1.58.2",
|
|
45
45
|
"@types/busboy": "^1.5.4",
|
|
46
46
|
"@types/express": "^5.0.2",
|
|
@@ -52,6 +52,6 @@
|
|
|
52
52
|
"rimraf": "^5.0.5",
|
|
53
53
|
"tsup": "^8.0.1",
|
|
54
54
|
"typescript": "^5.3.3",
|
|
55
|
-
"vitest": "^1.
|
|
55
|
+
"vitest": "^4.1.11"
|
|
56
56
|
}
|
|
57
57
|
}
|