@jay-framework/dev-server 0.24.2 → 0.24.3

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.
Files changed (2) hide show
  1. package/dist/index.js +69 -28
  2. package/package.json +15 -15
package/dist/index.js CHANGED
@@ -1913,7 +1913,7 @@ function normalizeActionEntry(entry) {
1913
1913
  if (typeof entry === "string") {
1914
1914
  return { name: entry };
1915
1915
  }
1916
- return { name: entry.name, action: entry.action };
1916
+ return { name: entry.name, action: entry.action, devOnly: entry.devOnly };
1917
1917
  }
1918
1918
  function loadPluginManifest(pluginDir) {
1919
1919
  const pluginYamlPath = path$1.join(pluginDir, "plugin.yaml");
@@ -1995,6 +1995,18 @@ ${clientParts.map((part) => " " + part.clientPart).join(",\n")}
1995
1995
  slowViewStateDecl
1996
1996
  };
1997
1997
  }
1998
+ function buildPageReloadHmrScript() {
1999
+ return `
2000
+ if (import.meta.hot) {
2001
+ import.meta.hot.on('jay:page-reload', (data) => {
2002
+ const prefix = data.routePrefix;
2003
+ const pathname = window.location.pathname;
2004
+ if (pathname === prefix || pathname.startsWith(prefix + '/')) {
2005
+ window.location.reload();
2006
+ }
2007
+ });
2008
+ }`;
2009
+ }
1998
2010
  function buildFreezeScript(routePattern) {
1999
2011
  const routePatternLiteral = routePattern ? `'${routePattern}'` : "undefined";
2000
2012
  return `
@@ -2070,15 +2082,7 @@ function buildFreezeScript(routePattern) {
2070
2082
  }
2071
2083
 
2072
2084
  // Targeted page reload: only reload if this page matches the changed route prefix
2073
- if (import.meta.hot) {
2074
- import.meta.hot.on('jay:page-reload', (data) => {
2075
- const prefix = data.routePrefix;
2076
- const pathname = window.location.pathname;
2077
- if (pathname === prefix || pathname.startsWith(prefix + '/')) {
2078
- window.location.reload();
2079
- }
2080
- });
2081
- }`;
2085
+ ${buildPageReloadHmrScript()}`;
2082
2086
  }
2083
2087
  function buildAutomationWrap(options, mode) {
2084
2088
  const { enableAutomation = true, slowViewState } = options;
@@ -2312,7 +2316,7 @@ ${titleTag}${headExtras ? headExtras + "\n" : ""} </head>
2312
2316
  </body>
2313
2317
  </html>`;
2314
2318
  }
2315
- async function generateFrozenPageHtml(vite, jayHtmlContent, jayHtmlFilename, jayHtmlDir, viewState, buildFolder, projectRoot, routeDir, tsConfigFilePath, sourceDir, format = "page", freezeName) {
2319
+ async function generateFrozenPageHtml(vite, jayHtmlContent, jayHtmlFilename, jayHtmlDir, viewState, buildFolder, projectRoot, routeDir, tsConfigFilePath, sourceDir, format = "page", freezeName, options) {
2316
2320
  const jayHtmlPath = path__default.join(jayHtmlDir, jayHtmlFilename);
2317
2321
  let cached = serverModuleCache.get(jayHtmlPath);
2318
2322
  if (!cached) {
@@ -2358,6 +2362,9 @@ ${ssrHtml}`;
2358
2362
  const cssLink = cached.cssHref ? ` <link rel="stylesheet" href="${cached.cssHref}" />` : "";
2359
2363
  const headExtras = [cssLink, frozenHeadTagsHtml].filter((_) => _).join("\n");
2360
2364
  const label = freezeName ? ` — ${freezeName}` : "";
2365
+ const devHmrScript = options?.injectDevHmr === true ? `
2366
+ <script type="module">${buildPageReloadHmrScript()}
2367
+ <\/script>` : "";
2361
2368
  return `<!doctype html>
2362
2369
  <html lang="en">
2363
2370
  <head>
@@ -2381,7 +2388,7 @@ ${headExtras ? headExtras + "\n" : ""} <style>
2381
2388
  </style>
2382
2389
  </head>
2383
2390
  <body>
2384
- <div id="target">${ssrHtml}</div>
2391
+ <div id="target">${ssrHtml}</div>${devHmrScript}
2385
2392
  </body>
2386
2393
  </html>`;
2387
2394
  }
@@ -2762,9 +2769,18 @@ async function registerNpmPluginActions(packageName, pluginConfig, pluginDir, re
2762
2769
  } else {
2763
2770
  pluginModule = await import(packageName);
2764
2771
  }
2772
+ let toolsModule;
2773
+ const loadToolsModule = async () => {
2774
+ if (!toolsModule) {
2775
+ const toolsEntry = `${packageName}/tools`;
2776
+ toolsModule = viteServer ? await viteServer.ssrLoadModule(toolsEntry) : await import(toolsEntry);
2777
+ }
2778
+ return toolsModule;
2779
+ };
2765
2780
  for (const entry of pluginConfig.actions) {
2766
- const { name: actionName, action: actionPath } = normalizeActionEntry(entry);
2767
- const actionExport = pluginModule[actionName];
2781
+ const { name: actionName, action: actionPath, devOnly } = normalizeActionEntry(entry);
2782
+ const sourceModule = devOnly ? await loadToolsModule() : pluginModule;
2783
+ const actionExport = sourceModule[actionName];
2768
2784
  if (actionExport && isJayAction(actionExport)) {
2769
2785
  registry.register(actionExport);
2770
2786
  const registeredName = actionExport.actionName;
@@ -2836,6 +2852,13 @@ async function discoverPluginActions(pluginPath, projectRoot, registry = actionR
2836
2852
  return [];
2837
2853
  }
2838
2854
  }
2855
+ const resolveLocalToolsModulePath = () => {
2856
+ for (const candidate of ["tools.ts", "tools.js"]) {
2857
+ const candidatePath = path.join(pluginPath, candidate);
2858
+ if (fs.existsSync(candidatePath)) return candidatePath;
2859
+ }
2860
+ return null;
2861
+ };
2839
2862
  try {
2840
2863
  let pluginModule;
2841
2864
  if (viteServer) {
@@ -2843,9 +2866,23 @@ async function discoverPluginActions(pluginPath, projectRoot, registry = actionR
2843
2866
  } else {
2844
2867
  pluginModule = await import(modulePath);
2845
2868
  }
2869
+ let toolsModule;
2870
+ const loadToolsModule = async () => {
2871
+ if (toolsModule) return toolsModule;
2872
+ const toolsPath = resolveLocalToolsModulePath();
2873
+ if (!toolsPath) {
2874
+ getLogger().warn(
2875
+ `[Actions] Plugin "${pluginName}" declares a devOnly action but has no tools.ts/tools.js module`
2876
+ );
2877
+ return void 0;
2878
+ }
2879
+ toolsModule = viteServer ? await viteServer.ssrLoadModule(toolsPath) : await import(toolsPath);
2880
+ return toolsModule;
2881
+ };
2846
2882
  for (const entry of pluginConfig.actions) {
2847
- const { name: actionName, action: actionPath } = normalizeActionEntry(entry);
2848
- const actionExport = pluginModule[actionName];
2883
+ const { name: actionName, action: actionPath, devOnly } = normalizeActionEntry(entry);
2884
+ const sourceModule = devOnly ? await loadToolsModule() : pluginModule;
2885
+ const actionExport = sourceModule?.[actionName];
2849
2886
  if (actionExport && isJayAction(actionExport)) {
2850
2887
  registry.register(actionExport);
2851
2888
  const registeredName = actionExport.actionName;
@@ -4212,7 +4249,7 @@ async function scanPluginRoutes(projectRoot, projectRoutes) {
4212
4249
  continue;
4213
4250
  }
4214
4251
  const isLocalComponent = route.component.startsWith(".");
4215
- const compPath = isLocalComponent ? path__default.resolve(plugin.pluginPath, route.component) : resolvePluginModule(plugin);
4252
+ const compPath = isLocalComponent ? path__default.resolve(plugin.pluginPath, route.component) : resolvePluginModule(plugin, route.devOnly === true ? "./tools" : ".");
4216
4253
  const componentExport = isLocalComponent ? void 0 : route.component;
4217
4254
  pluginRoutes.push(
4218
4255
  createRoute(route.path, jayHtmlPath, compPath, componentExport, {
@@ -4254,12 +4291,12 @@ function resolvePluginExport(pluginPath, exportSubpath) {
4254
4291
  }
4255
4292
  return void 0;
4256
4293
  }
4257
- function resolvePluginModule(plugin) {
4294
+ function resolvePluginModule(plugin, exportKey = ".") {
4258
4295
  const pkgJsonPath = path__default.join(plugin.pluginPath, "package.json");
4259
4296
  if (fs__default$1.existsSync(pkgJsonPath)) {
4260
4297
  try {
4261
4298
  const pkg = JSON.parse(fs__default$1.readFileSync(pkgJsonPath, "utf-8"));
4262
- const mainExport = pkg.exports?.["."];
4299
+ const mainExport = pkg.exports?.[exportKey];
4263
4300
  const mainPath = typeof mainExport === "string" ? mainExport : mainExport?.default || mainExport?.import || pkg.main;
4264
4301
  if (mainPath) {
4265
4302
  const resolved = path__default.join(plugin.pluginPath, mainPath);
@@ -4376,6 +4413,7 @@ function mkRoute(route, vite, slowlyPhase, options, slowRenderCache, freezeStore
4376
4413
  pageParams,
4377
4414
  query["format"] === "fragment" ? "fragment" : "page",
4378
4415
  res,
4416
+ url,
4379
4417
  timing
4380
4418
  );
4381
4419
  return;
@@ -4582,9 +4620,7 @@ async function handlePreRenderRequest(vite, route, options, slowlyPhase, slowRen
4582
4620
  );
4583
4621
  if (renderedSlowly.kind !== "PhaseOutput") {
4584
4622
  timing?.recordSlowRender(Date.now() - slowStart);
4585
- if (renderedSlowly.kind === "ClientError") {
4586
- handleOtherResponseCodes(res, renderedSlowly);
4587
- }
4623
+ handleOtherResponseCodes(res, renderedSlowly);
4588
4624
  timing?.end();
4589
4625
  return;
4590
4626
  }
@@ -4694,9 +4730,7 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
4694
4730
  );
4695
4731
  if (renderedSlowly.kind !== "PhaseOutput") {
4696
4732
  timing?.recordSlowRender(Date.now() - slowStart);
4697
- if (renderedSlowly.kind === "ClientError") {
4698
- handleOtherResponseCodes(res, renderedSlowly);
4699
- }
4733
+ handleOtherResponseCodes(res, renderedSlowly);
4700
4734
  timing?.end();
4701
4735
  return;
4702
4736
  }
@@ -4828,7 +4862,7 @@ async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, page
4828
4862
  res.status(200).set({ "Content-Type": "text/html" }).send(compiledPageHtml);
4829
4863
  timing?.end();
4830
4864
  }
4831
- async function handleFrozenRequest(vite, route, options, freezeStore, slowRenderCache, freezeId, pageParams, format, res, timing) {
4865
+ async function handleFrozenRequest(vite, route, options, freezeStore, slowRenderCache, freezeId, pageParams, format, res, url, timing) {
4832
4866
  const entry = await freezeStore.get(freezeId);
4833
4867
  if (!entry) {
4834
4868
  getLogger().warn(`[Freeze] Freeze "${freezeId}" not found`);
@@ -4851,6 +4885,7 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
4851
4885
  sourceDir,
4852
4886
  JAY_IMPORT_RESOLVER
4853
4887
  );
4888
+ const injectDevHmr = format === "page";
4854
4889
  const html = await generateFrozenPageHtml(
4855
4890
  vite,
4856
4891
  fullJayHtml,
@@ -4863,13 +4898,19 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
4863
4898
  options.jayRollupConfig?.tsConfigFilePath,
4864
4899
  sourceDir,
4865
4900
  format,
4866
- entry.name
4901
+ entry.name,
4902
+ injectDevHmr ? { injectDevHmr: true } : void 0
4867
4903
  );
4868
4904
  const headers = { "Content-Type": "text/html" };
4869
4905
  if (format === "fragment") {
4870
4906
  headers["Access-Control-Allow-Origin"] = "*";
4871
4907
  }
4872
- res.status(200).set(headers).send(html);
4908
+ if (injectDevHmr) {
4909
+ const compiledHtml = await vite.transformIndexHtml(url || "/", html);
4910
+ res.status(200).set(headers).send(compiledHtml);
4911
+ } else {
4912
+ res.status(200).set(headers).send(html);
4913
+ }
4873
4914
  } catch (err) {
4874
4915
  getLogger().warn(`[Freeze] Failed to render frozen page: ${err.message}`);
4875
4916
  res.status(500).send(`Failed to render frozen page: ${err.message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/dev-server",
3
- "version": "0.24.2",
3
+ "version": "0.24.3",
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.24.2",
27
- "@jay-framework/compiler-shared": "^0.24.2",
28
- "@jay-framework/component": "^0.24.2",
29
- "@jay-framework/fullstack-component": "^0.24.2",
30
- "@jay-framework/logger": "^0.24.2",
31
- "@jay-framework/runtime": "^0.24.2",
32
- "@jay-framework/stack-client-runtime": "^0.24.2",
33
- "@jay-framework/stack-route-scanner": "^0.24.2",
34
- "@jay-framework/stack-server-build": "^0.24.2",
35
- "@jay-framework/stack-server-runtime": "^0.24.2",
36
- "@jay-framework/view-state-merge": "^0.24.2",
26
+ "@jay-framework/compiler-jay-stack": "^0.24.3",
27
+ "@jay-framework/compiler-shared": "^0.24.3",
28
+ "@jay-framework/component": "^0.24.3",
29
+ "@jay-framework/fullstack-component": "^0.24.3",
30
+ "@jay-framework/logger": "^0.24.3",
31
+ "@jay-framework/runtime": "^0.24.3",
32
+ "@jay-framework/stack-client-runtime": "^0.24.3",
33
+ "@jay-framework/stack-route-scanner": "^0.24.3",
34
+ "@jay-framework/stack-server-build": "^0.24.3",
35
+ "@jay-framework/stack-server-runtime": "^0.24.3",
36
+ "@jay-framework/view-state-merge": "^0.24.3",
37
37
  "busboy": "^1.6.0",
38
38
  "vite": "^5.0.11"
39
39
  },
40
40
  "devDependencies": {
41
- "@jay-framework/dev-environment": "^0.24.2",
42
- "@jay-framework/jay-cli": "^0.24.2",
43
- "@jay-framework/stack-client-runtime": "^0.24.2",
41
+ "@jay-framework/dev-environment": "^0.24.3",
42
+ "@jay-framework/jay-cli": "^0.24.3",
43
+ "@jay-framework/stack-client-runtime": "^0.24.3",
44
44
  "@playwright/test": "^1.58.2",
45
45
  "@types/busboy": "^1.5.4",
46
46
  "@types/express": "^5.0.2",