@jay-framework/dev-server 0.25.4 → 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.
Files changed (3) hide show
  1. package/dist/index.d.ts +57 -1
  2. package/dist/index.js +286 -65
  3. package/package.json +17 -17
package/dist/index.d.ts CHANGED
@@ -39,6 +39,19 @@ interface DevServerOptions {
39
39
  logLevel?: LogLevel;
40
40
  /** HTTP server for HMR WebSocket attachment (avoids default port 24678 collision) */
41
41
  httpServer?: Server;
42
+ /**
43
+ * Hosts the dev server's Vite host-check accepts, beyond localhost (DL#220). A list of hosts
44
+ * (Vite host-suffix syntax, e.g. `.example.dev`), or `true` to disable the check entirely — for
45
+ * cloud preview proxies. Merged with the `__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS` env var.
46
+ */
47
+ allowedHosts?: string[] | true;
48
+ /**
49
+ * Enable source-editing dev markers (DL#219). When true, the pre-render pipeline injects
50
+ * `jay-dev-src` / `jay-dev-item` attributes so the source-editing inspector can map a rendered
51
+ * pixel back to its jay-html source. Off by default — the markers change rendered output, so
52
+ * they are only emitted for AIditor / source-editing sessions.
53
+ */
54
+ sourceEditing?: boolean;
42
55
  }
43
56
 
44
57
  /**
@@ -173,6 +186,35 @@ declare class DevServerService {
173
186
  loadRouteParams(routePath: string): AsyncGenerator<Record<string, string>[]>;
174
187
  }
175
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;
176
218
  interface DevServerRoute {
177
219
  path: string;
178
220
  handler: RequestHandler;
@@ -277,7 +319,21 @@ interface CreateViteServerOptions {
277
319
  clearScreen?: boolean;
278
320
  /** HTTP server for HMR WebSocket (avoids default port 24678 collision) */
279
321
  httpServer?: Server;
322
+ /**
323
+ * Hosts Vite's dev-server host-check accepts, beyond localhost (DL#220). A list of hosts (Vite
324
+ * host-suffix syntax, e.g. `.example.dev`), or `true` to disable the check entirely. Merged with
325
+ * the `__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS` env var. `undefined`/empty → Vite's default.
326
+ */
327
+ allowedHosts?: string[] | true;
280
328
  }
329
+ /**
330
+ * Resolves Vite's `server.allowedHosts` from the `.jay` config value and the
331
+ * `__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS` env var (Vite's own convention — honored natively only in
332
+ * Vite 6, so the nested Vite 5.4 needs us to read it). Returns `true` (disable check) if either source
333
+ * says so, a de-duplicated merged list otherwise, or `undefined` when neither is set (Vite keeps its
334
+ * localhost-only default). (DL#220)
335
+ */
336
+ declare function resolveAllowedHosts(fromConfig: string[] | true | undefined, env: string | undefined): string[] | true | undefined;
281
337
  /**
282
338
  * Creates a Vite server configured for Jay Stack.
283
339
  *
@@ -297,4 +353,4 @@ declare function createViteForCli(options: {
297
353
  tsConfigFilePath?: string;
298
354
  }): Promise<ViteDevServer>;
299
355
 
300
- 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 };
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
@@ -7,15 +7,15 @@ import { createRequire } from "module";
7
7
  import "@jay-framework/compiler-shared";
8
8
  import * as path from "node:path";
9
9
  import path__default from "node:path";
10
- import { parseJayFile, JAY_IMPORT_RESOLVER, discoverHeadlessInstances, assignCoordinatesToJayHtml, parseAction, generateServerElementFile, parseContract, slowRenderTransform } from "@jay-framework/compiler-jay-html";
10
+ import { parseJayFile, JAY_IMPORT_RESOLVER, discoverHeadlessInstances, assignCoordinatesToJayHtml, parseAction, generateServerElementFile, noteExportedTypesFileChanged, injectDevMarkers, parseContract, slowRenderTransform } from "@jay-framework/compiler-jay-html";
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$1 from "node:fs";
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, parseCookies, renderFastChangingData, getClientInitData, slowRenderInstances, normalizeInstancePropNames, resolveErrorPageToken, buildErrorViewState } from "@jay-framework/stack-server-runtime";
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 fs__default from "node:fs/promises";
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(expr.name.text)) {
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
  }
@@ -1518,6 +1520,13 @@ function jayStackCompiler(options = {}) {
1518
1520
  function stripInlineActionBuilders(code, builderNames) {
1519
1521
  return transformJayStackBuilder(code, "action-strip.ts", "client", new Set(builderNames));
1520
1522
  }
1523
+ function resolveAllowedHosts(fromConfig, env) {
1524
+ if (fromConfig === true) return true;
1525
+ const envHosts = (env ?? "").split(",").map((host) => host.trim()).filter(Boolean);
1526
+ if (envHosts.includes("true")) return true;
1527
+ const merged = [...fromConfig ?? [], ...envHosts];
1528
+ return merged.length ? Array.from(new Set(merged)) : void 0;
1529
+ }
1521
1530
  async function createViteServer(options) {
1522
1531
  const {
1523
1532
  projectRoot,
@@ -1526,14 +1535,21 @@ async function createViteServer(options) {
1526
1535
  jayRollupConfig = { tsConfigFilePath: path__default.join(projectRoot, "tsconfig.json") },
1527
1536
  logLevel = "info",
1528
1537
  clearScreen = true,
1529
- httpServer
1538
+ httpServer,
1539
+ allowedHosts
1530
1540
  } = options;
1541
+ const resolvedAllowedHosts = resolveAllowedHosts(
1542
+ allowedHosts,
1543
+ process.env.__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS
1544
+ );
1531
1545
  const vite = await createServer({
1532
1546
  // Don't start HTTP server - we use middleware mode
1533
1547
  server: {
1534
1548
  middlewareMode: true,
1535
1549
  hmr: httpServer ? { server: httpServer } : void 0,
1536
- watch: { ignored: ["**/build/**"] }
1550
+ watch: { ignored: ["**/build/**"] },
1551
+ // Omit the key entirely when unset so Vite keeps its localhost-only default (DL#220).
1552
+ ...resolvedAllowedHosts !== void 0 && { allowedHosts: resolvedAllowedHosts }
1537
1553
  },
1538
1554
  // Use Jay Stack compiler for .jay-html and other custom transforms
1539
1555
  plugins: [
@@ -1623,7 +1639,7 @@ function resolveClientImportPath(route) {
1623
1639
  return route.compPath;
1624
1640
  }
1625
1641
  async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfig, options) {
1626
- const exists = await fs__default.access(route.compPath, fs__default.constants.F_OK).then(() => true).catch(() => false);
1642
+ const exists = await fs$1__default.access(route.compPath, fs$1__default.constants.F_OK).then(() => true).catch(() => false);
1627
1643
  const parts = [];
1628
1644
  const validations = [];
1629
1645
  if (exists) {
@@ -1643,7 +1659,7 @@ async function loadPageParts(vite, route, pagesBase, projectBase, jayRollupConfi
1643
1659
  }
1644
1660
  }
1645
1661
  const jayHtmlFilePath = options?.preRenderedPath ?? route.jayHtmlPath;
1646
- const jayHtmlSource = options?.preRenderedContent ?? (await fs__default.readFile(jayHtmlFilePath)).toString();
1662
+ const jayHtmlSource = options?.preRenderedContent ?? (await fs$1__default.readFile(jayHtmlFilePath)).toString();
1647
1663
  const fileName = path__default.basename(route.jayHtmlPath);
1648
1664
  const dirName = path__default.dirname(route.jayHtmlPath);
1649
1665
  const jayHtmlWithValidations = await parseJayFile(
@@ -2018,8 +2034,9 @@ function buildPageReloadHmrScript() {
2018
2034
  });
2019
2035
  }`;
2020
2036
  }
2021
- function buildFreezeScript(routePattern) {
2037
+ function buildFreezeScript(routePattern, sourceFile) {
2022
2038
  const routePatternLiteral = routePattern ? `'${routePattern}'` : "undefined";
2039
+ const sourceFileLiteral = sourceFile ? JSON.stringify(sourceFile) : "undefined";
2023
2040
  return `
2024
2041
  // Page Freeze (DL#127, DL#128 iframe addendum)
2025
2042
  // Sticky embed mode: URL param sets a session cookie so in-iframe navigation preserves it
@@ -2074,13 +2091,152 @@ function buildFreezeScript(routePattern) {
2074
2091
  }
2075
2092
  }
2076
2093
 
2094
+ // Source-editing inspector (DL#219). Resolves a viewport point/rect to the jay-dev-* source
2095
+ // markers emitted when the dev server runs with sourceEditing on. Harmless without markers —
2096
+ // it simply finds no jay-dev-src and replies node:null. Reply carries source LOCATORS (line
2097
+ // ranges + route) plus runtime identities (forEach record id, region name + static props);
2098
+ // the agent reads bound expressions / collection / if-conditions from the jay-html itself.
2099
+ function __jayParseLines(s) {
2100
+ if (!s) return null;
2101
+ const parts = s.split(':');
2102
+ return { from: parseInt(parts[0], 10), to: parseInt(parts[1], 10) };
2103
+ }
2104
+ function __jayLines(el) {
2105
+ return __jayParseLines(el.getAttribute('jay-dev-src'));
2106
+ }
2107
+ // A significant enclosing frame: a forEach item root or a region boundary. Returns null for
2108
+ // plain wrapper elements (the agent reconstructs those from source via node.lines).
2109
+ function __jayFrame(el) {
2110
+ const item = el.getAttribute('jay-dev-item');
2111
+ if (item) return { kind: 'forEach', lines: __jayLines(el), itemId: item };
2112
+ const region = el.getAttribute('jay-dev-region');
2113
+ if (region) {
2114
+ // Region lines live in jay-dev-region-src (the <jay:…> tag's range), distinct from the
2115
+ // root element's own jay-dev-src.
2116
+ const frame = { kind: 'region', lines: __jayParseLines(el.getAttribute('jay-dev-region-src')), name: region };
2117
+ const rawProps = el.getAttribute('jay-dev-region-props');
2118
+ if (rawProps) { try { frame.props = JSON.parse(decodeURIComponent(rawProps)); } catch (e) {} }
2119
+ return frame;
2120
+ }
2121
+ return null;
2122
+ }
2123
+ // One-level HTML of an element: its open tag (authored attrs only, jay-* stripped), its direct
2124
+ // children shown as empty tags (grandchildren elided with …), and its text — so the agent sees
2125
+ // exactly what was clicked inside generated content without the whole subtree.
2126
+ function __jayOneLevelHtml(el) {
2127
+ if (!el || !el.tagName) return '';
2128
+ const tag = el.tagName.toLowerCase();
2129
+ let attrs = '';
2130
+ for (let i = 0; i < el.attributes.length; i++) {
2131
+ const a = el.attributes[i];
2132
+ if (a.name.indexOf('jay-') === 0) continue; // strip jay-dev-* / jay-coordinate
2133
+ attrs += ' ' + a.name + '="' + a.value + '"';
2134
+ }
2135
+ let inner = '';
2136
+ const kids = el.childNodes || [];
2137
+ for (let i = 0; i < kids.length; i++) {
2138
+ const c = kids[i];
2139
+ if (c.nodeType === 3) inner += (c.textContent || '');
2140
+ else if (c.nodeType === 1) {
2141
+ const ct = c.tagName.toLowerCase();
2142
+ inner += '<' + ct + '>' + (c.childNodes && c.childNodes.length ? '…' : '') + '</' + ct + '>';
2143
+ }
2144
+ }
2145
+ if (inner.length > 300) inner = inner.slice(0, 300) + '…';
2146
+ return '<' + tag + attrs + '>' + inner + '</' + tag + '>';
2147
+ }
2148
+ function __jayResolveElement(el) {
2149
+ if (!el) return null;
2150
+ // Walk el up to (but excluding) <body>.
2151
+ const entries = [];
2152
+ let cur = el;
2153
+ while (cur && cur.nodeType === 1 && cur.tagName && cur.tagName.toLowerCase() !== 'body') {
2154
+ entries.push(cur);
2155
+ cur = cur.parentElement;
2156
+ }
2157
+ // Source anchor = nearest element at/above el carrying a source marker (its line range).
2158
+ let sourceEl = null;
2159
+ for (let i = 0; i < entries.length; i++) {
2160
+ if (entries[i].getAttribute('jay-dev-src')) { sourceEl = entries[i]; break; }
2161
+ }
2162
+ if (!sourceEl) return null;
2163
+ // Stack = only the significant enclosing frames (forEach + region), innermost → outermost.
2164
+ const stack = [];
2165
+ for (let i = 0; i < entries.length; i++) {
2166
+ const f = __jayFrame(entries[i]);
2167
+ if (f) stack.push(f);
2168
+ }
2169
+ // node describes the ACTUAL element el (what the pointer hit / the rect chose). html — a
2170
+ // one-level rendering (open tag with authored attrs, direct children as empty tags, inline
2171
+ // text; grandchildren + long text elided) — is the single content field: it carries the tag,
2172
+ // attributes (src/href/value), and value, bounded in size. lines come from the source anchor;
2173
+ // for bound/generated content (an html-string value) el has no jay-dev-src of its own, so
2174
+ // lines point to the ENCLOSING binding (the editable source) and contentFromBinding flags it.
2175
+ const r = el.getBoundingClientRect();
2176
+ const node = {
2177
+ lines: __jayLines(sourceEl),
2178
+ tag: el.tagName ? el.tagName.toLowerCase() : '',
2179
+ html: __jayOneLevelHtml(el),
2180
+ rect: { x: r.x, y: r.y, width: r.width, height: r.height },
2181
+ };
2182
+ const childEls = Array.prototype.slice.call(el.children || []);
2183
+ const childrenGenerated =
2184
+ childEls.length > 0 && childEls.every((c) => !c.getAttribute('jay-dev-src'));
2185
+ if (!el.getAttribute('jay-dev-src') || childrenGenerated) {
2186
+ node.contentFromBinding = true;
2187
+ }
2188
+ return { node, stack };
2189
+ }
2190
+ function __jayInspectPoint(x, y) {
2191
+ return __jayResolveElement(document.elementFromPoint(x, y));
2192
+ }
2193
+ function __jayInspectRect(x, y, w, h) {
2194
+ const sel = { left: x, top: y, right: x + w, bottom: y + h };
2195
+ const marked = Array.prototype.slice.call(document.querySelectorAll('[jay-dev-src]'));
2196
+ let best = null, bestArea = -1;
2197
+ for (let i = 0; i < marked.length; i++) {
2198
+ const el = marked[i];
2199
+ const r = el.getBoundingClientRect();
2200
+ const elArea = r.width * r.height;
2201
+ if (elArea <= 0) continue;
2202
+ const ix = Math.max(0, Math.min(sel.right, r.right) - Math.max(sel.left, r.left));
2203
+ const iy = Math.max(0, Math.min(sel.bottom, r.bottom) - Math.max(sel.top, r.top));
2204
+ // Rect rule (DL#219): keep elements the box mostly encloses (overlap over the ELEMENT's
2205
+ // own area >= 0.8), then pick the LARGEST — the element the box was drawn around. A tight
2206
+ // box only clears the threshold for the small element; a big box clears it for the
2207
+ // container too, and largest-area returns the container (not its first child).
2208
+ if ((ix * iy) / elArea >= 0.8 && elArea > bestArea) {
2209
+ bestArea = elArea;
2210
+ best = el;
2211
+ }
2212
+ }
2213
+ if (best) return __jayResolveElement(best);
2214
+ return __jayInspectPoint(x + w / 2, y + h / 2);
2215
+ }
2216
+
2077
2217
  if (__jayEmbedMode) {
2078
2218
  // Notify parent of the current route on load (DL#128 route addendum)
2079
2219
  window.parent.postMessage({ type: 'jay:route', route: window.location.pathname, routePattern: ${routePatternLiteral} }, '*');
2080
2220
 
2081
- // Embed mode: parent triggers freeze via postMessage
2221
+ // Embed mode: parent triggers freeze / inspect via postMessage
2082
2222
  window.addEventListener('message', (e) => {
2083
- if (e.data?.type === 'jay:requestFreeze') __jayDoFreeze();
2223
+ const d = e.data;
2224
+ if (!d) return;
2225
+ if (d.type === 'jay:requestFreeze') { __jayDoFreeze(); return; }
2226
+ if (d.type === 'jay:inspectPoint' || d.type === 'jay:inspectRect') {
2227
+ const result = d.type === 'jay:inspectPoint'
2228
+ ? __jayInspectPoint(d.x, d.y)
2229
+ : __jayInspectRect(d.x, d.y, d.width, d.height);
2230
+ window.parent.postMessage({
2231
+ type: 'jay:inspectResult',
2232
+ requestId: d.requestId,
2233
+ file: ${sourceFileLiteral},
2234
+ route: window.location.pathname,
2235
+ routePattern: ${routePatternLiteral},
2236
+ node: result ? result.node : null, // node.rect is the matched element's on-screen box
2237
+ stack: result ? result.stack : [],
2238
+ }, '*');
2239
+ }
2084
2240
  });
2085
2241
  } else {
2086
2242
  // Standalone: Alt+S / Option+S keyboard shortcut
@@ -2105,7 +2261,7 @@ function buildAutomationWrap(options, mode) {
2105
2261
  }
2106
2262
  const appendLine = appendDom ? `
2107
2263
  target.appendChild(wrapped.element.dom);` : "";
2108
- const freezeScript = buildFreezeScript(options.routePattern);
2264
+ const freezeScript = buildFreezeScript(options.routePattern, options.sourceFile);
2109
2265
  if (hasSlowViewState) {
2110
2266
  return `
2111
2267
  // Wrap with automation for dev tooling
@@ -2358,7 +2514,7 @@ async function generateFrozenPageHtml(vite, jayHtmlContent, jayHtmlFilename, jay
2358
2514
  if (cached.cssHref) {
2359
2515
  try {
2360
2516
  const cssPath = cached.cssHref.replace(/^\/@fs/, "").replace(/\?.*$/, "");
2361
- const cssContent = await fs__default.readFile(cssPath, "utf-8");
2517
+ const cssContent = await fs$1__default.readFile(cssPath, "utf-8");
2362
2518
  inlineCss = `<style>${cssContent}</style>`;
2363
2519
  } catch {
2364
2520
  inlineCss = `<link rel="stylesheet" href="${cached.cssHref}" />`;
@@ -2437,11 +2593,11 @@ async function compileAndLoadServerElement(vite, jayHtmlContent, jayHtmlFilename
2437
2593
  generateServerElementFile(parsedJayFile, serverElementOptions)
2438
2594
  );
2439
2595
  const serverElementDir = path__default.join(buildFolder, "pre-rendered", routeDir);
2440
- await fs__default.mkdir(serverElementDir, { recursive: true });
2596
+ await fs$1__default.mkdir(serverElementDir, { recursive: true });
2441
2597
  const adjustedCode = rebaseRelativeImports(serverElementCode, jayHtmlDir, serverElementDir);
2442
2598
  const serverElementFilename = jayHtmlFilename.replace(".jay-html", ".server-element.ts");
2443
2599
  const serverElementPath = path__default.join(serverElementDir, serverElementFilename);
2444
- await fs__default.writeFile(serverElementPath, adjustedCode, "utf-8");
2600
+ await fs$1__default.writeFile(serverElementPath, adjustedCode, "utf-8");
2445
2601
  const existingModule = vite.moduleGraph.getModuleById(serverElementPath);
2446
2602
  if (existingModule) {
2447
2603
  vite.moduleGraph.invalidateModule(existingModule);
@@ -2453,7 +2609,7 @@ async function compileAndLoadServerElement(vite, jayHtmlContent, jayHtmlFilename
2453
2609
  if (parsedJayFile.css) {
2454
2610
  const cssFilename = jayHtmlFilename.replace(".jay-html", ".css");
2455
2611
  const cssPath = path__default.join(serverElementDir, cssFilename);
2456
- await fs__default.writeFile(cssPath, parsedJayFile.css, "utf-8");
2612
+ await fs$1__default.writeFile(cssPath, parsedJayFile.css, "utf-8");
2457
2613
  const cssModules = vite.moduleGraph.getModulesByFile(cssPath);
2458
2614
  if (cssModules) {
2459
2615
  for (const mod of cssModules) {
@@ -3530,7 +3686,7 @@ class SlowRenderCache {
3530
3686
  const preRenderedPath = this.computeCachePath(jayHtmlPath, params, routeDir);
3531
3687
  let fileContent;
3532
3688
  try {
3533
- fileContent = await fs__default.readFile(preRenderedPath, "utf-8");
3689
+ fileContent = await fs$1__default.readFile(preRenderedPath, "utf-8");
3534
3690
  } catch {
3535
3691
  return void 0;
3536
3692
  }
@@ -3558,8 +3714,8 @@ class SlowRenderCache {
3558
3714
  carryForward,
3559
3715
  jayHtmlPath
3560
3716
  );
3561
- await fs__default.mkdir(path__default.dirname(preRenderedPath), { recursive: true });
3562
- await fs__default.writeFile(preRenderedPath, fileContent, "utf-8");
3717
+ await fs$1__default.mkdir(path__default.dirname(preRenderedPath), { recursive: true });
3718
+ await fs$1__default.writeFile(preRenderedPath, fileContent, "utf-8");
3563
3719
  this.trackFile(jayHtmlPath, preRenderedPath);
3564
3720
  return {
3565
3721
  preRenderedPath,
@@ -3575,7 +3731,7 @@ class SlowRenderCache {
3575
3731
  async has(jayHtmlPath, params, routeDir) {
3576
3732
  const preRenderedPath = this.computeCachePath(jayHtmlPath, params, routeDir);
3577
3733
  try {
3578
- await fs__default.access(preRenderedPath);
3734
+ await fs$1__default.access(preRenderedPath);
3579
3735
  return true;
3580
3736
  } catch {
3581
3737
  return false;
@@ -3590,7 +3746,7 @@ class SlowRenderCache {
3590
3746
  if (files) {
3591
3747
  for (const filePath of files) {
3592
3748
  try {
3593
- await fs__default.unlink(filePath);
3749
+ await fs$1__default.unlink(filePath);
3594
3750
  } catch {
3595
3751
  }
3596
3752
  }
@@ -3627,14 +3783,14 @@ class SlowRenderCache {
3627
3783
  for (const files of this.pathToFiles.values()) {
3628
3784
  for (const filePath of files) {
3629
3785
  try {
3630
- await fs__default.unlink(filePath);
3786
+ await fs$1__default.unlink(filePath);
3631
3787
  } catch {
3632
3788
  }
3633
3789
  }
3634
3790
  }
3635
3791
  this.pathToFiles.clear();
3636
3792
  try {
3637
- await fs__default.rm(this.cacheDir, { recursive: true, force: true });
3793
+ await fs$1__default.rm(this.cacheDir, { recursive: true, force: true });
3638
3794
  } catch {
3639
3795
  }
3640
3796
  }
@@ -3685,11 +3841,11 @@ class SlowRenderCache {
3685
3841
  const basename = path__default.basename(jayHtmlPath, ".jay-html");
3686
3842
  const cacheSubDir = path__default.join(this.cacheDir, dir);
3687
3843
  try {
3688
- const files = await fs__default.readdir(cacheSubDir);
3844
+ const files = await fs$1__default.readdir(cacheSubDir);
3689
3845
  for (const file of files) {
3690
3846
  if (file.startsWith(basename)) {
3691
3847
  try {
3692
- await fs__default.unlink(path__default.join(cacheSubDir, file));
3848
+ await fs$1__default.unlink(path__default.join(cacheSubDir, file));
3693
3849
  } catch {
3694
3850
  }
3695
3851
  }
@@ -4005,6 +4161,10 @@ function createActionRouter(options) {
4005
4161
  });
4006
4162
  return;
4007
4163
  }
4164
+ if (isRejectedCrossOrigin(action, req)) {
4165
+ res.status(403).json(crossOriginErrorResponse(actionName));
4166
+ return;
4167
+ }
4008
4168
  let input;
4009
4169
  try {
4010
4170
  if (requestMethod === "GET") {
@@ -4036,11 +4196,15 @@ function createActionRouter(options) {
4036
4196
  const cleanup = () => {
4037
4197
  if (tempDir) cleanupTempDir(tempDir);
4038
4198
  };
4199
+ const incoming = action.needsRequest ? readIncomingRequest(req) : void 0;
4200
+ if (action.needsRequest) {
4201
+ res.set("Cache-Control", registry.getCacheHeaders(actionName));
4202
+ }
4039
4203
  if (registry.isStreaming(actionName)) {
4040
4204
  res.setHeader("Content-Type", "application/x-ndjson");
4041
4205
  res.setHeader("Transfer-Encoding", "chunked");
4042
4206
  try {
4043
- const generator = registry.executeStream(actionName, input);
4207
+ const generator = registry.executeStream(actionName, input, incoming);
4044
4208
  for await (const chunk of generator) {
4045
4209
  res.write(JSON.stringify({ chunk }) + "\n");
4046
4210
  }
@@ -4053,7 +4217,7 @@ function createActionRouter(options) {
4053
4217
  timing?.end();
4054
4218
  return;
4055
4219
  }
4056
- const result = await registry.execute(actionName, input);
4220
+ const result = await registry.execute(actionName, input, incoming);
4057
4221
  cleanup();
4058
4222
  if (requestMethod === "GET" && result.success) {
4059
4223
  const cacheHeaders = registry.getCacheHeaders(actionName);
@@ -4062,6 +4226,9 @@ function createActionRouter(options) {
4062
4226
  }
4063
4227
  }
4064
4228
  if (result.success) {
4229
+ for (const setCookie of result.setCookies ?? []) {
4230
+ res.append("Set-Cookie", setCookie);
4231
+ }
4065
4232
  res.status(200).json({
4066
4233
  success: true,
4067
4234
  data: result.data
@@ -4076,6 +4243,19 @@ function createActionRouter(options) {
4076
4243
  timing?.end();
4077
4244
  };
4078
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
+ }
4079
4259
  function getStatusCodeForError(code, isActionError) {
4080
4260
  if (isActionError) {
4081
4261
  return 422;
@@ -4206,6 +4386,11 @@ function actionBodyParser(options) {
4206
4386
  next();
4207
4387
  return;
4208
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
+ }
4209
4394
  const contentType = req.headers["content-type"] || "";
4210
4395
  if (contentType.startsWith("multipart/form-data")) {
4211
4396
  const actionName = req.path.slice(ACTION_ENDPOINT_BASE.length + 1);
@@ -4402,6 +4587,30 @@ class DevServerService {
4402
4587
  yield* runLoadParams(loaded.val.parts);
4403
4588
  }
4404
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
+ }
4405
4614
  let _watchLinkedFiles = () => {
4406
4615
  };
4407
4616
  async function initRoutes(pagesBaseFolder) {
@@ -4469,7 +4678,7 @@ function resolvePluginExport(pluginPath, exportSubpath) {
4469
4678
  const normalized = exportSubpath.replace(/^\.\//, "");
4470
4679
  const packageJsonPath = path__default.join(pluginPath, "package.json");
4471
4680
  try {
4472
- const packageJson = JSON.parse(fs__default$1.readFileSync(packageJsonPath, "utf-8"));
4681
+ const packageJson = JSON.parse(fs__default.readFileSync(packageJsonPath, "utf-8"));
4473
4682
  if (packageJson.exports) {
4474
4683
  const exportKey = "./" + normalized;
4475
4684
  const exportValue = packageJson.exports[exportKey];
@@ -4486,7 +4695,7 @@ function resolvePluginExport(pluginPath, exportSubpath) {
4486
4695
  for (const dir of ["dist", "lib", ""]) {
4487
4696
  const candidate = path__default.join(pluginPath, dir, normalized);
4488
4697
  try {
4489
- fs__default$1.accessSync(candidate);
4698
+ fs__default.accessSync(candidate);
4490
4699
  return candidate;
4491
4700
  } catch {
4492
4701
  }
@@ -4495,14 +4704,14 @@ function resolvePluginExport(pluginPath, exportSubpath) {
4495
4704
  }
4496
4705
  function resolvePluginModule(plugin, exportKey = ".") {
4497
4706
  const pkgJsonPath = path__default.join(plugin.pluginPath, "package.json");
4498
- if (fs__default$1.existsSync(pkgJsonPath)) {
4707
+ if (fs__default.existsSync(pkgJsonPath)) {
4499
4708
  try {
4500
- const pkg = JSON.parse(fs__default$1.readFileSync(pkgJsonPath, "utf-8"));
4709
+ const pkg = JSON.parse(fs__default.readFileSync(pkgJsonPath, "utf-8"));
4501
4710
  const mainExport = pkg.exports?.[exportKey];
4502
4711
  const mainPath = typeof mainExport === "string" ? mainExport : mainExport?.default || mainExport?.import || pkg.main;
4503
4712
  if (mainPath) {
4504
4713
  const resolved = path__default.join(plugin.pluginPath, mainPath);
4505
- if (fs__default$1.existsSync(resolved)) return resolved;
4714
+ if (fs__default.existsSync(resolved)) return resolved;
4506
4715
  }
4507
4716
  } catch {
4508
4717
  }
@@ -4511,7 +4720,7 @@ function resolvePluginModule(plugin, exportKey = ".") {
4511
4720
  for (const ext of [".ts", ".js", "/index.ts", "/index.js"]) {
4512
4721
  const candidate = path__default.join(plugin.pluginPath, modulePath + ext);
4513
4722
  try {
4514
- fs__default$1.accessSync(candidate);
4723
+ fs__default.accessSync(candidate);
4515
4724
  return candidate;
4516
4725
  } catch {
4517
4726
  }
@@ -4519,7 +4728,7 @@ function resolvePluginModule(plugin, exportKey = ".") {
4519
4728
  for (const ext of [".ts", ".js"]) {
4520
4729
  const candidate = path__default.join(plugin.pluginPath, "lib", path__default.basename(modulePath) + ext);
4521
4730
  try {
4522
- fs__default$1.accessSync(candidate);
4731
+ fs__default.accessSync(candidate);
4523
4732
  return candidate;
4524
4733
  } catch {
4525
4734
  }
@@ -4547,7 +4756,9 @@ function defaults(options) {
4547
4756
  pagesRoot: pagesRootFolder,
4548
4757
  buildFolder
4549
4758
  },
4550
- httpServer: options.httpServer
4759
+ httpServer: options.httpServer,
4760
+ allowedHosts: options.allowedHosts,
4761
+ sourceEditing: options.sourceEditing
4551
4762
  };
4552
4763
  }
4553
4764
  let _renderDevErrorPage = async (res, info) => {
@@ -4908,7 +5119,8 @@ async function handlePreRenderRequest(vite, route, options, slowlyPhase, slowRen
4908
5119
  initialPartsResult.val.headlessInstanceComponents,
4909
5120
  partKeys,
4910
5121
  pageParams,
4911
- pageProps
5122
+ pageProps,
5123
+ options.sourceEditing
4912
5124
  );
4913
5125
  timing?.recordSlowRender(Date.now() - slowStart);
4914
5126
  if (!preRenderResult) {
@@ -5056,26 +5268,26 @@ async function handleClientOnlyRequest(vite, route, options, slowlyPhase, pagePa
5056
5268
  pluginsForPage,
5057
5269
  {
5058
5270
  enableAutomation: !options.disableAutomation,
5059
- routePattern: routeToExpressRoute(route)
5271
+ routePattern: routeToExpressRoute(route),
5272
+ sourceFile: path__default.relative(options.projectRootFolder, route.jayHtmlPath)
5060
5273
  }
5061
5274
  );
5062
- if (options.buildFolder) {
5063
- const pageName = !url || url === "/" ? "index" : url.replace(/^\//, "").replace(/\//g, "-");
5064
- const clientScriptDir = path__default.join(options.buildFolder, "debug", "client-entry");
5065
- await fs__default.mkdir(clientScriptDir, { recursive: true });
5066
- await fs__default.writeFile(path__default.join(clientScriptDir, `${pageName}.html`), pageHtml, "utf-8");
5067
- }
5275
+ await writeDebugPage(options, url, pageHtml);
5068
5276
  const viteStart = Date.now();
5069
- const compiledPageHtml = await vite.transformIndexHtml(!!url ? url : "/", pageHtml);
5277
+ const compiledPageHtml = encodeBracketsInAssetUrls(
5278
+ await vite.transformIndexHtml(url?.split("?")[0] || "/", pageHtml)
5279
+ );
5070
5280
  timing?.recordViteClient(Date.now() - viteStart);
5071
5281
  res.status(200).set({ "Content-Type": "text/html" }).send(compiledPageHtml);
5072
5282
  timing?.end();
5073
5283
  }
5074
5284
  async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, pageParts, viewState, carryForward, clientTrackByMap, projectInit, pluginsForPage, options, routePattern, routeDir, slowViewState, timing, preLoadedContent, headTags, scripts, statusCode = 200) {
5075
5285
  let pageHtml;
5286
+ const sourceFile = path__default.relative(options.projectRootFolder, sourceJayHtmlPath);
5076
5287
  try {
5077
5288
  const jayHtmlDir = path__default.dirname(jayHtmlPath);
5078
- const jayHtmlContent = preLoadedContent ?? await fs__default.readFile(jayHtmlPath, "utf-8");
5289
+ const rawContent = preLoadedContent ?? await fs$1__default.readFile(jayHtmlPath, "utf-8");
5290
+ const jayHtmlContent = options.sourceEditing ? injectDevMarkers(rawContent) : rawContent;
5079
5291
  pageHtml = await generateSSRPageHtml(
5080
5292
  vite,
5081
5293
  jayHtmlContent,
@@ -5096,7 +5308,8 @@ async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, page
5096
5308
  {
5097
5309
  enableAutomation: !options.disableAutomation,
5098
5310
  slowViewState,
5099
- routePattern
5311
+ routePattern,
5312
+ sourceFile
5100
5313
  },
5101
5314
  void 0,
5102
5315
  headTags,
@@ -5116,23 +5329,21 @@ async function sendResponse(vite, res, url, jayHtmlPath, sourceJayHtmlPath, page
5116
5329
  {
5117
5330
  enableAutomation: !options.disableAutomation,
5118
5331
  slowViewState,
5119
- routePattern
5332
+ routePattern,
5333
+ sourceFile
5120
5334
  }
5121
5335
  );
5122
5336
  }
5123
- if (options.buildFolder) {
5124
- const pageName = !url || url === "/" ? "index" : url.replace(/^\//, "").replace(/\//g, "-");
5125
- const clientScriptDir = path__default.join(options.buildFolder, "debug", "client-entry");
5126
- await fs__default.mkdir(clientScriptDir, { recursive: true });
5127
- await fs__default.writeFile(path__default.join(clientScriptDir, `${pageName}.html`), pageHtml, "utf-8");
5128
- }
5337
+ await writeDebugPage(options, url, pageHtml);
5129
5338
  for (const [id, mod] of vite.moduleGraph.idToModuleMap) {
5130
5339
  if (id.includes("html-proxy")) {
5131
5340
  vite.moduleGraph.invalidateModule(mod);
5132
5341
  }
5133
5342
  }
5134
5343
  const viteStart = Date.now();
5135
- const compiledPageHtml = await vite.transformIndexHtml(!!url ? url : "/", pageHtml);
5344
+ const compiledPageHtml = encodeBracketsInAssetUrls(
5345
+ await vite.transformIndexHtml(url?.split("?")[0] || "/", pageHtml)
5346
+ );
5136
5347
  timing?.recordViteClient(Date.now() - viteStart);
5137
5348
  res.status(statusCode).set({ "Content-Type": "text/html" }).send(compiledPageHtml);
5138
5349
  timing?.end();
@@ -5151,7 +5362,7 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
5151
5362
  const routeDir = getRouteDir(route);
5152
5363
  const cachedEntry = await slowRenderCache.get(route.jayHtmlPath, pageParams, routeDir);
5153
5364
  const jayHtmlPath = cachedEntry?.preRenderedPath ?? route.jayHtmlPath;
5154
- const jayHtmlContent = cachedEntry?.preRenderedContent ?? await fs__default.readFile(jayHtmlPath, "utf-8");
5365
+ const jayHtmlContent = cachedEntry?.preRenderedContent ?? await fs$1__default.readFile(jayHtmlPath, "utf-8");
5155
5366
  const jayHtmlFilename = path__default.basename(jayHtmlPath);
5156
5367
  const jayHtmlDir = path__default.dirname(jayHtmlPath);
5157
5368
  const sourceDir = path__default.dirname(route.jayHtmlPath);
@@ -5176,7 +5387,9 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
5176
5387
  headers["Access-Control-Allow-Origin"] = "*";
5177
5388
  }
5178
5389
  if (injectDevHmr) {
5179
- const compiledHtml = await vite.transformIndexHtml(url || "/", html);
5390
+ const compiledHtml = encodeBracketsInAssetUrls(
5391
+ await vite.transformIndexHtml(url?.split("?")[0] || "/", html)
5392
+ );
5180
5393
  res.status(200).set(headers).send(compiledHtml);
5181
5394
  } else {
5182
5395
  res.status(200).set(headers).send(html);
@@ -5187,13 +5400,14 @@ async function handleFrozenRequest(vite, route, options, freezeStore, slowRender
5187
5400
  }
5188
5401
  timing?.end();
5189
5402
  }
5190
- async function preRenderJayHtml(route, slowViewState, headlessContracts, headlessInstanceComponents, partKeys = [], pageParams = {}, pageProps = { language: "en", url: "" }) {
5191
- const jayHtmlWithTemplates = await fs__default.readFile(route.jayHtmlPath, "utf-8");
5403
+ async function preRenderJayHtml(route, slowViewState, headlessContracts, headlessInstanceComponents, partKeys = [], pageParams = {}, pageProps = { language: "en", url: "" }, sourceEditing = false) {
5404
+ const rawJayHtml = await fs$1__default.readFile(route.jayHtmlPath, "utf-8");
5405
+ const jayHtmlWithTemplates = sourceEditing ? injectDevMarkers(rawJayHtml) : rawJayHtml;
5192
5406
  const sourceDir = path__default.dirname(route.jayHtmlPath);
5193
5407
  let contract;
5194
5408
  const contractPath = route.jayHtmlPath.replace(".jay-html", ".jay-contract");
5195
5409
  try {
5196
- const contractContent = await fs__default.readFile(contractPath, "utf-8");
5410
+ const contractContent = await fs$1__default.readFile(contractPath, "utf-8");
5197
5411
  const parseResult = parseContract(contractContent, path__default.basename(contractPath));
5198
5412
  if (parseResult.val) contract = parseResult.val;
5199
5413
  } catch {
@@ -5290,10 +5504,10 @@ async function mkDevServer(rawOptions) {
5290
5504
  const { publicBaseUrlPath, pagesRootFolder, projectRootFolder, buildFolder, jayRollupConfig } = options;
5291
5505
  if (buildFolder) {
5292
5506
  try {
5293
- const entries = await fs__default.readdir(buildFolder).catch(() => []);
5507
+ const entries = await fs$1__default.readdir(buildFolder).catch(() => []);
5294
5508
  for (const entry of entries) {
5295
5509
  if (entry === "freezes") continue;
5296
- await fs__default.rm(path__default.join(buildFolder, entry), { recursive: true, force: true });
5510
+ await fs$1__default.rm(path__default.join(buildFolder, entry), { recursive: true, force: true });
5297
5511
  }
5298
5512
  } catch {
5299
5513
  }
@@ -5307,7 +5521,8 @@ async function mkDevServer(rawOptions) {
5307
5521
  base: publicBaseUrlPath,
5308
5522
  jayRollupConfig,
5309
5523
  logLevel: viteLogLevel,
5310
- httpServer: options.httpServer
5524
+ httpServer: options.httpServer,
5525
+ allowedHosts: options.allowedHosts
5311
5526
  });
5312
5527
  lifecycleManager.setViteServer(vite);
5313
5528
  await lifecycleManager.initialize();
@@ -5369,7 +5584,7 @@ async function mkDevServer(rawOptions) {
5369
5584
  for (let i = devServerRoutes.length - 1; i >= 0; i--) {
5370
5585
  const route = devServerRoutes[i];
5371
5586
  const fsPath = route.fsRoute.jayHtmlPath;
5372
- const stillOnDisk = scannedRawRoutes.has(route.fsRoute.rawRoute) && fs__default$1.existsSync(fsPath);
5587
+ const stillOnDisk = scannedRawRoutes.has(route.fsRoute.rawRoute) && fs__default.existsSync(fsPath);
5373
5588
  if (!stillOnDisk) {
5374
5589
  devServerRoutes.splice(i, 1);
5375
5590
  }
@@ -5529,6 +5744,9 @@ function setupSlowRenderCacheInvalidation(vite, cache, pagesRootFolder, projectR
5529
5744
  }
5530
5745
  };
5531
5746
  vite.watcher.on("change", (changedPath) => {
5747
+ if (/\.(ts|tsx|jay-contract)$/.test(changedPath)) {
5748
+ noteExportedTypesFileChanged(changedPath);
5749
+ }
5532
5750
  if (watchedFiles.has(changedPath)) {
5533
5751
  clearServerElementCache();
5534
5752
  cache.clear().then(() => {
@@ -5596,5 +5814,8 @@ export {
5596
5814
  createActionRouter,
5597
5815
  createViteForCli,
5598
5816
  createViteServer,
5599
- mkDevServer
5817
+ debugPageName,
5818
+ encodeBracketsInAssetUrls,
5819
+ mkDevServer,
5820
+ resolveAllowedHosts
5600
5821
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/dev-server",
3
- "version": "0.25.4",
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.25.4",
27
- "@jay-framework/compiler-shared": "^0.25.4",
28
- "@jay-framework/component": "^0.25.4",
29
- "@jay-framework/fullstack-component": "^0.25.4",
30
- "@jay-framework/logger": "^0.25.4",
31
- "@jay-framework/runtime": "^0.25.4",
32
- "@jay-framework/stack-client-runtime": "^0.25.4",
33
- "@jay-framework/stack-route-scanner": "^0.25.4",
34
- "@jay-framework/stack-server-build": "^0.25.4",
35
- "@jay-framework/stack-server-runtime": "^0.25.4",
36
- "@jay-framework/view-state-merge": "^0.25.4",
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": "^5.0.11"
38
+ "vite": "^6.4.4"
39
39
  },
40
40
  "devDependencies": {
41
- "@jay-framework/dev-environment": "^0.25.4",
42
- "@jay-framework/jay-cli": "^0.25.4",
43
- "@jay-framework/stack-client-runtime": "^0.25.4",
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.2.1"
55
+ "vitest": "^4.1.11"
56
56
  }
57
57
  }