@vesk/vesk-cli 0.2.16 → 0.2.18

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/cli.js +1430 -645
  2. package/package.json +5 -5
package/dist/cli.js CHANGED
@@ -2102,6 +2102,20 @@ var init_portal = __esm({
2102
2102
  });
2103
2103
 
2104
2104
  // ../runtime/src/hydrate.ts
2105
+ function runInHydrateBlock(fn) {
2106
+ const previous = scope();
2107
+ const block2 = root(() => {
2108
+ });
2109
+ set_active_block(block2);
2110
+ try {
2111
+ const result2 = fn();
2112
+ set_active_block(previous);
2113
+ return result2;
2114
+ } catch (error) {
2115
+ set_active_block(previous);
2116
+ throw error;
2117
+ }
2118
+ }
2105
2119
  function collectVskMarkers(container) {
2106
2120
  const markers = [];
2107
2121
  const walker = document.createTreeWalker(container, _SHOW_COMMENT, {
@@ -2177,7 +2191,7 @@ function hydrateViewport(container, componentFn, props, rootMargin = 500) {
2177
2191
  marker.textContent = "vsk-hold";
2178
2192
  }
2179
2193
  const viewportWalker = createHydrateWalker(container, viewportMarkers);
2180
- componentFn(props || {}, /* @__PURE__ */ new Map(), viewportWalker);
2194
+ runInHydrateBlock(() => componentFn(props || {}, /* @__PURE__ */ new Map(), viewportWalker));
2181
2195
  if (deferredMarkers.length > 0) {
2182
2196
  return new Promise((resolve39) => {
2183
2197
  const observer = new IntersectionObserver((entries) => {
@@ -2198,7 +2212,7 @@ function hydrateViewport(container, componentFn, props, rootMargin = 500) {
2198
2212
  }
2199
2213
  if (toHydrate.length > 0) {
2200
2214
  const w = createHydrateWalker(container, toHydrate);
2201
- componentFn(props || {}, /* @__PURE__ */ new Map(), w);
2215
+ runInHydrateBlock(() => componentFn(props || {}, /* @__PURE__ */ new Map(), w));
2202
2216
  }
2203
2217
  if (observer._observed === 0) {
2204
2218
  observer.disconnect();
@@ -2230,7 +2244,7 @@ function hydrateIdle(container, componentFn, props, options2 = {}) {
2230
2244
  idx = end;
2231
2245
  if (chunk.length > 0) {
2232
2246
  const walker = createHydrateWalker(container, chunk);
2233
- componentFn(props || {}, /* @__PURE__ */ new Map(), walker);
2247
+ runInHydrateBlock(() => componentFn(props || {}, /* @__PURE__ */ new Map(), walker));
2234
2248
  }
2235
2249
  if (idx < allMarkers.length && (!deadline || deadline.timeRemaining() > 0 || deadline.didTimeout)) {
2236
2250
  rafId2 = rIC(processChunk, { timeout });
@@ -2259,7 +2273,7 @@ function hydrateOnInteraction(container, componentFn, props, options2 = {}) {
2259
2273
  const markers = collectVskMarkers(container);
2260
2274
  if (markers.length > 0) {
2261
2275
  const walker = createHydrateWalker(container, markers);
2262
- componentFn(props || {}, /* @__PURE__ */ new Map(), walker);
2276
+ runInHydrateBlock(() => componentFn(props || {}, /* @__PURE__ */ new Map(), walker));
2263
2277
  }
2264
2278
  }
2265
2279
  const handler = (e) => trigger(e.type);
@@ -2281,6 +2295,7 @@ var init_hydrate = __esm({
2281
2295
  "../runtime/src/hydrate.ts"() {
2282
2296
  "use strict";
2283
2297
  init_ripple_runtime();
2298
+ init_ripple_blocks();
2284
2299
  _SHOW_COMMENT = 128;
2285
2300
  _FILTER_ACCEPT = 1;
2286
2301
  _FILTER_SKIP = 2;
@@ -2651,6 +2666,17 @@ function permanentRedirect(url) {
2651
2666
  function notFound() {
2652
2667
  throw new NotFoundError();
2653
2668
  }
2669
+ function routerMode() {
2670
+ const r = RouterCtx.get() || _currentRouter;
2671
+ return !!(r && r._hashMode);
2672
+ }
2673
+ function routeHrefOf(href) {
2674
+ return routerMode() && href.startsWith("#") ? href.slice(1) : href;
2675
+ }
2676
+ function isRouteHref(href) {
2677
+ if (!routerMode()) return !href.startsWith("#");
2678
+ return !href.startsWith("#") || href.startsWith("#/");
2679
+ }
2654
2680
  function setIsHydrating(v) {
2655
2681
  __isHydrating = v;
2656
2682
  }
@@ -2660,33 +2686,44 @@ function setIsPopStateNavigation(v) {
2660
2686
  function setCurrentRouter(r) {
2661
2687
  _currentRouter = r;
2662
2688
  }
2689
+ function getCurrentRouter() {
2690
+ return _currentRouter;
2691
+ }
2692
+ function isFn(v) {
2693
+ return typeof v === "function";
2694
+ }
2663
2695
  function findLoadingComponent(chain) {
2664
2696
  for (let i = chain.length - 1; i >= 0; i--) {
2665
- if (chain[i].loading) return chain[i].loading;
2697
+ const v = chain[i].loading;
2698
+ if (isFn(v)) return v;
2666
2699
  }
2667
2700
  return null;
2668
2701
  }
2669
2702
  function findErrorComponent(chain) {
2670
2703
  for (let i = chain.length - 1; i >= 0; i--) {
2671
- if (chain[i].error) return chain[i].error;
2704
+ const v = chain[i].error;
2705
+ if (isFn(v)) return v;
2672
2706
  }
2673
2707
  return null;
2674
2708
  }
2675
2709
  function findNotFoundComponent(chain) {
2676
2710
  for (let i = chain.length - 1; i >= 0; i--) {
2677
- if (chain[i].notFound) return chain[i].notFound;
2711
+ const v = chain[i].notFound;
2712
+ if (isFn(v)) return v;
2678
2713
  }
2679
2714
  return null;
2680
2715
  }
2681
2716
  function findOfflineComponent(chain) {
2682
2717
  for (let i = chain.length - 1; i >= 0; i--) {
2683
- if (chain[i].offline) return chain[i].offline;
2718
+ const v = chain[i].offline;
2719
+ if (v !== void 0 && v !== null) return v;
2684
2720
  }
2685
2721
  return null;
2686
2722
  }
2687
2723
  function findNetworkComponent(chain) {
2688
2724
  for (let i = chain.length - 1; i >= 0; i--) {
2689
- if (chain[i].network) return chain[i].network;
2725
+ const v = chain[i].network;
2726
+ if (v !== void 0 && v !== null) return v;
2690
2727
  }
2691
2728
  return null;
2692
2729
  }
@@ -2759,6 +2796,16 @@ function Outlet(props) {
2759
2796
  }
2760
2797
  return div;
2761
2798
  }
2799
+ function mountLinkChildren(target, children) {
2800
+ if (children.nodeType) {
2801
+ target.appendChild(children);
2802
+ } else if (Array.isArray(children)) {
2803
+ for (const c of children) {
2804
+ if (c && c.nodeType) target.appendChild(c);
2805
+ else if (c != null) target.appendChild(document.createTextNode(String(c)));
2806
+ }
2807
+ }
2808
+ }
2762
2809
  function Link(props, registry, hydrate) {
2763
2810
  const href = props.href || "#";
2764
2811
  if (hydrate && hydrate.nextElement) {
@@ -2767,22 +2814,27 @@ function Link(props, registry, hydrate) {
2767
2814
  const existing = hydrate.root.querySelector("a");
2768
2815
  if (existing) a2 = existing;
2769
2816
  }
2817
+ const claimed = a2 ? a2.parentNode !== null : false;
2818
+ if (!a2) a2 = document.createElement("a");
2819
+ applyLinkDom(a2, props, href);
2770
2820
  if (props.children != null) {
2771
2821
  if (typeof props.children === "string" || typeof props.children === "number") {
2772
2822
  a2.textContent = String(props.children);
2773
- } else if (props.children.textContent) {
2774
- a2.textContent = props.children.textContent;
2823
+ } else {
2824
+ a2.replaceChildren();
2825
+ mountLinkChildren(a2, props.children);
2775
2826
  }
2776
2827
  }
2777
2828
  a2.addEventListener("click", (e) => {
2778
2829
  if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
2779
2830
  if (props.target === "_blank") return;
2831
+ if (!isRouteHref(href)) return;
2780
2832
  e.preventDefault();
2781
2833
  e.stopPropagation();
2782
2834
  const nav = useNavigate();
2783
2835
  nav(href);
2784
2836
  });
2785
- return document.createDocumentFragment();
2837
+ return claimed ? document.createDocumentFragment() : a2;
2786
2838
  }
2787
2839
  const attrs = [
2788
2840
  `href="${href.replace(/"/g, "&quot;")}"`,
@@ -2799,26 +2851,16 @@ function Link(props, registry, hydrate) {
2799
2851
  return `<a ${attrs}>${childStr}</a>`;
2800
2852
  }
2801
2853
  const a = document.createElement("a");
2802
- a.href = href;
2803
- if (props.class) a.className = props.class;
2804
- if (props.style) a.setAttribute("style", props.style);
2805
- if (props.target) a.target = props.target;
2806
- if (props.rel) a.rel = props.rel;
2854
+ applyLinkDom(a, props, href);
2807
2855
  if (childStr) {
2808
2856
  a.textContent = childStr;
2809
2857
  } else if (props.children != null) {
2810
- if (props.children.nodeType) {
2811
- a.appendChild(props.children);
2812
- } else if (Array.isArray(props.children)) {
2813
- for (const c of props.children) {
2814
- if (c && c.nodeType) a.appendChild(c);
2815
- else if (c != null) a.appendChild(document.createTextNode(String(c)));
2816
- }
2817
- }
2858
+ mountLinkChildren(a, props.children);
2818
2859
  }
2819
2860
  a.addEventListener("click", (e) => {
2820
2861
  if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
2821
2862
  if (props.target === "_blank") return;
2863
+ if (!isRouteHref(href)) return;
2822
2864
  e.preventDefault();
2823
2865
  e.stopPropagation();
2824
2866
  const nav = useNavigate();
@@ -2826,6 +2868,14 @@ function Link(props, registry, hydrate) {
2826
2868
  });
2827
2869
  return a;
2828
2870
  }
2871
+ function applyLinkDom(a, props, href) {
2872
+ const displayHref = routerMode() && !href.startsWith("#") ? "#" + href : href;
2873
+ a.href = displayHref;
2874
+ if (props.class) a.className = props.class;
2875
+ if (props.style) a.setAttribute("style", props.style);
2876
+ if (props.target) a.target = props.target;
2877
+ if (props.rel) a.rel = props.rel;
2878
+ }
2829
2879
  function NavLink(props, registry, hydrate) {
2830
2880
  if (typeof document === "undefined") {
2831
2881
  return Link(props, registry, hydrate);
@@ -2833,23 +2883,27 @@ function NavLink(props, registry, hydrate) {
2833
2883
  if (__isHydrating) {
2834
2884
  const a2 = document.querySelector(`a[href="${props.href}"]`);
2835
2885
  if (a2) {
2886
+ applyLinkDom(a2, props, props.href);
2836
2887
  if (props.children != null) {
2837
2888
  if (typeof props.children === "string" || typeof props.children === "number") {
2838
2889
  a2.textContent = String(props.children);
2839
- } else if (props.children.textContent) {
2840
- a2.textContent = props.children.textContent;
2890
+ } else {
2891
+ a2.replaceChildren();
2892
+ mountLinkChildren(a2, props.children);
2841
2893
  }
2842
2894
  }
2843
2895
  a2.addEventListener("click", (e) => {
2844
2896
  if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) return;
2845
2897
  if (props.target === "_blank") return;
2898
+ if (!isRouteHref(props.href)) return;
2846
2899
  e.preventDefault();
2847
2900
  e.stopPropagation();
2848
2901
  const nav = useNavigate();
2849
2902
  nav(props.href);
2850
2903
  });
2851
2904
  const path2 = usePathname();
2852
- const isActive2 = props.href === path2 || props.href !== "/" && path2.startsWith(props.href) && (path2.length === props.href.length || path2[props.href.length] === "/" || path2[props.href.length] === "?");
2905
+ const routeHref2 = routeHrefOf(props.href);
2906
+ const isActive2 = routeHref2 === path2 || routeHref2 !== "/" && path2.startsWith(routeHref2) && (path2.length === routeHref2.length || path2[routeHref2.length] === "/" || path2[routeHref2.length] === "?");
2853
2907
  if (isActive2) {
2854
2908
  a2.classList.add(props.activeClass || "active");
2855
2909
  if (props.ariaCurrent !== false) a2.setAttribute("aria-current", "page");
@@ -2859,7 +2913,8 @@ function NavLink(props, registry, hydrate) {
2859
2913
  }
2860
2914
  const a = Link(props, registry, hydrate);
2861
2915
  const path = usePathname();
2862
- const isActive = props.href === path || props.href !== "/" && path.startsWith(props.href) && (path.length === props.href.length || path[props.href.length] === "/" || path[props.href.length] === "?");
2916
+ const routeHref = routeHrefOf(props.href);
2917
+ const isActive = routeHref === path || routeHref !== "/" && path.startsWith(routeHref) && (path.length === routeHref.length || path[routeHref.length] === "/" || path[routeHref.length] === "?");
2863
2918
  if (isActive) {
2864
2919
  a.classList.add(props.activeClass || "active");
2865
2920
  if (props.ariaCurrent !== false) a.setAttribute("aria-current", "page");
@@ -2904,7 +2959,11 @@ function useRouter() {
2904
2959
  back: () => window.history.back(),
2905
2960
  forward: () => window.history.forward(),
2906
2961
  go: (n) => window.history.go(n),
2907
- refresh: () => router?.navigate?.(window.location.pathname, { replace: true }),
2962
+ refresh: () => {
2963
+ const mode = routerMode();
2964
+ const p = mode && typeof window !== "undefined" && window.location.hash && window.location.hash.length > 1 ? window.location.hash.slice(1) : typeof window !== "undefined" ? window.location.pathname : "";
2965
+ router?.navigate?.(p, { replace: true });
2966
+ },
2908
2967
  prefetch: (href) => router?.prefetch?.(href),
2909
2968
  beforeEach: (fn) => {
2910
2969
  const r = router;
@@ -3297,7 +3356,7 @@ function registerOnlineRecovery(router) {
3297
3356
  r._onlineHandler = () => {
3298
3357
  if (!r._showingOffline) return;
3299
3358
  r._showingOffline = false;
3300
- router.navigate(window.location.pathname + window.location.search, { replace: true });
3359
+ router.navigate(routeFromLocation(hashModeOf(r)), { replace: true });
3301
3360
  };
3302
3361
  window.addEventListener("online", r._onlineHandler);
3303
3362
  }
@@ -3586,10 +3645,10 @@ function renderMatch(router, match, container, navToken) {
3586
3645
  if (!errorFn) throw error;
3587
3646
  const retry = () => {
3588
3647
  if (router && router.navigate) {
3589
- router.navigate(window.location.pathname, { replace: true });
3648
+ router.navigate(routeFromLocation(hashModeOf(router)), { replace: true });
3590
3649
  }
3591
3650
  };
3592
- const errorProps = { error, retry, params: paramValues, statusCode: error?.statusCode ?? 500, stack: error instanceof Error ? error.stack : String(error), url: typeof window !== "undefined" ? window.location.pathname : "", offline: error?.offline === true, networkState: getNetworkState() };
3651
+ const errorProps = { error, retry, params: paramValues, statusCode: error?.statusCode ?? 500, stack: error instanceof Error ? error.stack : String(error), url: typeof window !== "undefined" ? routeFromLocation(hashModeOf(router)) : "", offline: error?.offline === true, networkState: getNetworkState() };
3593
3652
  return runInBlockWindow(() => renderLayoutWith(0, () => {
3594
3653
  const result2 = errorFn(errorProps, /* @__PURE__ */ new Map(), clientWalker);
3595
3654
  if (result2 && typeof result2.then === "function") {
@@ -3603,10 +3662,10 @@ function renderMatch(router, match, container, navToken) {
3603
3662
  if (!errorFn) throw error;
3604
3663
  const retry = () => {
3605
3664
  if (router && router.navigate) {
3606
- router.navigate(window.location.pathname, { replace: true });
3665
+ router.navigate(routeFromLocation(hashModeOf(router)), { replace: true });
3607
3666
  }
3608
3667
  };
3609
- const errorProps = { error, retry, params: paramValues, statusCode: error?.statusCode ?? 500, stack: error instanceof Error ? error.stack : String(error), url: typeof window !== "undefined" ? window.location.pathname : "", offline: error?.offline === true, networkState: getNetworkState() };
3668
+ const errorProps = { error, retry, params: paramValues, statusCode: error?.statusCode ?? 500, stack: error instanceof Error ? error.stack : String(error), url: typeof window !== "undefined" ? routeFromLocation(hashModeOf(router)) : "", offline: error?.offline === true, networkState: getNetworkState() };
3610
3669
  const errDom = runInBlockWindow(() => errorFn(errorProps, /* @__PURE__ */ new Map(), clientWalker));
3611
3670
  if (errDom && typeof errDom.then === "function") {
3612
3671
  errDom.then(mountDom);
@@ -3696,10 +3755,10 @@ async function renderErrorPage(router, match, container, error) {
3696
3755
  const walker = createHydrateWalker(tempRoot, []);
3697
3756
  const retry = () => {
3698
3757
  if (router && router.navigate) {
3699
- router.navigate(window.location.pathname, { replace: true });
3758
+ router.navigate(routeFromLocation(hashModeOf(router)), { replace: true });
3700
3759
  }
3701
3760
  };
3702
- const errorProps = { error, retry, params: paramValues, statusCode: error?.statusCode ?? 500, stack: error instanceof Error ? error.stack : String(error), url: typeof window !== "undefined" ? window.location.pathname : "", offline: error?.offline === true, networkState: getNetworkState() };
3761
+ const errorProps = { error, retry, params: paramValues, statusCode: error?.statusCode ?? 500, stack: error instanceof Error ? error.stack : String(error), url: typeof window !== "undefined" ? routeFromLocation(hashModeOf(router)) : "", offline: error?.offline === true, networkState: getNetworkState() };
3703
3762
  const renderErrorChain = (index) => {
3704
3763
  if (index >= layoutNodes.length) {
3705
3764
  const result3 = errorFn(errorProps, /* @__PURE__ */ new Map(), walker);
@@ -3811,9 +3870,9 @@ async function hydrateInitial(router, match, container, strategy) {
3811
3870
  return (subWalker) => {
3812
3871
  if (!strategy || strategy === "full") {
3813
3872
  const pageProps = { params: paramValues, ...pageNode.props };
3814
- const result3 = hydPage(pageProps, /* @__PURE__ */ new Map(), subWalker);
3815
- storePageInstance(router, pageNode, pageProps, result3);
3816
- return result3;
3873
+ const result2 = hydPage(pageProps, /* @__PURE__ */ new Map(), subWalker);
3874
+ storePageInstance(router, pageNode, pageProps, result2);
3875
+ return result2;
3817
3876
  } else if (strategy === "viewport") {
3818
3877
  hydrateViewport(subWalker.root, hydPage, { params: paramValues, ...pageNode.props });
3819
3878
  } else if (strategy === "idle") {
@@ -3827,10 +3886,12 @@ async function hydrateInitial(router, match, container, strategy) {
3827
3886
  const node = layoutNodes[index];
3828
3887
  const hydLayout = hydLayouts[index];
3829
3888
  const childHydrator = renderLayoutChain2(index + 1);
3830
- const layoutProps = { children: childHydrator, params: paramValues };
3831
- const result2 = hydLayout(layoutProps, /* @__PURE__ */ new Map(), walker);
3832
- storeLayoutInstance(router, node, layoutProps, result2);
3833
- return result2;
3889
+ return (walker2) => {
3890
+ const layoutProps = { children: childHydrator, params: paramValues };
3891
+ const result2 = hydLayout(layoutProps, /* @__PURE__ */ new Map(), walker2);
3892
+ storeLayoutInstance(router, node, layoutProps, result2);
3893
+ return result2;
3894
+ };
3834
3895
  };
3835
3896
  var renderLayoutChain = renderLayoutChain2;
3836
3897
  if (layoutNodes.length === 0) {
@@ -3860,7 +3921,7 @@ async function hydrateInitial(router, match, container, strategy) {
3860
3921
  }
3861
3922
  setIsHydrating(true);
3862
3923
  const walker = createHydrateWalker(container);
3863
- await runInBlockWindow(() => renderLayoutChain2(0));
3924
+ await runInBlockWindow(() => renderLayoutChain2(0)(walker));
3864
3925
  setIsHydrating(false);
3865
3926
  } catch (error) {
3866
3927
  setIsHydrating(false);
@@ -3876,7 +3937,23 @@ async function hydrateInitial(router, match, container, strategy) {
3876
3937
  }
3877
3938
  }
3878
3939
  }
3940
+ function hashModeOf(r) {
3941
+ return !!r && r._hashMode === true;
3942
+ }
3943
+ function routeFromLocation(mode) {
3944
+ if (mode) {
3945
+ const h = typeof window !== "undefined" ? window.location.hash : "";
3946
+ if (h.length > 1 && h[1] === "/") return h.slice(1);
3947
+ return "/";
3948
+ }
3949
+ return window.location.pathname + window.location.search;
3950
+ }
3951
+ function routeKey(mode) {
3952
+ return get(_state.path) || routeFromLocation(mode);
3953
+ }
3879
3954
  function scrollToHash() {
3955
+ const r = getCurrentRouter();
3956
+ if (hashModeOf(r)) return;
3880
3957
  const h = typeof window !== "undefined" ? window.location.hash : "";
3881
3958
  if (!h || h === "#") return;
3882
3959
  const id = h.slice(1);
@@ -3893,6 +3970,7 @@ function createRouter(routes, options2 = {}) {
3893
3970
  const prefetch = options2.prefetch !== false;
3894
3971
  const hydrateStrategy = options2.hydrate || "full";
3895
3972
  const routeTree = Array.isArray(routes) ? routes : buildTreeFromMap(routes, options2);
3973
+ const hashMode = options2.hash === true;
3896
3974
  const router = {
3897
3975
  routeTree,
3898
3976
  container,
@@ -3904,6 +3982,7 @@ function createRouter(routes, options2 = {}) {
3904
3982
  _offlineUI: options2.offline ?? null,
3905
3983
  _beforeGuards: [],
3906
3984
  _viewTransitions: options2.viewTransitions === true,
3985
+ _hashMode: hashMode,
3907
3986
  beforeEach(fn) {
3908
3987
  this._beforeGuards.push(fn);
3909
3988
  let active = true;
@@ -3916,7 +3995,7 @@ function createRouter(routes, options2 = {}) {
3916
3995
  };
3917
3996
  },
3918
3997
  _runGuards(to) {
3919
- const from = window.location.pathname;
3998
+ const from = get(_state.path) || window.location.pathname;
3920
3999
  for (const g2 of this._beforeGuards ?? []) {
3921
4000
  const d = g2(to, from);
3922
4001
  if (d instanceof Promise) {
@@ -3952,16 +4031,26 @@ function createRouter(routes, options2 = {}) {
3952
4031
  if (_scrollTimer) return;
3953
4032
  _scrollTimer = setTimeout(() => {
3954
4033
  if (window.scrollY !== void 0) {
3955
- _scrollPositions.set(window.location.pathname, window.scrollY);
4034
+ _scrollPositions.set(routeKey(hashMode), window.scrollY);
3956
4035
  }
3957
4036
  _scrollTimer = null;
3958
4037
  }, 100);
3959
4038
  }, { passive: true });
3960
4039
  }
3961
4040
  window.addEventListener("popstate", () => {
4041
+ const p = routeFromLocation(hashMode);
4042
+ if (get(_state.path) === p) return;
3962
4043
  setIsPopStateNavigation(true);
3963
- this.navigate(window.location.href, { replace: true });
4044
+ this.navigate(p, { replace: true });
3964
4045
  });
4046
+ if (hashMode) {
4047
+ window.addEventListener("hashchange", () => {
4048
+ const p = routeFromLocation(true);
4049
+ if (get(_state.path) === p) return;
4050
+ setIsPopStateNavigation(true);
4051
+ this.navigate(p, { replace: true });
4052
+ });
4053
+ }
3965
4054
  document.addEventListener("click", (e) => {
3966
4055
  const target = e.target;
3967
4056
  if (!target || target.nodeType !== 1) return;
@@ -3975,7 +4064,8 @@ function createRouter(routes, options2 = {}) {
3975
4064
  if (anchor.hasAttribute("download")) return;
3976
4065
  if (anchor.getAttribute("rel") === "external") return;
3977
4066
  const href = anchor.getAttribute("href");
3978
- if (!href || href.startsWith("#") || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("javascript:")) return;
4067
+ if (!href || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("javascript:")) return;
4068
+ if (href.startsWith("#") && (!hashMode || !href.startsWith("#/"))) return;
3979
4069
  try {
3980
4070
  const url = new URL(href, window.location.origin);
3981
4071
  if (url.origin !== window.location.origin) return;
@@ -3992,8 +4082,8 @@ function createRouter(routes, options2 = {}) {
3992
4082
  if (link) this.prefetch(link.getAttribute("href"));
3993
4083
  }, { passive: true });
3994
4084
  }
3995
- const path = window.location.pathname + window.location.search;
3996
- if (container.children.length > 0) {
4085
+ const path = routeFromLocation(hashMode);
4086
+ if (container.children.length > 0 && !hashMode) {
3997
4087
  const url = new URL(path, window.location.origin);
3998
4088
  const match = matchRoute(this.routeTree, url.pathname);
3999
4089
  if (match) {
@@ -4009,7 +4099,9 @@ function createRouter(routes, options2 = {}) {
4009
4099
  return this;
4010
4100
  },
4011
4101
  navigate(path, opts = {}) {
4012
- const url = new URL(path, window.location.origin);
4102
+ const mode = hashModeOf(this);
4103
+ const raw2 = mode && typeof path === "string" && path.startsWith("#/") ? path.slice(1) : path;
4104
+ const url = new URL(raw2, window.location.origin);
4013
4105
  const match = matchRoute(this.routeTree, url.pathname);
4014
4106
  if (!match) {
4015
4107
  window.location.href = path;
@@ -4020,7 +4112,7 @@ function createRouter(routes, options2 = {}) {
4020
4112
  const guardResult = self._runGuards(url.pathname);
4021
4113
  const proceedNav = () => {
4022
4114
  if (!_isPopStateNavigation) {
4023
- _scrollPositions.set(window.location.pathname, window.scrollY);
4115
+ _scrollPositions.set(routeKey(mode), window.scrollY);
4024
4116
  }
4025
4117
  const loadingFn = findLoadingComponent(match.matchChain);
4026
4118
  this._navToken = (this._navToken || 0) + 1;
@@ -4028,10 +4120,12 @@ function createRouter(routes, options2 = {}) {
4028
4120
  loadingStart();
4029
4121
  let firstRenderFailed = false;
4030
4122
  const updateUrl = () => {
4123
+ const fullPath = url.pathname + url.search;
4124
+ const target = mode ? fullPath.startsWith("/") ? "#" + fullPath : "#" + fullPath : fullPath;
4031
4125
  if (!opts.replace) {
4032
- window.history.pushState({ path: url.pathname }, "", url.pathname + url.search);
4126
+ window.history.pushState({ path: url.pathname }, "", target);
4033
4127
  } else {
4034
- window.history.replaceState({ path: url.pathname }, "", url.pathname + url.search);
4128
+ window.history.replaceState({ path: url.pathname }, "", target);
4035
4129
  }
4036
4130
  set(_state.path, url.pathname);
4037
4131
  set(_state.search, url.search.startsWith("?") ? url.search.slice(1) : url.search);
@@ -4130,7 +4224,9 @@ function createRouter(routes, options2 = {}) {
4130
4224
  proceedNav();
4131
4225
  },
4132
4226
  prefetch(path) {
4133
- const url = new URL(path, window.location.origin);
4227
+ const mode = hashModeOf(this);
4228
+ const raw2 = mode && typeof path === "string" && path.startsWith("#/") ? path.slice(1) : path;
4229
+ const url = new URL(raw2, window.location.origin);
4134
4230
  const match = matchRoute(this.routeTree, url.pathname);
4135
4231
  if (!match) return;
4136
4232
  match.pathname = url.pathname;
@@ -4182,11 +4278,11 @@ function createRouter(routes, options2 = {}) {
4182
4278
  }
4183
4279
  }
4184
4280
  if (!didUpdate) {
4185
- const path = window.location.pathname + window.location.search;
4281
+ const path = routeFromLocation(hashMode);
4186
4282
  this.navigate(path, { replace: true });
4187
4283
  }
4188
4284
  } else {
4189
- const path = window.location.pathname + window.location.search;
4285
+ const path = routeFromLocation(hashMode);
4190
4286
  this.navigate(path, { replace: true });
4191
4287
  }
4192
4288
  }
@@ -4198,6 +4294,7 @@ function createFileRouter(routeTree, options2 = {}) {
4198
4294
  const middleware = options2.middleware || null;
4199
4295
  const renderFn = options2.render || renderMatch;
4200
4296
  const hydrateStrategy = options2.hydrate || "full";
4297
+ const hashMode = options2.hash === true;
4201
4298
  const router = {
4202
4299
  _hydrateStrategy: hydrateStrategy,
4203
4300
  routeTree,
@@ -4210,6 +4307,7 @@ function createFileRouter(routeTree, options2 = {}) {
4210
4307
  _offlineUI: options2.offline ?? null,
4211
4308
  _beforeGuards: [],
4212
4309
  _viewTransitions: options2.viewTransitions === true,
4310
+ _hashMode: hashMode,
4213
4311
  beforeEach(fn) {
4214
4312
  this._beforeGuards.push(fn);
4215
4313
  let active = true;
@@ -4222,7 +4320,7 @@ function createFileRouter(routeTree, options2 = {}) {
4222
4320
  };
4223
4321
  },
4224
4322
  _runGuards(to) {
4225
- const from = window.location.pathname;
4323
+ const from = get(_state.path) || window.location.pathname;
4226
4324
  for (const g2 of this._beforeGuards ?? []) {
4227
4325
  const d = g2(to, from);
4228
4326
  if (d instanceof Promise) {
@@ -4258,7 +4356,7 @@ function createFileRouter(routeTree, options2 = {}) {
4258
4356
  if (_scrollTimer) return;
4259
4357
  _scrollTimer = setTimeout(() => {
4260
4358
  if (window.scrollY !== void 0) {
4261
- _scrollPositions.set(window.location.pathname, window.scrollY);
4359
+ _scrollPositions.set(routeKey(hashMode), window.scrollY);
4262
4360
  }
4263
4361
  _scrollTimer = null;
4264
4362
  }, 100);
@@ -4266,9 +4364,19 @@ function createFileRouter(routeTree, options2 = {}) {
4266
4364
  window.addEventListener("scroll", _onScroll, { passive: true });
4267
4365
  }
4268
4366
  window.addEventListener("popstate", () => {
4367
+ const p = routeFromLocation(hashMode);
4368
+ if (get(_state.path) === p) return;
4269
4369
  setIsPopStateNavigation(true);
4270
- router.navigate(window.location.pathname + window.location.search, { replace: true });
4370
+ router.navigate(p, { replace: true });
4271
4371
  });
4372
+ if (hashMode) {
4373
+ window.addEventListener("hashchange", () => {
4374
+ const p = routeFromLocation(true);
4375
+ if (get(_state.path) === p) return;
4376
+ setIsPopStateNavigation(true);
4377
+ router.navigate(p, { replace: true });
4378
+ });
4379
+ }
4272
4380
  document.addEventListener("click", (e) => {
4273
4381
  const target = e.target;
4274
4382
  if (!target || target.nodeType !== 1) return;
@@ -4282,7 +4390,8 @@ function createFileRouter(routeTree, options2 = {}) {
4282
4390
  if (anchor.hasAttribute("download")) return;
4283
4391
  if (anchor.getAttribute("rel") === "external") return;
4284
4392
  const href = anchor.getAttribute("href");
4285
- if (!href || href.startsWith("#") || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("javascript:")) return;
4393
+ if (!href || href.startsWith("mailto:") || href.startsWith("tel:") || href.startsWith("javascript:")) return;
4394
+ if (href.startsWith("#") && (!hashMode || !href.startsWith("#/"))) return;
4286
4395
  try {
4287
4396
  const url = new URL(href, window.location.origin);
4288
4397
  if (url.origin !== window.location.origin) return;
@@ -4299,8 +4408,8 @@ function createFileRouter(routeTree, options2 = {}) {
4299
4408
  if (link) router.prefetch(link.getAttribute("href"));
4300
4409
  }, { passive: true });
4301
4410
  }
4302
- const path = window.location.pathname;
4303
- if (container.children.length > 0) {
4411
+ const path = routeFromLocation(hashMode).split("?")[0];
4412
+ if (container.children.length > 0 && !hashMode) {
4304
4413
  const match = matchRoute(routeTree, path);
4305
4414
  if (match) {
4306
4415
  match.pathname = path;
@@ -4315,7 +4424,9 @@ function createFileRouter(routeTree, options2 = {}) {
4315
4424
  return router;
4316
4425
  },
4317
4426
  navigate(pathname, opts = {}) {
4318
- const url = pathname instanceof URL ? pathname : new URL(pathname, window.location.origin);
4427
+ const mode = hashModeOf(router);
4428
+ const raw2 = mode && typeof pathname === "string" && pathname.startsWith("#/") ? pathname.slice(1) : pathname;
4429
+ const url = raw2 instanceof URL ? raw2 : new URL(raw2, window.location.origin);
4319
4430
  const match = matchRoute(routeTree, url.pathname);
4320
4431
  if (!match) {
4321
4432
  const chain = flattenLayoutChain(routeTree, url.pathname.split("/").filter(Boolean));
@@ -4344,7 +4455,7 @@ function createFileRouter(routeTree, options2 = {}) {
4344
4455
  match.pathname = url.pathname;
4345
4456
  const afterGuards = () => {
4346
4457
  if (!_isPopStateNavigation) {
4347
- _scrollPositions.set(window.location.pathname, window.scrollY);
4458
+ _scrollPositions.set(routeKey(mode), window.scrollY);
4348
4459
  }
4349
4460
  const swapView = (fn) => {
4350
4461
  const d = document;
@@ -4360,10 +4471,11 @@ function createFileRouter(routeTree, options2 = {}) {
4360
4471
  let firstRenderFailed = false;
4361
4472
  const updateUrl = () => {
4362
4473
  const fullUrl = url.pathname + url.search;
4474
+ const target = mode ? fullUrl.startsWith("/") ? "#" + fullUrl : "#" + fullUrl : fullUrl;
4363
4475
  if (!opts.replace) {
4364
- window.history.pushState({ path: fullUrl }, "", fullUrl);
4476
+ window.history.pushState({ path: fullUrl }, "", target);
4365
4477
  } else {
4366
- window.history.replaceState({ path: fullUrl }, "", fullUrl);
4478
+ window.history.replaceState({ path: fullUrl }, "", target);
4367
4479
  }
4368
4480
  set(_state.path, url.pathname);
4369
4481
  set(_state.search, url.search.startsWith("?") ? url.search.slice(1) : url.search);
@@ -4541,7 +4653,9 @@ function createFileRouter(routeTree, options2 = {}) {
4541
4653
  afterGuards();
4542
4654
  },
4543
4655
  prefetch(path) {
4544
- const url = new URL(path, window.location.origin);
4656
+ const mode = hashModeOf(router);
4657
+ const raw2 = mode && typeof path === "string" && path.startsWith("#/") ? path.slice(1) : path;
4658
+ const url = new URL(raw2, window.location.origin);
4545
4659
  const match = matchRoute(routeTree, url.pathname);
4546
4660
  if (!match) return;
4547
4661
  match.pathname = url.pathname;
@@ -4568,7 +4682,7 @@ function createFileRouter(routeTree, options2 = {}) {
4568
4682
  if (typeof router.__updateComponents === "function") {
4569
4683
  router.__updateComponents(router.routeTree);
4570
4684
  }
4571
- const path = window.location.pathname + window.location.search;
4685
+ const path = routeFromLocation(hashModeOf(router)).split("?")[0];
4572
4686
  const match = matchRoute(router.routeTree, path);
4573
4687
  if (match) {
4574
4688
  match.pathname = path;
@@ -15737,16 +15851,23 @@ function VeskParserPlugin(config = {}) {
15737
15851
  }
15738
15852
  if (this.#componentDepth > 0 && code === 60 && this.#isBlockContext()) {
15739
15853
  const next = this.input.charCodeAt(this.pos + 1);
15740
- if (next === 47 || next >= 65 && next <= 90 || next >= 97 && next <= 122) {
15741
- const startsNewStatement = this.hasPrecedingLineBreak();
15742
- const inType = this.inType;
15743
- const forceJsx = () => {
15744
- const savedExprAllowed = this.exprAllowed;
15745
- this.exprAllowed = true;
15746
- const result2 = super.readToken(code);
15747
- this.exprAllowed = savedExprAllowed;
15748
- return result2;
15749
- };
15854
+ const startsNewStatement = this.hasPrecedingLineBreak();
15855
+ const inType = this.inType;
15856
+ const forceJsx = () => {
15857
+ const savedExprAllowed = this.exprAllowed;
15858
+ this.exprAllowed = true;
15859
+ const result2 = super.readToken(code);
15860
+ this.exprAllowed = savedExprAllowed;
15861
+ return result2;
15862
+ };
15863
+ const prev = this.type;
15864
+ const canEndExpr = prev === tt.name || prev === tt.num || prev === tt.string || prev === tt.regexp || prev === tt.bracketR || prev === tt.backQuote || prev === tt.template || prev === tt._this || prev === tt._super || prev === tt._true || prev === tt._false || prev === tt._null || prev === tt.jsxTagEnd;
15865
+ const fragmentStart = !inType && next === 62 && startsNewStatement;
15866
+ if (next === 47 || fragmentStart || next >= 65 && next <= 90 || next >= 97 && next <= 122) {
15867
+ if (fragmentStart) {
15868
+ this.#jsxStartsStatement = true;
15869
+ return forceJsx();
15870
+ }
15750
15871
  if (inType) {
15751
15872
  if (startsNewStatement) {
15752
15873
  if (looksLikeGenericArrowAt(this.input, this.pos) || looksLikeTypeAssertionAt(this.input, this.pos)) {
@@ -15758,8 +15879,6 @@ function VeskParserPlugin(config = {}) {
15758
15879
  return this.finishToken(tstt.jsxTagStart);
15759
15880
  }
15760
15881
  } else {
15761
- const prev = this.type;
15762
- const canEndExpr = prev === tt.name || prev === tt.num || prev === tt.string || prev === tt.regexp || prev === tt.bracketR || prev === tt.backQuote || prev === tt.template || prev === tt._this || prev === tt._super || prev === tt._true || prev === tt._false || prev === tt._null || prev === tt.jsxTagEnd;
15763
15882
  if (!canEndExpr || startsNewStatement) {
15764
15883
  if (looksLikeGenericArrowAt(this.input, this.pos) || looksLikeTypeAssertionAt(this.input, this.pos)) {
15765
15884
  this.#jsxStartsStatement = false;
@@ -16474,28 +16593,6 @@ function skipTrackGeneric(text, open) {
16474
16593
  }
16475
16594
  return text.length;
16476
16595
  }
16477
- function cssBlockEnd(css, start) {
16478
- let depth = 0;
16479
- let i = start;
16480
- while (i < css.length) {
16481
- const c = css[i];
16482
- if (c === '"' || c === "'") {
16483
- i = skipString(css, i);
16484
- continue;
16485
- }
16486
- if (c === "/" && css[i + 1] === "*") {
16487
- i = skipComment(css, i);
16488
- continue;
16489
- }
16490
- if (c === "{") depth++;
16491
- else if (c === "}") {
16492
- depth--;
16493
- if (depth === 0) return i + 1;
16494
- }
16495
- i++;
16496
- }
16497
- return css.length;
16498
- }
16499
16596
  function htmlTagEnd(html, lt) {
16500
16597
  let i = lt + 1;
16501
16598
  while (i < html.length) {
@@ -16536,6 +16633,19 @@ function isIdentChar2(code) {
16536
16633
  function isWhitespaceChar2(ch) {
16537
16634
  return ch === " " || ch === " " || ch === "\n" || ch === "\r" || ch === "\f" || ch === "\v" || ch === "\xA0" || ch === "\uFEFF";
16538
16635
  }
16636
+ function offsetToLineCol(source, offset2) {
16637
+ let line = 1;
16638
+ let column = 1;
16639
+ for (let i = 0; i < offset2 && i < source.length; i++) {
16640
+ if (source.charCodeAt(i) === 10) {
16641
+ line++;
16642
+ column = 1;
16643
+ } else {
16644
+ column++;
16645
+ }
16646
+ }
16647
+ return { line, column };
16648
+ }
16539
16649
  function preprocessForClauses(source) {
16540
16650
  const annotations = [];
16541
16651
  const chars = source.split("");
@@ -16678,6 +16788,21 @@ function preprocessForClauses(source) {
16678
16788
  while (k < end && isWhitespaceChar2(source[k])) k++;
16679
16789
  const expr = source.slice(k, end).trim();
16680
16790
  if (expr) {
16791
+ if (expr[0] === ":") {
16792
+ const { line, column } = offsetToLineCol(source, start);
16793
+ throw new VeskError(
16794
+ `Invalid \`; key\` clause \u2014 write the key expression after \`key\` without a colon: \`key ${expr.slice(1).trim()}\`.`,
16795
+ {
16796
+ line,
16797
+ column,
16798
+ code: codeFrame(source, line, column),
16799
+ nextSteps: [
16800
+ "Use `; key <expr>` (no colon), e.g. `for (const item of items; key item.id)`.",
16801
+ "For the iteration index use `; index <name>`, e.g. `for (const item of items; key item.id; index i)`."
16802
+ ]
16803
+ }
16804
+ );
16805
+ }
16681
16806
  keyRange = [k, start + clause.length];
16682
16807
  clauseCode = " ".repeat(clause.length);
16683
16808
  }
@@ -17432,10 +17557,16 @@ function loadSsrModule(absPath) {
17432
17557
  exportsObj = null;
17433
17558
  }
17434
17559
  } else {
17435
- exportsObj = {};
17436
- EVALUATING.set(absPath, exportsObj);
17437
- const ran = evaluateModuleFile(absPath, exportsObj);
17438
- if (!ran) exportsObj = null;
17560
+ const src2 = readSsrSource(absPath);
17561
+ const body = src2?.ast?.body || [];
17562
+ if (src2 && isPureReexportBarrel(body)) {
17563
+ exportsObj = createLazyBarrelExports(buildBarrelSpec(body), dirname2(absPath));
17564
+ } else {
17565
+ exportsObj = {};
17566
+ EVALUATING.set(absPath, exportsObj);
17567
+ const ran = evaluateModuleFile(absPath, exportsObj, src2);
17568
+ if (!ran) exportsObj = null;
17569
+ }
17439
17570
  }
17440
17571
  if (exportsObj === null) {
17441
17572
  exportsObj = nativeRequireFallback(absPath);
@@ -17469,13 +17600,13 @@ function depsFresh(cachedVal) {
17469
17600
  }
17470
17601
  return true;
17471
17602
  }
17472
- function evaluateModuleFile(absPath, exportsObj) {
17603
+ function readSsrSource(absPath) {
17473
17604
  let raw2;
17474
17605
  try {
17475
17606
  raw2 = readFileSync(absPath, "utf-8");
17476
17607
  } catch (err) {
17477
17608
  console.warn(`[vesk] SSR: failed to read ${absPath}: ${err?.message ?? String(err)}`);
17478
- return false;
17609
+ return null;
17479
17610
  }
17480
17611
  let ast = null;
17481
17612
  try {
@@ -17483,6 +17614,164 @@ function evaluateModuleFile(absPath, exportsObj) {
17483
17614
  } catch {
17484
17615
  ast = null;
17485
17616
  }
17617
+ return { raw: raw2, ast };
17618
+ }
17619
+ function isPureReexportBarrel(body) {
17620
+ for (const stmt of body) {
17621
+ if (stmt.type === "EmptyStatement") continue;
17622
+ if (stmt.type === "ExpressionStatement") {
17623
+ const expr = stmt.expression;
17624
+ if (expr && expr.type === "Literal" && typeof expr.value === "string" && expr.value.length > 0) continue;
17625
+ return false;
17626
+ }
17627
+ if (stmt.type === "ExportAllDeclaration") {
17628
+ if (stmt.exportKind === "type") continue;
17629
+ continue;
17630
+ }
17631
+ if (stmt.type === "ExportNamedDeclaration") {
17632
+ if (stmt.exportKind === "type") continue;
17633
+ if (stmt.source) continue;
17634
+ return false;
17635
+ }
17636
+ if (stmt.type === "ImportDeclaration" && stmt.importKind === "type") continue;
17637
+ return false;
17638
+ }
17639
+ return true;
17640
+ }
17641
+ function buildBarrelSpec(body) {
17642
+ const spec = { direct: /* @__PURE__ */ new Map(), namespaces: /* @__PURE__ */ new Map(), stars: [] };
17643
+ for (const stmt of body) {
17644
+ if (stmt.type === "ExportNamedDeclaration") {
17645
+ if (stmt.exportKind === "type" || !stmt.source) continue;
17646
+ const source = quotedSourceValue(stmt.source);
17647
+ const specifiers = stmt.specifiers || [];
17648
+ for (const ex of specifiers) {
17649
+ if (ex.exportKind === "type") continue;
17650
+ const imported = exportKeyName(ex.local);
17651
+ const exported = exportKeyName(ex.exported);
17652
+ if (!exported || !imported) continue;
17653
+ if (source !== null) spec.direct.set(exported, { source, imported });
17654
+ }
17655
+ } else if (stmt.type === "ExportAllDeclaration") {
17656
+ if (stmt.exportKind === "type") continue;
17657
+ const source = quotedSourceValue(stmt.source);
17658
+ if (stmt.exported) {
17659
+ const nsName = exportKeyName(stmt.exported);
17660
+ if (source !== null && nsName) spec.namespaces.set(nsName, source);
17661
+ } else if (source !== null) {
17662
+ spec.stars.push(source);
17663
+ }
17664
+ }
17665
+ }
17666
+ return spec;
17667
+ }
17668
+ function quotedSourceValue(node) {
17669
+ const n = node;
17670
+ if (n && (n.type === "Literal" || n.type === "StringLiteral") && typeof n.value === "string") {
17671
+ return n.value;
17672
+ }
17673
+ const printed = printNode(node);
17674
+ return printed ? stripOuterQuotes(printed) : null;
17675
+ }
17676
+ function createLazyBarrelExports(spec, dir) {
17677
+ const targets = /* @__PURE__ */ new Map();
17678
+ const starKeys = /* @__PURE__ */ new Set();
17679
+ let starsEnumerated = false;
17680
+ const loadSource = (source) => {
17681
+ let target = targets.get(source);
17682
+ if (!target) {
17683
+ target = resolveSsrModule(source, dir) ?? "";
17684
+ if (!target) return null;
17685
+ targets.set(source, target);
17686
+ }
17687
+ const mod = loadSsrModule(target);
17688
+ return mod && typeof mod === "object" ? mod : null;
17689
+ };
17690
+ const hasPresent = (prop) => {
17691
+ if (spec.direct.has(prop) || spec.namespaces.has(prop)) return true;
17692
+ if (starsEnumerated && starKeys.has(prop)) return true;
17693
+ if (prop === "default") return false;
17694
+ for (const source of spec.stars) {
17695
+ const mod = loadSource(source);
17696
+ if (mod && Object.prototype.hasOwnProperty.call(mod, prop)) return true;
17697
+ }
17698
+ return false;
17699
+ };
17700
+ const getNamed = (prop) => {
17701
+ const direct = spec.direct.get(prop);
17702
+ if (direct) {
17703
+ const mod = loadSource(direct.source);
17704
+ if (!mod) return void 0;
17705
+ return mod[direct.imported];
17706
+ }
17707
+ const nsSource = spec.namespaces.get(prop);
17708
+ if (nsSource) {
17709
+ return loadSource(nsSource) ?? void 0;
17710
+ }
17711
+ if (prop === "default") return void 0;
17712
+ for (const source of spec.stars) {
17713
+ const mod = loadSource(source);
17714
+ if (mod && Object.prototype.hasOwnProperty.call(mod, prop)) {
17715
+ return mod[prop];
17716
+ }
17717
+ }
17718
+ return void 0;
17719
+ };
17720
+ return new Proxy(/* @__PURE__ */ Object.create(null), {
17721
+ get(_target, prop) {
17722
+ if (typeof prop === "symbol") return void 0;
17723
+ return getNamed(prop);
17724
+ },
17725
+ has(_target, prop) {
17726
+ if (typeof prop === "symbol") return false;
17727
+ return hasPresent(prop);
17728
+ },
17729
+ ownKeys() {
17730
+ if (!starsEnumerated) {
17731
+ for (const source of spec.stars) {
17732
+ const mod = loadSource(source);
17733
+ if (!mod) continue;
17734
+ for (const k of Reflect.ownKeys(mod)) {
17735
+ if (typeof k === "string" && k !== "default") starKeys.add(k);
17736
+ }
17737
+ }
17738
+ starsEnumerated = true;
17739
+ }
17740
+ return [.../* @__PURE__ */ new Set([...spec.direct.keys(), ...spec.namespaces.keys(), ...starKeys])];
17741
+ },
17742
+ getOwnPropertyDescriptor(_target, prop) {
17743
+ if (typeof prop === "symbol") return void 0;
17744
+ if (!hasPresent(prop)) return void 0;
17745
+ return {
17746
+ enumerable: true,
17747
+ configurable: true,
17748
+ get: () => getNamed(prop)
17749
+ };
17750
+ }
17751
+ });
17752
+ }
17753
+ function evaluateModuleFile(absPath, exportsObj, src2) {
17754
+ let raw2;
17755
+ if (src2) {
17756
+ raw2 = src2.raw;
17757
+ } else {
17758
+ try {
17759
+ raw2 = readFileSync(absPath, "utf-8");
17760
+ } catch (err) {
17761
+ console.warn(`[vesk] SSR: failed to read ${absPath}: ${err?.message ?? String(err)}`);
17762
+ return false;
17763
+ }
17764
+ }
17765
+ let ast;
17766
+ if (src2) {
17767
+ ast = src2.ast;
17768
+ } else {
17769
+ try {
17770
+ ast = parse4(raw2, { filename: absPath });
17771
+ } catch {
17772
+ ast = null;
17773
+ }
17774
+ }
17486
17775
  if (!ast) {
17487
17776
  try {
17488
17777
  const fn = new Function("require", "module", "exports", "__dirname", "__filename", raw2);
@@ -17561,7 +17850,9 @@ function createModuleRequire(fromDir) {
17561
17850
  }
17562
17851
  function resolveSsrModule(specifier, fromDir) {
17563
17852
  let resolved = null;
17564
- if (specifier === "." || specifier === ".." || isAbsolute(specifier)) {
17853
+ if (specifier === "." || specifier === "..") {
17854
+ resolved = probeFile(resolve2(fromDir, specifier));
17855
+ } else if (isAbsolute(specifier)) {
17565
17856
  resolved = probeFile(resolve2(specifier));
17566
17857
  } else if (specifier.startsWith("./") || specifier.startsWith("../")) {
17567
17858
  resolved = probeFile(resolve2(fromDir, specifier));
@@ -17864,7 +18155,7 @@ function collectComponentCalls(nodes, out) {
17864
18155
  }
17865
18156
  }
17866
18157
  }
17867
- function offsetToLineCol(source, offset2) {
18158
+ function offsetToLineCol2(source, offset2) {
17868
18159
  let line = 1;
17869
18160
  let column = 1;
17870
18161
  for (let i = 0; i < offset2 && i < source.length; i++) {
@@ -18573,7 +18864,7 @@ function processStatementModeBody(source, bodyStmts, filename) {
18573
18864
  if (raw2) nodes.push(new RuntimeStatement(raw2, stmt, source));
18574
18865
  }
18575
18866
  } else if (stmt.type === "ClassDeclaration") {
18576
- const { line, column } = offsetToLineCol(source, stmt.start ?? 0);
18867
+ const { line, column } = offsetToLineCol2(source, stmt.start ?? 0);
18577
18868
  throw VeskError.classDecl({ file: filename || "", line, column, code: codeFrame(source, line, column) });
18578
18869
  } else {
18579
18870
  const raw2 = getSource(source, stmt);
@@ -18605,7 +18896,7 @@ function validateBlocks(compName, isClient, body, file, source) {
18605
18896
  const opts = file ? { file } : {};
18606
18897
  if (source && node.start !== void 0) {
18607
18898
  const pos = node.start;
18608
- const { line, column } = offsetToLineCol(source, pos);
18899
+ const { line, column } = offsetToLineCol2(source, pos);
18609
18900
  opts.line = line;
18610
18901
  opts.column = column;
18611
18902
  opts.code = codeFrame(source, line, column);
@@ -18617,7 +18908,7 @@ function validateBlocks(compName, isClient, body, file, source) {
18617
18908
  const opts = file ? { file } : {};
18618
18909
  if (source && node.start !== void 0) {
18619
18910
  const pos = node.start;
18620
- const { line, column } = offsetToLineCol(source, pos);
18911
+ const { line, column } = offsetToLineCol2(source, pos);
18621
18912
  opts.line = line;
18622
18913
  opts.column = column;
18623
18914
  opts.code = codeFrame(source, line, column);
@@ -18723,7 +19014,7 @@ function generateIR(ast, source, filename) {
18723
19014
  }
18724
19015
  if (inner.type === "ComponentDeclaration") {
18725
19016
  } else if (inner.type === "ClassDeclaration") {
18726
- const { line, column } = offsetToLineCol(source, inner.start ?? 0);
19017
+ const { line, column } = offsetToLineCol2(source, inner.start ?? 0);
18727
19018
  throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
18728
19019
  } else if (inner.type === "TSEnumDeclaration") {
18729
19020
  const code = processEnum(inner, source, exported);
@@ -18770,7 +19061,7 @@ function generateIR(ast, source, filename) {
18770
19061
  } else if (stmt.type === "IfStatement" && !mainReturn && stmt.consequent.type !== "ThrowStatement") {
18771
19062
  guardClauses.push(stmt);
18772
19063
  } else if (stmt.type === "ClassDeclaration") {
18773
- const { line, column } = offsetToLineCol(source, stmt.start ?? 0);
19064
+ const { line, column } = offsetToLineCol2(source, stmt.start ?? 0);
18774
19065
  throw VeskError.classDecl({ file, line, column, code: codeFrame(source, line, column) });
18775
19066
  } else {
18776
19067
  const raw2 = getSource(source, stmt);
@@ -18792,7 +19083,7 @@ function generateIR(ast, source, filename) {
18792
19083
  collectComponentCalls(comp.body, called);
18793
19084
  for (const [childName, start] of called) {
18794
19085
  if (!asyncNames.has(childName)) continue;
18795
- const { line, column } = offsetToLineCol(source, start >= 0 ? start : 0);
19086
+ const { line, column } = offsetToLineCol2(source, start >= 0 ? start : 0);
18796
19087
  throw VeskError.asyncChildInSyncParent(comp.name, childName, { file, line, column, code: codeFrame(source, line, column) });
18797
19088
  }
18798
19089
  }
@@ -18845,7 +19136,11 @@ function generateIR(ast, source, filename) {
18845
19136
  "getAction",
18846
19137
  "validateActionInput",
18847
19138
  "issuesToFieldMap",
18848
- "isFormAction"
19139
+ "isFormAction",
19140
+ "Show",
19141
+ "For",
19142
+ "Switch",
19143
+ "Match"
18849
19144
  ];
18850
19145
  const usedFunctions = /* @__PURE__ */ new Set();
18851
19146
  const addUsedFrom = (code) => {
@@ -18863,6 +19158,30 @@ function generateIR(ast, source, filename) {
18863
19158
  if (node instanceof RuntimeStatement && node.raw) {
18864
19159
  addUsedFrom(node.raw);
18865
19160
  }
19161
+ if (node instanceof TrackDecl && node.init) {
19162
+ addUsedFrom(node.init);
19163
+ }
19164
+ if (node instanceof ForLoop) {
19165
+ if (node.init) addUsedFrom(node.init);
19166
+ if (node.update) addUsedFrom(node.update);
19167
+ if (node.condition && node.condition.raw) addUsedFrom(node.condition.raw);
19168
+ scanForAutoImport(node.bodyTemplate);
19169
+ }
19170
+ if (node instanceof WhileLoop) {
19171
+ if (node.condition && node.condition.raw) addUsedFrom(node.condition.raw);
19172
+ scanForAutoImport(node.bodyTemplate);
19173
+ }
19174
+ if (node instanceof SwitchBlock) {
19175
+ if (node.discriminant && node.discriminant.raw) addUsedFrom(node.discriminant.raw);
19176
+ for (const c of node.cases) {
19177
+ if (c.test && c.test.raw) addUsedFrom(c.test.raw);
19178
+ scanForAutoImport(c.body);
19179
+ }
19180
+ }
19181
+ if (node instanceof TryCatch) {
19182
+ scanForAutoImport(node.bodyTemplate);
19183
+ scanForAutoImport(node.catchBody);
19184
+ }
18866
19185
  if (node instanceof ComponentCall) {
18867
19186
  if (autoImportable.includes(node.componentName)) {
18868
19187
  usedFunctions.add(node.componentName);
@@ -26716,6 +27035,17 @@ function collectTrackedNames(body) {
26716
27035
  }
26717
27036
  return names;
26718
27037
  }
27038
+ function transformTrackedInit(init, tracked2) {
27039
+ if (!init) return init;
27040
+ let expr = null;
27041
+ try {
27042
+ const prog = parse4(`(${init})`);
27043
+ expr = prog.body?.[0]?.type === "ExpressionStatement" ? prog.body[0].expression ?? null : null;
27044
+ } catch {
27045
+ }
27046
+ if (!expr) return init;
27047
+ return transformTracked({ raw: init, ast: expr }, tracked2);
27048
+ }
26719
27049
  function indent2(code, level = 1) {
26720
27050
  const pad = " ".repeat(level);
26721
27051
  return code.split("\n").map((l) => l ? pad + l : "").join("\n");
@@ -26731,7 +27061,7 @@ function emitNode(ctx2, node, tracked2, effectsVar, parentVar, compPrefix = "__c
26731
27061
  if (node instanceof DynamicBinding) return emitDynamicBinding(ctx2, node, tracked2, effectsVar);
26732
27062
  if (node instanceof TrackDecl) {
26733
27063
  const cellName = node.rawName || node.name;
26734
- const init = stripTrackGeneric(node.init);
27064
+ const init = transformTrackedInit(stripTrackGeneric(node.init), tracked2);
26735
27065
  ctx2.push(`const ${cellName} = ${init};`);
26736
27066
  return null;
26737
27067
  }
@@ -26992,6 +27322,9 @@ function emitComponentCall(ctx2, node, tracked2, effectsVar, parentVar, compPref
26992
27322
  ctx2.push(`const ${frag} = (() => { const $f = document.createDocumentFragment();`);
26993
27323
  const savedWalker = ctx2.walker;
26994
27324
  const savedEffects = ctx2.effects;
27325
+ const wipeMount = ctx2.linkNames.has(node.componentName);
27326
+ const savedHydrate = ctx2.hydrate;
27327
+ if (wipeMount) ctx2.hydrate = false;
26995
27328
  ctx2.walker = walkerVar;
26996
27329
  ctx2.effects = [];
26997
27330
  for (const child of node.children) {
@@ -27001,6 +27334,7 @@ function emitComponentCall(ctx2, node, tracked2, effectsVar, parentVar, compPref
27001
27334
  for (const eff of ctx2.effects) ctx2.push(effectsVar ? `${effectsVar}.push(${effectBlockToHandlerExpr(eff)});` : eff);
27002
27335
  ctx2.effects = savedEffects;
27003
27336
  ctx2.walker = savedWalker;
27337
+ ctx2.hydrate = savedHydrate;
27004
27338
  ctx2.push(`return $f; })();`);
27005
27339
  propsEntries.push(`children: ${frag}`);
27006
27340
  ctx2.push(`const ${v} = ${awaitKw}${access}({ ${propsEntries.join(", ")} }, __registry, ${walkerVar});`);
@@ -27060,7 +27394,7 @@ function emitTryCatch(ctx2, node, tracked2, effectsVar, parentVar) {
27060
27394
  ctx2.push(indent2(`const __cl = [];`));
27061
27395
  }
27062
27396
  for (const child of body) {
27063
- const childVar = emitNode(ctx2, child, tracked2, isCatch ? null : effArr, void 0, compPrefix);
27397
+ const childVar = emitNode(ctx2, child, tracked2, isCatch ? null : effArr, hydMode ? void 0 : "__p", compPrefix);
27064
27398
  if (childVar) {
27065
27399
  if (hydMode) ctx2.push(indent2(`__cl.push(${childVar});`));
27066
27400
  else ctx2.push(indent2(`__p.insertBefore(${childVar}, ${endAnchor});`));
@@ -27159,7 +27493,7 @@ function emitOpaque(ctx2, node, tracked2, effTarget, parentVar) {
27159
27493
  ctx2.push(`if (${condExpr}) { ${asyncKw}${conRenderName}(); }` + (hasElse ? ` else { ${asyncKw}${altRenderName}(); }` : ""));
27160
27494
  const renderBranch = `if (__nv) { ${asyncKw}${conRenderName}(); }` + (hasElse ? ` else { ${asyncKw}${altRenderName}(); }` : "");
27161
27495
  const effectBody = `effect(${ctx2.isAsyncScope ? "async () => {" : "() => {"}
27162
- if (__first) { __first = false; return; }
27496
+ if (__first) { __first = false; __iv = ${condExpr}; return; }
27163
27497
  const __nv = ${condExpr};
27164
27498
  if (__nv !== __iv) {
27165
27499
  for (const e of ${effectsVar}) destroy_block(e);
@@ -27169,6 +27503,7 @@ function emitOpaque(ctx2, node, tracked2, effTarget, parentVar) {
27169
27503
  __iv = __nv;
27170
27504
  }
27171
27505
  });`;
27506
+ if (!isReactiveExpression(node.condition, tracked2)) return null;
27172
27507
  if (effTarget) {
27173
27508
  ctx2.push(`${effTarget}.push((() => {
27174
27509
  let __iv = ${condExpr};
@@ -27198,28 +27533,30 @@ function emitWhileLoop(ctx2, node, tracked2, parentVar) {
27198
27533
  const renderLoop = ctx2.n();
27199
27534
  ctx2.push(`const ${renderLoop} = ${ctx2.isAsyncScope ? "async () => {" : "() => {"}`);
27200
27535
  if (!hyd) ctx2.push(indent2(`const __p = ${anchor}.parentNode;`));
27536
+ if (!hyd) ctx2.push(indent2(`const __b = document.createDocumentFragment();`));
27201
27537
  if (hyd) ctx2.push(indent2(`const __cl = [];`));
27202
27538
  if (node.isDoWhile) {
27203
27539
  ctx2.push(indent2(`do {`));
27204
27540
  for (const n of node.bodyTemplate) {
27205
- const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
27541
+ const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__b");
27206
27542
  if (v) {
27207
27543
  if (hyd) ctx2.push(indent2(`__cl.push(${v});`));
27208
- else ctx2.push(indent2(`__p.insertBefore(${v}, ${endAnchor});`));
27544
+ else ctx2.push(indent2(`__b.appendChild(${v});`));
27209
27545
  }
27210
27546
  }
27211
27547
  ctx2.push(indent2(`} while (${condExpr});`));
27212
27548
  } else {
27213
27549
  ctx2.push(indent2(`while (${condExpr}) {`));
27214
27550
  for (const n of node.bodyTemplate) {
27215
- const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
27551
+ const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__b");
27216
27552
  if (v) {
27217
27553
  if (hyd) ctx2.push(indent2(`__cl.push(${v});`));
27218
- else ctx2.push(indent2(`__p.insertBefore(${v}, ${endAnchor});`));
27554
+ else ctx2.push(indent2(`__b.appendChild(${v});`));
27219
27555
  }
27220
27556
  }
27221
27557
  ctx2.push(indent2(`}`));
27222
27558
  }
27559
+ if (!hyd) ctx2.push(indent2(`__p.insertBefore(__b, ${endAnchor});`));
27223
27560
  if (hyd) ctx2.push(indent2(`__place(${anchor}, ${endAnchor}, __cl, ${parent});`));
27224
27561
  ctx2.push(`};`);
27225
27562
  if (!hyd) ctx2.push(`${parent}.appendChild(${endAnchor});`);
@@ -27229,7 +27566,7 @@ function emitWhileLoop(ctx2, node, tracked2, parentVar) {
27229
27566
  let __iv = (${condExpr});
27230
27567
  let __first = true;
27231
27568
  effect(${ctx2.isAsyncScope ? "async () => {" : "() => {"}
27232
- if (__first) { __first = false; return; }
27569
+ if (__first) { __first = false; __iv = (${condExpr}); return; }
27233
27570
  if (__busy) return;
27234
27571
  const __nv = (${condExpr});
27235
27572
  if (__nv !== __iv) {
@@ -27258,44 +27595,52 @@ function emitForLoop(ctx2, node, tracked2, parentVar) {
27258
27595
  const renderLoop = ctx2.n();
27259
27596
  ctx2.push(`const ${renderLoop} = ${ctx2.isAsyncScope ? "async () => {" : "() => {"}`);
27260
27597
  if (!hyd) ctx2.push(indent2(`const __p = ${anchor}.parentNode;`));
27598
+ if (!hyd) ctx2.push(indent2(`const __b = document.createDocumentFragment();`));
27261
27599
  if (hyd) ctx2.push(indent2(`const __cl = [];`));
27262
27600
  if (node.kind === "for-in") {
27263
27601
  const srcExpr = transformTracked(node.condition, tracked2);
27264
27602
  ctx2.push(indent2(`for (${node.init} of (Array.isArray(${srcExpr}) ? ${srcExpr} : (${srcExpr} == null ? [] : Object.keys(${srcExpr})))) {`));
27265
27603
  for (const n of node.bodyTemplate) {
27266
- const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
27604
+ const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__b");
27267
27605
  if (v) {
27268
27606
  if (hyd) ctx2.push(indent2(`__cl.push(${v});`));
27269
- else ctx2.push(indent2(`__p.insertBefore(${v}, ${endAnchor});`));
27607
+ else ctx2.push(indent2(`__b.appendChild(${v});`));
27270
27608
  }
27271
27609
  }
27272
27610
  ctx2.push(indent2(`}`));
27273
27611
  } else {
27274
27612
  const condExpr = transformTracked(node.condition, tracked2);
27275
- if (node.init) ctx2.push(indent2(`${node.init}`));
27276
- ctx2.push(indent2(`while (${condExpr}) {`));
27613
+ let initPart = (node.init || "").trim();
27614
+ let updatePart = (node.update || "").trim();
27615
+ if (initPart.endsWith(";")) initPart = initPart.slice(0, -1).trim();
27616
+ if (updatePart.endsWith(";")) updatePart = updatePart.slice(0, -1).trim();
27617
+ const head = initPart ? `${initPart}; ${condExpr}` : `; ${condExpr}`;
27618
+ ctx2.push(indent2(`for (${head}; ${updatePart}) {`));
27277
27619
  for (const n of node.bodyTemplate) {
27278
- const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
27620
+ const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__b");
27279
27621
  if (v) {
27280
27622
  if (hyd) ctx2.push(indent2(`__cl.push(${v});`));
27281
- else ctx2.push(indent2(`__p.insertBefore(${v}, ${endAnchor});`));
27623
+ else ctx2.push(indent2(`__b.appendChild(${v});`));
27282
27624
  }
27283
27625
  }
27284
- if (node.update) ctx2.push(indent2(`${node.update}`));
27285
27626
  ctx2.push(indent2(`}`));
27286
27627
  }
27628
+ if (!hyd) ctx2.push(indent2(`__p.insertBefore(__b, ${endAnchor});`));
27287
27629
  if (hyd) ctx2.push(indent2(`__place(${anchor}, ${endAnchor}, __cl, ${parent});`));
27288
27630
  ctx2.push(`};`);
27289
27631
  if (!hyd) ctx2.push(`${parent}.appendChild(${endAnchor});`);
27290
27632
  ctx2.push(`${ctx2.isAsyncScope ? "await " : ""}${renderLoop}();`);
27291
27633
  if (node.kind === "for-in") {
27292
27634
  const srcExpr = transformTracked(node.condition, tracked2);
27635
+ if (!isReactiveExpression(node.condition, tracked2)) {
27636
+ return null;
27637
+ }
27293
27638
  ctx2.effects.push(`{
27294
27639
  let __busy = false;
27295
27640
  let __iv = undefined;
27296
27641
  let __first = true;
27297
27642
  effect(${ctx2.isAsyncScope ? "async () => {" : "() => {"}
27298
- if (__first) { __first = false; return; }
27643
+ if (__first) { __first = false; __iv = (${srcExpr}); return; }
27299
27644
  if (__busy) return;
27300
27645
  const __nv = (${srcExpr});
27301
27646
  if (__nv !== __iv) {
@@ -27326,8 +27671,12 @@ function emitSwitchBlock(ctx2, node, tracked2, parentVar) {
27326
27671
  ctx2.push(`const ${endAnchor} = document.createComment('switch-end');`);
27327
27672
  const renderSwitch = ctx2.n();
27328
27673
  ctx2.push(`const ${renderSwitch} = ${ctx2.isAsyncScope ? "async () => {" : "() => {"}`);
27329
- if (!hyd) ctx2.push(indent2(`const __p = ${anchor}.parentNode;`));
27330
- if (hyd) ctx2.push(indent2(`const __cl = [];`));
27674
+ if (hyd) {
27675
+ ctx2.push(indent2(`const __cl = [];`));
27676
+ } else {
27677
+ ctx2.push(indent2(`const __p = ${anchor}.parentNode;`));
27678
+ ctx2.push(indent2(`const __c = document.createDocumentFragment();`));
27679
+ }
27331
27680
  ctx2.push(indent2(`switch (${discExpr}) {`));
27332
27681
  for (const c of node.cases) {
27333
27682
  if (c.test) {
@@ -27336,15 +27685,16 @@ function emitSwitchBlock(ctx2, node, tracked2, parentVar) {
27336
27685
  ctx2.push(indent2(`default:`));
27337
27686
  }
27338
27687
  for (const n of c.body) {
27339
- const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
27688
+ const v = emitNode(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__c");
27340
27689
  if (v) {
27341
27690
  if (hyd) ctx2.push(indent2(`__cl.push(${v});`));
27342
- else ctx2.push(indent2(`__p.insertBefore(${v}, ${endAnchor});`));
27691
+ else ctx2.push(indent2(`__c.appendChild(${v});`));
27343
27692
  }
27344
27693
  }
27345
27694
  ctx2.push(indent2(`break;`));
27346
27695
  }
27347
27696
  ctx2.push(indent2(`}`));
27697
+ if (!hyd) ctx2.push(indent2(`__p.insertBefore(__c, ${endAnchor});`));
27348
27698
  if (hyd) ctx2.push(indent2(`__place(${anchor}, ${endAnchor}, __cl, ${parent});`));
27349
27699
  ctx2.push(`};`);
27350
27700
  if (!hyd) ctx2.push(`${parent}.appendChild(${endAnchor});`);
@@ -27354,7 +27704,7 @@ function emitSwitchBlock(ctx2, node, tracked2, parentVar) {
27354
27704
  let __iv = (${discExpr});
27355
27705
  let __first = true;
27356
27706
  effect(${ctx2.isAsyncScope ? "async () => {" : "() => {"}
27357
- if (__first) { __first = false; return; }
27707
+ if (__first) { __first = false; __iv = (${discExpr}); return; }
27358
27708
  if (__busy) return;
27359
27709
  const __nv = (${discExpr});
27360
27710
  if (__nv !== __iv) {
@@ -27381,6 +27731,7 @@ function emitMap(ctx2, node, tracked2, parentVar) {
27381
27731
  const keyed = !!node.keyExpr;
27382
27732
  const hyd = ctx2.hydrate && !keyed;
27383
27733
  const parent = parentVar || "$root";
27734
+ const reactiveSource = isReactiveExpression(node.expression, tracked2);
27384
27735
  ctx2.push(`const ${anchor} = document.createComment('map');`);
27385
27736
  if (!hyd) ctx2.push(`${parent}.appendChild(${anchor});`);
27386
27737
  ctx2.push(`let ${effectsVar} = [];`);
@@ -27390,14 +27741,20 @@ function emitMap(ctx2, node, tracked2, parentVar) {
27390
27741
  ctx2.push(`const ${renderItem} = ${ctx2.isAsyncScope ? "async " : ""}(${itemVar}${indexParam}, __e, __r${hyd ? ", __cl" : ""}) => {`);
27391
27742
  ctx2.push(indent2(`__r = __r || ${endAnchor};`));
27392
27743
  if (node.indexVariable) ctx2.push(indent2(`const ${node.indexVariable} = __i;`));
27393
- ctx2.push(indent2(`const __p = ${anchor}.parentNode;`));
27744
+ if (hyd) {
27745
+ ctx2.push(indent2(`const __p = ${anchor}.parentNode;`));
27746
+ } else {
27747
+ ctx2.push(indent2(`const __p = ${anchor}.parentNode;`));
27748
+ ctx2.push(indent2(`const __it = document.createDocumentFragment();`));
27749
+ }
27394
27750
  for (const n of node.bodyTemplate) {
27395
- const v = emitNode(ctx2, n, tracked2, "__e");
27751
+ const v = emitNode(ctx2, n, tracked2, "__e", hyd ? void 0 : "__it");
27396
27752
  if (v) {
27397
27753
  if (hyd) ctx2.push(indent2(`if (__cl) __cl.push(${v}); else __p.insertBefore(${v}, __r);`));
27398
- else ctx2.push(indent2(`__p.insertBefore(${v}, __r);`));
27754
+ else ctx2.push(indent2(`__it.appendChild(${v});`));
27399
27755
  }
27400
27756
  }
27757
+ if (!hyd) ctx2.push(indent2(`__p.insertBefore(__it, __r);`));
27401
27758
  ctx2.push(`};`);
27402
27759
  let emptyRenderName = null;
27403
27760
  if (node.alternateNodes.length > 0) {
@@ -27433,11 +27790,12 @@ function emitMap(ctx2, node, tracked2, parentVar) {
27433
27790
  const isEmptyVar = ctx2.n();
27434
27791
  ctx2.push(`let ${isEmptyVar} = !${hasItems}();`);
27435
27792
  ctx2.push(`if (!${isEmptyVar}) { ${initList}(); } else { ${aw}${emptyRenderName}(); }`);
27793
+ if (!reactiveSource) return null;
27436
27794
  ctx2.effects.push(`{
27437
27795
  let __first = true;
27438
27796
  effect(${effOpen}
27439
27797
  const __new = ${hasItems}();
27440
- if (__first) { __first = false; return; }
27798
+ if (__first) { __first = false; __new; return; }
27441
27799
  if (__new !== ${isEmptyVar}) {
27442
27800
  if (__new) ${reconciler}(${arrExpr});
27443
27801
  return;
@@ -27451,11 +27809,12 @@ function emitMap(ctx2, node, tracked2, parentVar) {
27451
27809
  }`);
27452
27810
  } else {
27453
27811
  ctx2.push(`${initList}();`);
27812
+ if (!reactiveSource) return null;
27454
27813
  ctx2.effects.push(`{
27455
27814
  let __first = true;
27456
27815
  effect(() => {
27457
27816
  const __nv = ${arrExpr};
27458
- if (__first) { __first = false; return; }
27817
+ if (__first) { __first = false; __nv; ${reconciler}(${arrExpr}); return; }
27459
27818
  ${reconciler}(${arrExpr});
27460
27819
  });
27461
27820
  }`);
@@ -27485,11 +27844,12 @@ function emitMap(ctx2, node, tracked2, parentVar) {
27485
27844
  ctx2.push(indent2(renderAllItems("", collectVar)));
27486
27845
  ctx2.push(indent2(`} else { ${aw}${emptyRenderName}(${collectVar ? collectVar : ""}); }`));
27487
27846
  if (collectVar) ctx2.push(`__place(${anchor}, ${endAnchor}, ${collectVar}, ${parent});`);
27847
+ if (!reactiveSource) return null;
27488
27848
  ctx2.effects.push(`{
27489
27849
  let __first = true;
27490
27850
  effect(${effOpen}
27491
27851
  const __new = ${hasItems}();
27492
- if (__first) { __first = false; return; }
27852
+ if (__first) { __first = false; __new; return; }
27493
27853
  if (__new !== ${isEmptyVar}) {
27494
27854
  if (__new) {
27495
27855
  for (const e of ${effectsVar}) destroy_block(e);
@@ -27513,11 +27873,12 @@ ${renderAllItems(" ", null)}
27513
27873
  if (collectVar) ctx2.push(`const ${collectVar} = [];`);
27514
27874
  ctx2.push(renderAllItems("", collectVar));
27515
27875
  if (collectVar) ctx2.push(`__place(${anchor}, ${endAnchor}, ${collectVar}, ${parent});`);
27876
+ if (!reactiveSource) return null;
27516
27877
  ctx2.effects.push(`{
27517
27878
  let __first = true;
27518
27879
  effect(${effOpen}
27519
27880
  const __nv = ${arrExpr};
27520
- if (__first) { __first = false; return; }
27881
+ if (__first) { __first = false; __nv; return; }
27521
27882
  for (const e of ${effectsVar}) destroy_block(e);
27522
27883
  ${effectsVar}.length = 0;
27523
27884
  __cleanup(${anchor}, ${endAnchor});
@@ -27531,10 +27892,11 @@ ${renderAllItems(" ", null)}
27531
27892
  function computeAsyncComponents(comps) {
27532
27893
  return new Set(comps.filter((c) => c.isAsync).map((c) => c.name));
27533
27894
  }
27534
- function generateComponent(comp, importedNames = /* @__PURE__ */ new Set(), hydrate = false, asyncComps = /* @__PURE__ */ new Set()) {
27895
+ function generateComponent(comp, importedNames = /* @__PURE__ */ new Set(), hydrate = false, asyncComps = /* @__PURE__ */ new Set(), linkNames = /* @__PURE__ */ new Set()) {
27535
27896
  const tracked2 = collectTrackedNames(comp.body);
27536
27897
  const ctx2 = new Ctx();
27537
27898
  ctx2.importedNames = importedNames;
27899
+ ctx2.linkNames = linkNames;
27538
27900
  ctx2.hydrate = hydrate;
27539
27901
  ctx2.asyncComps = asyncComps;
27540
27902
  ctx2.isAsyncScope = comp.isAsync || asyncComps.has(comp.name);
@@ -27561,7 +27923,7 @@ function generateComponent(comp, importedNames = /* @__PURE__ */ new Set(), hydr
27561
27923
  const v = emitNode(ctx2, node, tracked2, null);
27562
27924
  if (v) {
27563
27925
  if (ctx2.hydrate) {
27564
- ctx2.push(indent2(`if (${v}.parentNode !== $root) $root.appendChild(${v});`));
27926
+ ctx2.push(indent2(`if (${v}.parentNode !== $root) { if (!$root || ${v}.parentNode == null || !$root.contains(${v})) $root.appendChild(${v}); }`));
27565
27927
  } else {
27566
27928
  ctx2.push(indent2(`$root.appendChild(${v});`));
27567
27929
  }
@@ -27587,6 +27949,12 @@ function buildComponentMap(irRoot, hydrate = false) {
27587
27949
  const mapLines = [];
27588
27950
  mapLines.push(`const __components = {};`);
27589
27951
  const asyncComps = computeAsyncComponents(irRoot.components);
27952
+ const linkNames = /* @__PURE__ */ new Set();
27953
+ for (const imp of irRoot.imports) {
27954
+ for (const pair of importBindingPairs(imp)) {
27955
+ if (pair.imported === "Link" || pair.imported === "NavLink") linkNames.add(pair.local);
27956
+ }
27957
+ }
27590
27958
  const componentNames = new Set(irRoot.components.map((c) => c.name));
27591
27959
  const topValueNames = extractTopLevelNames(irRoot.topLevelCode).filter((n) => !componentNames.has(n));
27592
27960
  const directNames = /* @__PURE__ */ new Set([...extractRuntimeNames(irRoot.imports), ...localValueImportNames(irRoot.imports), ...topValueNames]);
@@ -27596,7 +27964,7 @@ function buildComponentMap(irRoot, hydrate = false) {
27596
27964
  mapLines.push(`__components[${JSON.stringify(comp.name)}] = ${stub};`);
27597
27965
  continue;
27598
27966
  }
27599
- const code = generateComponent(comp, directNames, hydrate, asyncComps);
27967
+ const code = generateComponent(comp, directNames, hydrate, asyncComps, linkNames);
27600
27968
  mapLines.push(`__components[${JSON.stringify(comp.name)}] = ${code};`);
27601
27969
  }
27602
27970
  mapLines.push(`function __cleanup(start, end) {`);
@@ -27893,6 +28261,7 @@ var init_client_codegen = __esm({
27893
28261
  effects = [];
27894
28262
  c = 0;
27895
28263
  importedNames = /* @__PURE__ */ new Set();
28264
+ linkNames = /* @__PURE__ */ new Set();
27896
28265
  delegatedEvents = /* @__PURE__ */ new Set();
27897
28266
  directEvents = /* @__PURE__ */ new Set();
27898
28267
  hydrate = false;
@@ -27970,8 +28339,9 @@ function irNodeToJS(node, importedNames, isAsync = false, tracked2) {
27970
28339
  if (node instanceof ForLoop) return forLoopToJS(node, isAsync, tracked2);
27971
28340
  if (node instanceof TrackDecl) {
27972
28341
  const cellName = node.rawName || node.name;
27973
- const unwrapped = unwrapTrackCall(node.init);
27974
- const inner = hasTopLevelComma(unwrapped) ? stripTrackGeneric(node.init) : unwrapped;
28342
+ const init = transformTrackedInit(node.init, tracked2 || /* @__PURE__ */ new Map());
28343
+ const unwrapped = unwrapTrackCall(init);
28344
+ const inner = hasTopLevelComma(unwrapped) ? stripTrackGeneric(init) : unwrapped;
27975
28345
  const key = JSON.stringify(`${compKey(node)}:${node.name}`);
27976
28346
  return [
27977
28347
  `const ${cellName} = (() => {`,
@@ -28210,13 +28580,17 @@ function forLoopToJS(node, isAsync = false, tracked2) {
28210
28580
  }
28211
28581
  lines.push(`}`);
28212
28582
  } else {
28213
- if (node.init) lines.push(`${node.init}`);
28214
- lines.push(`while (${exprJSX(node.condition, tracked2)}) {`);
28583
+ let initPart = (node.init || "").trim();
28584
+ let updatePart = (node.update || "").trim();
28585
+ if (initPart.endsWith(";")) initPart = initPart.slice(0, -1).trim();
28586
+ if (updatePart.endsWith(";")) updatePart = updatePart.slice(0, -1).trim();
28587
+ const cond = exprJSX(node.condition, tracked2);
28588
+ const head = initPart ? `${initPart}; ${cond}` : `; ${cond}`;
28589
+ lines.push(`for (${head}; ${updatePart}) {`);
28215
28590
  for (const n of node.bodyTemplate) {
28216
28591
  const code = irNodeToJS(n, null, isAsync, tracked2);
28217
28592
  if (code) lines.push(indent(code));
28218
28593
  }
28219
- if (node.update) lines.push(indent(`${node.update}`));
28220
28594
  lines.push(`}`);
28221
28595
  }
28222
28596
  return lines.join("\n");
@@ -35048,7 +35422,7 @@ __export(typecheck_exports, {
35048
35422
  typecheckProject: () => typecheckProject
35049
35423
  });
35050
35424
  import { readFileSync as readFileSync34, readdirSync as readdirSync14, statSync as statSync22 } from "node:fs";
35051
- import { join as join22, dirname as dirname22, normalize, relative as relative7, resolve as resolve37, sep as sep7 } from "node:path";
35425
+ import { join as join21, dirname as dirname22, normalize, relative as relative7, resolve as resolve37, sep as sep7 } from "node:path";
35052
35426
  import * as ts8 from "typescript";
35053
35427
  function walkProjectFiles(projectRoot) {
35054
35428
  const code = [];
@@ -35061,7 +35435,7 @@ function walkProjectFiles(projectRoot) {
35061
35435
  return;
35062
35436
  }
35063
35437
  for (const e of entries) {
35064
- const p = join22(dir, e);
35438
+ const p = join21(dir, e);
35065
35439
  let st;
35066
35440
  try {
35067
35441
  st = statSync22(p);
@@ -35116,8 +35490,8 @@ function checkStructureFile(appDir, file) {
35116
35490
  return null;
35117
35491
  }
35118
35492
  function createTypecheckHost(projectRoot, appDir, vskFiles) {
35119
- const ambientPath = join22(appDir, "__vesk_ambient.d.ts");
35120
- const overridePath = join22(appDir, "__vesk_runtime_override.d.ts");
35493
+ const ambientPath = join21(appDir, "__vesk_ambient.d.ts");
35494
+ const overridePath = join21(appDir, "__vesk_runtime_override.d.ts");
35121
35495
  const cached = /* @__PURE__ */ new Map();
35122
35496
  const scriptKindFor = (file) => file.endsWith(".vsk") ? ts8.ScriptKind.TSX : ts8.ScriptKind.TS;
35123
35497
  const host2 = {
@@ -35187,7 +35561,7 @@ function createTypecheckHost(projectRoot, appDir, vskFiles) {
35187
35561
  directoryExists: (dir) => ts8.sys.directoryExists(dir),
35188
35562
  getDirectories: (dir) => {
35189
35563
  try {
35190
- return readdirSync14(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => join22(dir, d.name));
35564
+ return readdirSync14(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => join21(dir, d.name));
35191
35565
  } catch {
35192
35566
  return [];
35193
35567
  }
@@ -35198,7 +35572,7 @@ function createTypecheckHost(projectRoot, appDir, vskFiles) {
35198
35572
  resolveModuleNameLiterals(moduleLiterals, containingFile, redirectedReference, options2) {
35199
35573
  return moduleLiterals.map(({ text }) => {
35200
35574
  if (text.endsWith(".vsk")) {
35201
- const abs = normalize(join22(dirname22(containingFile), text));
35575
+ const abs = normalize(join21(dirname22(containingFile), text));
35202
35576
  return {
35203
35577
  resolvedModule: {
35204
35578
  resolvedFileName: abs + ".d.ts",
@@ -35209,7 +35583,7 @@ function createTypecheckHost(projectRoot, appDir, vskFiles) {
35209
35583
  };
35210
35584
  }
35211
35585
  if (text.endsWith(".css")) {
35212
- const abs = normalize(join22(dirname22(containingFile), text));
35586
+ const abs = normalize(join21(dirname22(containingFile), text));
35213
35587
  return {
35214
35588
  resolvedModule: {
35215
35589
  resolvedFileName: abs + ".d.ts",
@@ -35227,7 +35601,7 @@ function createTypecheckHost(projectRoot, appDir, vskFiles) {
35227
35601
  return host2;
35228
35602
  }
35229
35603
  function typecheckProject(projectRoot, opts = {}) {
35230
- const appDir = opts.appDir ?? join22(projectRoot, "app");
35604
+ const appDir = opts.appDir ?? join21(projectRoot, "app");
35231
35605
  const vskFiles = /* @__PURE__ */ new Map();
35232
35606
  const parseErrors = [];
35233
35607
  const warnings = [];
@@ -35266,8 +35640,8 @@ function typecheckProject(projectRoot, opts = {}) {
35266
35640
  }
35267
35641
  rootNames.push(f);
35268
35642
  }
35269
- const ambientPath = join22(appDir, "__vesk_ambient.d.ts");
35270
- const overridePath = join22(appDir, "__vesk_runtime_override.d.ts");
35643
+ const ambientPath = join21(appDir, "__vesk_ambient.d.ts");
35644
+ const overridePath = join21(appDir, "__vesk_runtime_override.d.ts");
35271
35645
  rootNames.push(ambientPath);
35272
35646
  rootNames.push(overridePath);
35273
35647
  const options2 = {
@@ -35832,7 +36206,7 @@ declare module '@vesk/runtime' {
35832
36206
 
35833
36207
  // src/index.ts
35834
36208
  import { readFileSync as readFileSync35, writeFileSync as writeFileSync19, mkdirSync as mkdirSync16, existsSync as existsSync38 } from "fs";
35835
- import { resolve as resolve38, join as join23, dirname as dirname23 } from "path";
36209
+ import { resolve as resolve38, join as join22, dirname as dirname23 } from "path";
35836
36210
  import { fileURLToPath as fileURLToPath9 } from "url";
35837
36211
 
35838
36212
  // ../compiler/dist/config.js
@@ -36498,10 +36872,8 @@ init_server_jsgen();
36498
36872
  init_server_render();
36499
36873
 
36500
36874
  // ../adapter/src/css.ts
36501
- init_scan();
36502
36875
  import { readFileSync as readFileSync4, existsSync as existsSync5 } from "node:fs";
36503
36876
  import { resolve as resolve6 } from "node:path";
36504
- var TAILWIND_CSS_URL = "/_vesk/static/_tailwind.css";
36505
36877
  var GLOBAL_CSS_URL = "/_vesk/static/global.css";
36506
36878
  function resolveUserCssPath(appDir) {
36507
36879
  const cssSrc = resolve6(appDir, "..", "src", "global.css");
@@ -36510,40 +36882,16 @@ function resolveUserCssPath(appDir) {
36510
36882
  if (existsSync5(altCssSrc)) return altCssSrc;
36511
36883
  return null;
36512
36884
  }
36513
- function hasUserCss(appDir) {
36514
- return resolveUserCssPath(appDir) !== null;
36515
- }
36516
- function hasBuiltTailwindCss(outDir2) {
36517
- const p = resolve6(outDir2, "static", "_tailwind.css");
36885
+ function hasBuiltGlobalCss(outDir2) {
36886
+ const p = resolve6(outDir2, "static", "global.css");
36518
36887
  return existsSync5(p) && readFileSync4(p, "utf-8").trim().length > 0;
36519
36888
  }
36520
36889
  function isTailwindPlugin(plugins) {
36521
36890
  return (plugins || []).some((p) => String(p && p.name).toLowerCase().includes("tailwind"));
36522
36891
  }
36523
36892
  function resolveCssUrls(opts) {
36524
- const urls = [];
36525
- if (opts.tailwind) urls.push(TAILWIND_CSS_URL);
36526
- if (opts.userCss) urls.push(GLOBAL_CSS_URL);
36527
- return urls;
36528
- }
36529
- function stripTailwindDirectives(css) {
36530
- const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+[\w-]+\s*\{)/;
36531
- let result2 = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, "");
36532
- result2 = result2.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, "");
36533
- const output = [];
36534
- let pos = 0;
36535
- while (pos < result2.length) {
36536
- const lineEnd = result2.indexOf("\n", pos) === -1 ? result2.length : result2.indexOf("\n", pos) + 1;
36537
- const line = result2.slice(pos, lineEnd);
36538
- if (blockStart.test(line.trim())) {
36539
- const end = cssBlockEnd(result2, pos);
36540
- pos = end;
36541
- continue;
36542
- }
36543
- output.push(line);
36544
- pos = lineEnd;
36545
- }
36546
- return output.join("").trim();
36893
+ if (opts.enabled) return [GLOBAL_CSS_URL];
36894
+ return [];
36547
36895
  }
36548
36896
 
36549
36897
  // ../adapter/src/ssr-function.ts
@@ -36608,20 +36956,33 @@ function generateSsrFunction(routeNode, appDir, outDir2, componentMap, options2)
36608
36956
  const middlewareCode = options2?.middlewareCode || null;
36609
36957
  const headExtra = options2?.headExtra || null;
36610
36958
  const pagePath = resolve7(appDir, routeNode.sourceDir, "page.vsk");
36611
- const layoutPath = resolve7(appDir, routeNode.sourceDir, "layout.vsk");
36612
36959
  const parts = routeNode.fullPath.split("/").filter(Boolean);
36613
36960
  const name = routeName(parts);
36614
36961
  const funcDir = resolve7(outDir2, "server", "functions");
36615
36962
  const funcPath = resolve7(funcDir, `${name}.js`);
36616
36963
  const cssUrls = resolveCssUrls({
36617
- tailwind: hasBuiltTailwindCss(outDir2),
36618
- userCss: hasUserCss(appDir)
36964
+ enabled: hasBuiltGlobalCss(outDir2)
36619
36965
  });
36620
36966
  const cssOption = cssUrls.length > 0 ? `, cssUrls: ${JSON.stringify(cssUrls)}` : "";
36621
36967
  const headExtraOption = headExtra ? `, headExtra: ${JSON.stringify(headExtra)}` : "";
36622
36968
  const bakedOptions = cssOption + headExtraOption;
36623
- const hasLayout = !!routeNode.layout;
36624
- const hasAncestorLayout = ancestorLayouts.length > 0;
36969
+ const layoutStack = [
36970
+ ...ancestorLayouts.map((a) => ({ sourceDir: a.sourceDir, layoutCompName: a.layoutCompName })),
36971
+ ...routeNode.layout ? [{ sourceDir: routeNode.sourceDir, layoutCompName: routeNode.layout }] : []
36972
+ ];
36973
+ const layoutDecls = [];
36974
+ for (const entry of layoutStack) {
36975
+ const entryPath = resolve7(appDir, entry.sourceDir, "layout.vsk");
36976
+ const entrySrc = readFileSync5(entryPath, "utf-8");
36977
+ const entryComp = extractCompName(entrySrc) || "Layout";
36978
+ const escaped = escapeSource(entrySrc);
36979
+ layoutDecls.push({
36980
+ src: `\`${escaped}\``,
36981
+ comp: JSON.stringify(entryComp),
36982
+ path: JSON.stringify(entryPath),
36983
+ compiled: `(() => { try { setVskHydrate(true); return compileFile(\`${escaped}\`, { sourcePath: ${JSON.stringify(entryPath)} }); } catch { return null; } finally { setVskHydrate(false); } })()`
36984
+ });
36985
+ }
36625
36986
  const pageSrc = readFileSync5(pagePath, "utf-8");
36626
36987
  const pageComp = extractCompName(pageSrc) || "Page";
36627
36988
  const errorPath = resolveErrorFile(routeNode.sourceDir, appDir);
@@ -36633,42 +36994,26 @@ const _errorPath = ${JSON.stringify(errorPath)};
36633
36994
  const _errorCompiled = (() => { try { setVskHydrate(true); return compileFile(_errorSrc, { sourcePath: _errorPath }); } catch { return null; } finally { setVskHydrate(false); } })();
36634
36995
  ` : "const _errorSrc = null;\nconst _errorComp = null;\nconst _errorPath = null;\nconst _errorCompiled = null;\n";
36635
36996
  let src2 = "";
36636
- if (hasLayout) {
36637
- const layoutSrc = readFileSync5(layoutPath, "utf-8");
36638
- const layoutComp = extractCompName(layoutSrc) || "Layout";
36639
- src2 = `const _layoutSrc = \`${escapeSource(layoutSrc)}\`;
36640
- const _pageSrc = \`${escapeSource(pageSrc)}\`;
36641
- `;
36642
- src2 += `const _layoutComp = ${JSON.stringify(layoutComp)};
36643
- const _pageComp = ${JSON.stringify(pageComp)};
36644
- `;
36645
- src2 += `const _layoutPath = ${JSON.stringify(layoutPath)};
36646
- const _pagePath = ${JSON.stringify(pagePath)};
36647
- `;
36648
- src2 += `const _layoutCompiled = (() => { try { setVskHydrate(true); return compileFile(_layoutSrc, { sourcePath: _layoutPath }); } catch { return null; } finally { setVskHydrate(false); } })();
36649
- `;
36650
- src2 += `const _pageCompiled = (() => { try { setVskHydrate(true); return compileFile(_pageSrc, { sourcePath: _pagePath }); } catch { return null; } finally { setVskHydrate(false); } })();
36651
- `;
36652
- src2 += errorVars;
36653
- } else if (hasAncestorLayout) {
36654
- const outerLayout = ancestorLayouts[0];
36655
- const outerLayoutPath = resolve7(appDir, outerLayout.sourceDir, "layout.vsk");
36656
- const outerLayoutSrc = readFileSync5(outerLayoutPath, "utf-8");
36657
- const outerLayoutComp = extractCompName(outerLayoutSrc) || "Layout";
36997
+ if (layoutDecls.length > 0) {
36658
36998
  src2 = `const _pageSrc = \`${escapeSource(pageSrc)}\`;
36659
36999
  `;
36660
37000
  src2 += `const _pageComp = ${JSON.stringify(pageComp)};
36661
37001
  `;
36662
- src2 += `const _layoutSrc = \`${escapeSource(outerLayoutSrc)}\`;
37002
+ src2 += `const _pagePath = ${JSON.stringify(pagePath)};
37003
+ `;
37004
+ src2 += `const _pageCompiled = (() => { try { setVskHydrate(true); return compileFile(_pageSrc, { sourcePath: _pagePath }); } catch { return null; } finally { setVskHydrate(false); } })();
36663
37005
  `;
36664
- src2 += `const _layoutComp = ${JSON.stringify(outerLayoutComp)};
37006
+ src2 += `const _layoutSrcList = [
37007
+ ${layoutDecls.map((d) => " " + d.src + ",").join("\n")}
37008
+ ];
36665
37009
  `;
36666
- src2 += `const _layoutPath = ${JSON.stringify(outerLayoutPath)};
36667
- const _pagePath = ${JSON.stringify(pagePath)};
37010
+ src2 += `const _layoutCompList = [${layoutDecls.map((d) => d.comp).join(", ")}];
36668
37011
  `;
36669
- src2 += `const _layoutCompiled = (() => { try { setVskHydrate(true); return compileFile(_layoutSrc, { sourcePath: _layoutPath }); } catch { return null; } finally { setVskHydrate(false); } })();
37012
+ src2 += `const _layoutPathList = [${layoutDecls.map((d) => d.path).join(", ")}];
36670
37013
  `;
36671
- src2 += `const _pageCompiled = (() => { try { setVskHydrate(true); return compileFile(_pageSrc, { sourcePath: _pagePath }); } catch { return null; } finally { setVskHydrate(false); } })();
37014
+ src2 += `const _layoutCompiledList = [
37015
+ ${layoutDecls.map((d) => " " + d.compiled + ",").join("\n")}
37016
+ ];
36672
37017
  `;
36673
37018
  src2 += errorVars;
36674
37019
  } else {
@@ -36714,7 +37059,7 @@ ${compRegEntries.join("\n")}
36714
37059
  registryCode = "const __componentRegistry = new Map();\n";
36715
37060
  }
36716
37061
  let htmlFnCode;
36717
- if (hasLayout || hasAncestorLayout) {
37062
+ if (layoutDecls.length > 0) {
36718
37063
  htmlFnCode = [
36719
37064
  "async function __renderErrorBody(props) {",
36720
37065
  ' if (!_errorSrc) throw props.error || new Error("Internal Server Error");',
@@ -36740,7 +37085,14 @@ ${compRegEntries.join("\n")}
36740
37085
  " const stack = err && typeof err === 'object' && 'stack' in err ? String(err.stack) : '';",
36741
37086
  " page = { body: await __renderErrorBody({ params, statusCode: 500, error: __expose ? message : 'Internal Server Error', stack: __expose ? stack : '', url: requestUrl || '' }), head: '' };",
36742
37087
  " }",
36743
- " const html = await renderFullPage(_layoutSrc, _layoutComp, { params, children: (caughtError ? '<!--vesk-ssr-error:' + (caughtError && typeof caughtError === 'object' && 'message' in caughtError ? encodeURIComponent(__expose ? String(caughtError.message) : 'Internal Server Error') : '') + '-->' : '') + page.body }, __componentRegistry, { hydrate: true, cached: _layoutCompiled" + bakedOptions + clientScriptOption + dataScriptOption + ", pageHead: page.head, sourcePath: _layoutPath });",
37088
+ " let _body = (caughtError ? '<!--vesk-ssr-error:' + (caughtError && typeof caughtError === 'object' && 'message' in caughtError ? encodeURIComponent(__expose ? String(caughtError.message) : 'Internal Server Error') : '') + '-->' : '') + page.body;",
37089
+ " let _head = page.head || '';",
37090
+ " for (let _i = _layoutSrcList.length - 1; _i > 0; _i--) {",
37091
+ " const _inner = await renderPage(_layoutSrcList[_i], _layoutCompList[_i], { params, children: _body }, __componentRegistry, { hydrate: true, cached: _layoutCompiledList[_i], sourcePath: _layoutPathList[_i] });",
37092
+ " _body = _inner.body;",
37093
+ " if (_inner.head) _head = _inner.head + _head;",
37094
+ " }",
37095
+ " const html = await renderFullPage(_layoutSrcList[0], _layoutCompList[0], { params, children: _body }, __componentRegistry, { hydrate: true, cached: _layoutCompiledList[0]" + bakedOptions + clientScriptOption + dataScriptOption + ", pageHead: _head, sourcePath: _layoutPathList[0] });",
36744
37096
  " return new Response(html, { headers: { 'Content-Type': 'text/html' }, status: caughtError ? 500 : 200 });",
36745
37097
  " });",
36746
37098
  "}",
@@ -36791,7 +37143,7 @@ ${compRegEntries.join("\n")}
36791
37143
  }
36792
37144
  let dataCode;
36793
37145
  const exposeErr = "process.env.NODE_ENV !== 'production'";
36794
- if (hasLayout || hasAncestorLayout) {
37146
+ if (layoutDecls.length > 0) {
36795
37147
  dataCode = [
36796
37148
  " if (request.headers.get('x-vesk-data') === '1') {",
36797
37149
  " let dataPage;",
@@ -36802,8 +37154,12 @@ ${compRegEntries.join("\n")}
36802
37154
  " const message = err && typeof err === 'object' && 'message' in err ? String(err.message) : String(err);",
36803
37155
  ` return new Response(JSON.stringify({ error: ${exposeErr} ? message : 'Internal Server Error' }), { status: 500, headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', Vary: 'x-vesk-data' } });`,
36804
37156
  " }",
36805
- " const dataLayout = await renderPage(_layoutSrc, _layoutComp, { params, children: '' }, __componentRegistry, { hydrate: true, cached: _layoutCompiled, sourcePath: _layoutPath });",
36806
- " return new Response(JSON.stringify({ path: url.pathname, params, props: dataPage.props || { params }, head: (dataLayout.head || '') + (dataPage.head || '') }), {",
37157
+ " let _dataHead = dataPage.head || '';",
37158
+ " for (let _i = _layoutSrcList.length - 1; _i >= 0; _i--) {",
37159
+ " const _dl = await renderPage(_layoutSrcList[_i], _layoutCompList[_i], { params, children: '' }, __componentRegistry, { hydrate: true, cached: _layoutCompiledList[_i], sourcePath: _layoutPathList[_i] });",
37160
+ " _dataHead = (_dl.head || '') + _dataHead;",
37161
+ " }",
37162
+ " return new Response(JSON.stringify({ path: url.pathname, params, props: dataPage.props || { params }, head: _dataHead }), {",
36807
37163
  " headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store', Vary: 'x-vesk-data' },",
36808
37164
  " });",
36809
37165
  " }",
@@ -36869,12 +37225,12 @@ ${compRegEntries.join("\n")}
36869
37225
  ].join("\n");
36870
37226
  }
36871
37227
  let registerActionsCode;
36872
- if (hasLayout || hasAncestorLayout) {
37228
+ if (layoutDecls.length > 0) {
36873
37229
  registerActionsCode = [
36874
37230
  "async function __registerActions() {",
36875
37231
  " if (__actionsRegistered) return;",
36876
37232
  " __actionsRegistered = true;",
36877
- " compileFile(_layoutSrc, { sourcePath: _layoutPath });",
37233
+ " for (let _i = 0; _i < _layoutSrcList.length; _i++) compileFile(_layoutSrcList[_i], { sourcePath: _layoutPathList[_i] });",
36878
37234
  " compileFile(_pageSrc, { sourcePath: _pagePath });",
36879
37235
  "}",
36880
37236
  ""
@@ -37487,7 +37843,7 @@ init_esbuild_fallback();
37487
37843
  init_strip_ts();
37488
37844
  init_parser();
37489
37845
  init_client_codegen();
37490
- import { readFileSync as readFileSync9, existsSync as existsSync9, writeFileSync as writeFileSync3, unlinkSync as unlinkSync3, statSync as statSync3, rmSync } from "node:fs";
37846
+ import { readFileSync as readFileSync9, existsSync as existsSync9, writeFileSync as writeFileSync3, unlinkSync as unlinkSync3, statSync as statSync3, rmSync, mkdtempSync } from "node:fs";
37491
37847
  import { resolve as resolve10, join as join6, dirname as dirname6, relative as relative2, sep } from "node:path";
37492
37848
  import { fileURLToPath as fileURLToPath2 } from "node:url";
37493
37849
  init_vsk_imports();
@@ -37622,8 +37978,113 @@ function demoteExports(code) {
37622
37978
  for (const e of edits) code = code.slice(0, e.start) + e.text + code.slice(e.end);
37623
37979
  return code;
37624
37980
  }
37625
- function stripChunkImports(code) {
37626
- return demoteExports(removeCompiledNodes(code, isAnyImport));
37981
+ function hasChunkImports(code) {
37982
+ try {
37983
+ const ast = parse4(code);
37984
+ return (ast.body ?? []).some((n) => n.type === "ImportDeclaration");
37985
+ } catch {
37986
+ return false;
37987
+ }
37988
+ }
37989
+ function resolveImportSource(src2, filePath) {
37990
+ if (src2.startsWith("./") || src2.startsWith("../")) {
37991
+ return resolve10(dirname6(filePath), src2) + ".ts";
37992
+ }
37993
+ return src2;
37994
+ }
37995
+ var ChunkImports = class {
37996
+ bySource = /* @__PURE__ */ new Map();
37997
+ aborted = false;
37998
+ abortReason = null;
37999
+ fail(reason, code) {
38000
+ if (!this.aborted) {
38001
+ this.aborted = true;
38002
+ this.abortReason = reason;
38003
+ }
38004
+ return code;
38005
+ }
38006
+ /** Folds one file's imports into the merged set and returns the code with its imports stripped. */
38007
+ add(code, filePath) {
38008
+ if (!code || this.aborted) return code;
38009
+ let ast;
38010
+ try {
38011
+ ast = parse4(code);
38012
+ } catch {
38013
+ return this.fail(`unparseable contribution from ${filePath}`, code);
38014
+ }
38015
+ const body = ast.body ?? [];
38016
+ const ranges = [];
38017
+ for (const raw2 of body) {
38018
+ const node = raw2;
38019
+ if (node.type !== "ImportDeclaration" || typeof node.start !== "number" || typeof node.end !== "number") continue;
38020
+ const src2 = node.source?.value;
38021
+ if (typeof src2 !== "string") continue;
38022
+ const resolved = resolveImportSource(src2, filePath);
38023
+ let group = this.bySource.get(resolved);
38024
+ if (!group) {
38025
+ group = { named: /* @__PURE__ */ new Map() };
38026
+ this.bySource.set(resolved, group);
38027
+ }
38028
+ for (const spec of node.specifiers ?? []) {
38029
+ const s = spec;
38030
+ const local = s.local?.name;
38031
+ if (typeof local !== "string") return this.fail(`nameless specifier from '${resolved}' in ${filePath}`, code);
38032
+ if (s.type === "ImportDefaultSpecifier") {
38033
+ if (group.default && group.default.local !== local) return this.fail(`conflicting default imports from '${resolved}' in ${filePath}`, code);
38034
+ group.default = { kind: "default", local };
38035
+ } else if (s.type === "ImportNamespaceSpecifier") {
38036
+ if (group.namespace && group.namespace.local !== local) return this.fail(`conflicting namespace imports from '${resolved}' in ${filePath}`, code);
38037
+ group.namespace = { kind: "namespace", local };
38038
+ } else if (s.type === "ImportSpecifier") {
38039
+ const imported = s.imported?.name;
38040
+ if (typeof imported !== "string") return this.fail(`nameless named-import from '${resolved}' in ${filePath}`, code);
38041
+ const existing = group.named.get(imported);
38042
+ if (existing && existing.local !== local) return this.fail(`'${imported}' from '${resolved}' bound to both '${existing.local}' and '${local}' in ${filePath}`, code);
38043
+ group.named.set(imported, { kind: "named", local, imported });
38044
+ }
38045
+ }
38046
+ let cut = node.end;
38047
+ if (code[cut] === ";") cut++;
38048
+ ranges.push([node.start, cut]);
38049
+ }
38050
+ if (ranges.length === 0) return code;
38051
+ return removeRanges(code, ranges);
38052
+ }
38053
+ /** True when every file parsed and merged cleanly (no conflict, no parse abort). */
38054
+ get ok() {
38055
+ return !this.aborted;
38056
+ }
38057
+ /** Why the merge aborted (null when `ok`). Surfaced by the assembler. */
38058
+ get reason() {
38059
+ return this.abortReason;
38060
+ }
38061
+ /** Renders the deduped import block (empty string when there are no imports). */
38062
+ render() {
38063
+ if (this.aborted || this.bySource.size === 0) return "";
38064
+ const lines = [];
38065
+ const sources = [...this.bySource.keys()].sort();
38066
+ for (const src2 of sources) {
38067
+ const g2 = this.bySource.get(src2);
38068
+ const parts = [];
38069
+ if (g2.default) parts.push(`import ${g2.default.local} from ${JSON.stringify(src2)}`);
38070
+ if (g2.namespace) parts.push(`import * as ${g2.namespace.local} from ${JSON.stringify(src2)}`);
38071
+ const named = [...g2.named.values()].sort((a, b) => a.imported < b.imported ? -1 : 1);
38072
+ if (named.length > 0) {
38073
+ const specs = named.map((sp) => sp.imported === sp.local ? sp.local : `${sp.imported} as ${sp.local}`).join(", ");
38074
+ parts.push(`import { ${specs} } from ${JSON.stringify(src2)}`);
38075
+ }
38076
+ lines.push(parts.join("\n"));
38077
+ }
38078
+ return lines.join("\n");
38079
+ }
38080
+ };
38081
+ function removeRanges(code, ranges) {
38082
+ const sorted = [...ranges].sort((a, b) => b[0] - a[0]);
38083
+ let out = code;
38084
+ for (const [start, end] of sorted) {
38085
+ out = out.slice(0, start) + out.slice(end);
38086
+ }
38087
+ return out.trim();
37627
38088
  }
37628
38089
  function scopeFileContribution(code) {
37629
38090
  const head = extractCompiledNodes(code, isModuleLevel);
@@ -37721,7 +38182,7 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37721
38182
  function stripExports(code) {
37722
38183
  return removeCompiledNodes(code, isComponentExport);
37723
38184
  }
37724
- function compileFile2(filePath, resolvedName, output) {
38185
+ function compileFile2(filePath, resolvedName, output, imports) {
37725
38186
  if (seen.has(filePath)) return;
37726
38187
  seen.add(filePath);
37727
38188
  const cachedEntry = cache2?.files.get(filePath);
@@ -37738,8 +38199,10 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37738
38199
  const cached = cacheUsable ? cachedEntry : void 0;
37739
38200
  if (cached && cacheUsable) {
37740
38201
  cachedFileHits++;
37741
- for (const dep of cached.imports) compileFile2(dep, cache2?.files.get(dep)?.actualName ?? "", output);
37742
- const cachedFileCode = [cached.compCode, cached.hydCode].filter(Boolean).join("\n");
38202
+ for (const dep of cached.imports) compileFile2(dep, cache2?.files.get(dep)?.actualName ?? "", output, imports);
38203
+ const cachedComp = cached.compCode ? imports.add(cached.compCode, filePath).replace(/^\n+/, "").replace(/\n+$/, "") : "";
38204
+ const cachedHyd = cached.hydCode ? imports.add(cached.hydCode, filePath).replace(/__components/g, "__hydrators").replace(/^\n+/, "").replace(/\n+$/, "") : "";
38205
+ const cachedFileCode = [cachedComp, cachedHyd].filter(Boolean).join("\n");
37743
38206
  if (cachedFileCode.trim()) output.push(scopeFileContribution(cachedFileCode));
37744
38207
  for (const n of cached.runtimeNames) runtimeImportNames.add(n);
37745
38208
  if (cached.actualName && resolvedName !== null && cached.actualName !== resolvedName) {
@@ -37754,10 +38217,12 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37754
38217
  src2 = inlineMdContentAttrs(src2, dirname6(filePath), guessProjectRoots(appDir));
37755
38218
  }
37756
38219
  const namesBefore = cache2 ? new Set(runtimeImportNames) : null;
37757
- const importedPaths = resolveVskImports(filePath, (p, n) => compileFile2(p, n || "", output));
38220
+ const importedPaths = resolveVskImports(filePath, (p, n) => compileFile2(p, n, output, imports));
37758
38221
  const { comp: rawComp, hyd: rawHyd, name: actualName } = compileClientBoth(src2, null, filePath);
37759
- const compCode = rawComp ? stripChunkImports(stripExports(stripVskImports(stripRuntimeImport(rawComp)))).replace(/^\n+/, "").replace(/\n+$/, "") : "";
37760
- const hydCode = rawHyd ? stripChunkImports(stripExports(stripVskImports(stripRuntimeImport(rawHyd)))).replace(/__components/g, "__hydrators").replace(/^\n+/, "").replace(/\n+$/, "") : "";
38222
+ const compWithImports = rawComp ? stripExports(stripVskImports(stripRuntimeImport(rawComp))) : "";
38223
+ const hydWithImports = rawHyd ? stripExports(stripVskImports(stripRuntimeImport(rawHyd))) : "";
38224
+ const compCode = compWithImports ? imports.add(compWithImports, filePath).replace(/^\n+/, "").replace(/\n+$/, "") : "";
38225
+ const hydCode = hydWithImports ? imports.add(hydWithImports, filePath).replace(/__components/g, "__hydrators").replace(/^\n+/, "").replace(/\n+$/, "") : "";
37761
38226
  if (rawComp) collectRuntimeImports(rawComp);
37762
38227
  if (rawHyd) collectRuntimeImports(rawHyd);
37763
38228
  if (returnEdited && only.has(filePath)) {
@@ -37775,8 +38240,8 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37775
38240
  cache2.files.set(filePath, {
37776
38241
  mtimeMs: st.mtimeMs,
37777
38242
  size: st.size,
37778
- compCode,
37779
- hydCode,
38243
+ compCode: compWithImports,
38244
+ hydCode: hydWithImports,
37780
38245
  actualName,
37781
38246
  runtimeNames: [...runtimeImportNames].filter((n) => !namesBefore.has(n)),
37782
38247
  imports: importedPaths
@@ -37806,37 +38271,41 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37806
38271
  let walkSplit2 = function(nodes, _chain) {
37807
38272
  for (const node of nodes) {
37808
38273
  const chunkCode = [];
38274
+ const chunkImports = new ChunkImports();
37809
38275
  const pagePath = resolve10(appDir, node.sourceDir, "page.vsk");
37810
38276
  if (node.page && existsSync9(pagePath)) {
37811
- compileFile2(pagePath, node.page, chunkCode);
38277
+ compileFile2(pagePath, node.page, chunkCode, chunkImports);
37812
38278
  }
37813
38279
  const layoutPath = resolve10(appDir, node.sourceDir, "layout.vsk");
37814
38280
  if (node.layout && existsSync9(layoutPath)) {
37815
- compileFile2(layoutPath, node.layout, chunkCode);
38281
+ compileFile2(layoutPath, node.layout, chunkCode, chunkImports);
37816
38282
  }
37817
38283
  const errorPath = resolve10(appDir, node.sourceDir, "error.vsk");
37818
38284
  if (node.error && existsSync9(errorPath)) {
37819
- compileFile2(errorPath, node.error, chunkCode);
38285
+ compileFile2(errorPath, node.error, chunkCode, chunkImports);
37820
38286
  }
37821
38287
  const notFoundPath = resolve10(appDir, node.sourceDir, "not-found.vsk");
37822
38288
  if (node.notFound && existsSync9(notFoundPath)) {
37823
- compileFile2(notFoundPath, node.notFound, chunkCode);
38289
+ compileFile2(notFoundPath, node.notFound, chunkCode, chunkImports);
37824
38290
  }
37825
38291
  const offlinePath = resolve10(appDir, node.sourceDir, "offline.vsk");
37826
38292
  if (node.offline && existsSync9(offlinePath)) {
37827
- compileFile2(offlinePath, node.offline, chunkCode);
38293
+ compileFile2(offlinePath, node.offline, chunkCode, chunkImports);
37828
38294
  }
37829
38295
  const networkPath = resolve10(appDir, node.sourceDir, "network.vsk");
37830
38296
  if (node.network && existsSync9(networkPath)) {
37831
- compileFile2(networkPath, node.network, chunkCode);
38297
+ compileFile2(networkPath, node.network, chunkCode, chunkImports);
37832
38298
  }
37833
38299
  const loadingPath = resolve10(appDir, node.sourceDir, "loading.vsk");
37834
38300
  if (node.loading && existsSync9(loadingPath)) {
37835
- compileFile2(loadingPath, node.loading, chunkCode);
38301
+ compileFile2(loadingPath, node.loading, chunkCode, chunkImports);
37836
38302
  }
37837
38303
  if (chunkCode.length > 0) {
37838
38304
  const chunkName = `page-${buildChunkName(node)}.js`;
37839
- chunkEntries.push({ name: chunkName, code: chunkCode.join("\n\n"), node });
38305
+ if (!chunkImports.ok) console.error("[vesk] chunk import merge aborted for", chunkName + ":", chunkImports.reason);
38306
+ const head = chunkImports.render();
38307
+ const code = (head ? head + "\n\n" : "") + chunkCode.join("\n\n");
38308
+ chunkEntries.push({ name: chunkName, code, node });
37840
38309
  }
37841
38310
  walkSplit2(node.children || [], [..._chain, node]);
37842
38311
  }
@@ -37852,25 +38321,60 @@ async function generateClientBundle(routeTree, appDir, componentMap, options2) {
37852
38321
  const chunkEntries = [];
37853
38322
  walkSplit2(routeTree, []);
37854
38323
  const sharedCode = [];
38324
+ const sharedImports = new ChunkImports();
37855
38325
  const compMap = componentMap || /* @__PURE__ */ new Map();
37856
38326
  for (const [compName, compPath] of compMap) {
37857
- compileFile2(compPath, compName, sharedCode);
38327
+ compileFile2(compPath, compName, sharedCode, sharedImports);
37858
38328
  }
37859
38329
  if (sharedCode.length > 0) {
37860
- chunkEntries.push({ name: "shared.js", code: sharedCode.join("\n\n"), node: null });
38330
+ if (!sharedImports.ok) console.error("[vesk] chunk import merge aborted for shared.js:", sharedImports.reason);
38331
+ const head = sharedImports.render();
38332
+ const code = (head ? head + "\n\n" : "") + sharedCode.join("\n\n");
38333
+ chunkEntries.push({ name: "shared.js", code, node: null });
37861
38334
  }
37862
- for (const entry of chunkEntries) {
37863
- if (entry.code.trim()) {
37864
- chunks.push({
37865
- name: entry.name,
37866
- code: `(()=>{
38335
+ const chunkIIFE = (body) => `(()=>{
37867
38336
  const __components = globalThis.__components || (globalThis.__components = {});
37868
38337
  const __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});
37869
- ${entry.code}
38338
+ ${body}
37870
38339
  })();
37871
- `
37872
- });
38340
+ `;
38341
+ for (const entry of chunkEntries) {
38342
+ if (!entry.code.trim()) continue;
38343
+ let finalCode;
38344
+ if (hasChunkImports(entry.code)) {
38345
+ const tmpBase = mkdtempSync(join6(resolve10(appDir, ".."), "tmp-vesk-chunk-"));
38346
+ const tmpFile = join6(tmpBase, "entry.js");
38347
+ const toBundle = `const __components = globalThis.__components || (globalThis.__components = {});
38348
+ const __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});
38349
+ ${entry.code}
38350
+ `;
38351
+ writeFileSync3(tmpFile, toBundle);
38352
+ try {
38353
+ const result2 = await build({
38354
+ entryPoints: [tmpFile],
38355
+ bundle: true,
38356
+ format: "iife",
38357
+ platform: "browser",
38358
+ write: false,
38359
+ logLevel: "silent",
38360
+ loader: { ".js": "tsx" }
38361
+ });
38362
+ finalCode = result2.outputFiles[0].text;
38363
+ } catch (e) {
38364
+ const err = e;
38365
+ console.error("[vesk] chunk bundle failed", entry.name, err?.errors?.map((x) => x.text).join(" | ") || err?.message || String(e));
38366
+ const stripped = demoteExports(removeCompiledNodes(entry.code, isAnyImport));
38367
+ finalCode = chunkIIFE(stripped);
38368
+ } finally {
38369
+ try {
38370
+ rmSync(tmpBase, { recursive: true, force: true });
38371
+ } catch {
38372
+ }
38373
+ }
38374
+ } else {
38375
+ finalCode = chunkIIFE(entry.code);
37873
38376
  }
38377
+ chunks.push({ name: entry.name, code: finalCode });
37874
38378
  }
37875
38379
  annotate2(routeTree);
37876
38380
  const mainKey = JSON.stringify(routeTree) + "|" + [...runtimeImportNames].sort().join(",") + `|${!!options2?.hmr}|${!!options2?.importRuntime}|${options2?.routeDataCache ?? ""}`;
@@ -38623,8 +39127,7 @@ async function startProdServer(outDir, options) {
38623
39127
  }
38624
39128
  const appDir = resolve13(projectDir, "app");
38625
39129
  const pageCssUrls = resolveCssUrls({
38626
- tailwind: hasBuiltTailwindCss(outDir),
38627
- userCss: hasUserCss(appDir)
39130
+ enabled: hasBuiltGlobalCss(outDir)
38628
39131
  });
38629
39132
  const nfPath = resolve13(appDir, "not-found.vsk");
38630
39133
  let notFoundHtml = null;
@@ -38952,40 +39455,24 @@ async function build2(appDir, options2) {
38952
39455
  const cssSourcePath = resolveUserCssPath(appDir);
38953
39456
  if (cssSourcePath !== null) {
38954
39457
  const cssContent = readFileSync18(cssSourcePath, "utf-8");
38955
- const userCss = stripTailwindDirectives(cssContent);
38956
- const userCssTarget = resolve21(outDir2, "static", "global.css");
38957
- writeFileSync10(userCssTarget, userCss, "utf-8");
38958
- console.error(`vesk build: css \u2192 static/global.css (${userCss.length} bytes)`);
38959
- const twCssTarget = resolve21(outDir2, "static", "_tailwind.css");
39458
+ const cssTarget = resolve21(outDir2, "static", "global.css");
38960
39459
  const tailwindActive = isTailwindPlugin(pluginsPipelines);
38961
- if (!tailwindActive) {
38962
- writeFileSync10(twCssTarget, "", "utf-8");
38963
- console.error("vesk build: css \u2192 static/_tailwind.css (empty, tailwind plugin inactive)");
38964
- } else {
38965
- let twCss = cssContent;
39460
+ let finalCss = cssContent;
39461
+ if (tailwindActive) {
38966
39462
  for (const plugin of pluginsPipelines) {
38967
39463
  if (typeof plugin.onCSS === "function") {
38968
- const result2 = await plugin.onCSS(twCss, cssSourcePath);
39464
+ const result2 = await plugin.onCSS(finalCss, cssSourcePath);
38969
39465
  if (result2 !== null && typeof result2 === "string") {
38970
- twCss = result2;
39466
+ finalCss = result2;
38971
39467
  }
38972
39468
  }
38973
39469
  }
38974
- const hasUnresolvedTailwindImport = /@import\s+['"]tailwindcss['"]/.test(twCss);
38975
- if (hasUnresolvedTailwindImport) {
38976
- const lines = twCss.split("\n").filter((l) => !/^\s*@import\s+['"]tailwindcss['"]/.test(l));
38977
- twCss = lines.join("\n").trim();
38978
- if (twCss.length === 0) {
38979
- writeFileSync10(twCssTarget, "", "utf-8");
38980
- console.error("vesk build: css \u2192 static/_tailwind.css (empty, tailwind unresolved)");
38981
- } else {
38982
- writeFileSync10(twCssTarget, twCss, "utf-8");
38983
- console.error(`vesk build: css \u2192 static/_tailwind.css (${twCss.length} bytes, tailwind partially unresolved)`);
38984
- }
38985
- } else {
38986
- writeFileSync10(twCssTarget, twCss, "utf-8");
38987
- console.error(`vesk build: css \u2192 static/_tailwind.css (${twCss.length} bytes)`);
38988
- }
39470
+ }
39471
+ writeFileSync10(cssTarget, finalCss, "utf-8");
39472
+ if (tailwindActive) {
39473
+ console.error(`vesk build: css \u2192 static/global.css (${finalCss.length} bytes)`);
39474
+ } else {
39475
+ console.error(`vesk build: css \u2192 static/global.css (${finalCss.length} bytes, tailwind plugin inactive)`);
38989
39476
  }
38990
39477
  }
38991
39478
  const { scanRoutes: scanRoutes2, scanComponents } = await resolveCompilerApi("router.js");
@@ -39105,8 +39592,7 @@ async function build2(appDir, options2) {
39105
39592
  if (options2?.ssg) {
39106
39593
  const { generateSsgRoutes: generateSsgRoutes2 } = await Promise.resolve().then(() => (init_static(), static_exports));
39107
39594
  const cssUrls = resolveCssUrls({
39108
- tailwind: hasBuiltTailwindCss(outDir2),
39109
- userCss: hasUserCss(appDir)
39595
+ enabled: hasBuiltGlobalCss(outDir2)
39110
39596
  });
39111
39597
  prerenderedRoutes = await generateSsgRoutes2(routeTree, appDir, outDir2, pluginsPipelines, pluginHeadExtra, cssUrls);
39112
39598
  console.error(`vesk build: ssg \u2192 prerendered/ (${prerenderedRoutes.length} pages)`);
@@ -39185,7 +39671,7 @@ init_seo_audit();
39185
39671
 
39186
39672
  // src/dev-server.ts
39187
39673
  import { readFileSync as readFileSync33, watch, statSync as statSync21, existsSync as existsSync37, readdirSync as readdirSync13 } from "node:fs";
39188
- import { resolve as resolve36, extname as extname8, join as join21 } from "node:path";
39674
+ import { resolve as resolve36, extname as extname8, join as join20 } from "node:path";
39189
39675
  import { createServer as createServer2 } from "node:http";
39190
39676
  import { WebSocketServer as WebSocketServer2 } from "ws";
39191
39677
 
@@ -39550,6 +40036,19 @@ function collectTrackedNames2(body) {
39550
40036
  }
39551
40037
  return names;
39552
40038
  }
40039
+ function transformTrackedInit2(init, tracked2) {
40040
+ if (!init)
40041
+ return init;
40042
+ let expr = null;
40043
+ try {
40044
+ const prog = parse4(`(${init})`);
40045
+ expr = prog.body?.[0]?.type === "ExpressionStatement" ? prog.body[0].expression ?? null : null;
40046
+ } catch {
40047
+ }
40048
+ if (!expr)
40049
+ return init;
40050
+ return transformTracked2({ raw: init, ast: expr }, tracked2);
40051
+ }
39553
40052
  var NON_BUBBLING_EVENTS2 = /* @__PURE__ */ new Set([
39554
40053
  "focus",
39555
40054
  "blur",
@@ -39592,6 +40091,7 @@ var Ctx2 = class {
39592
40091
  effects = [];
39593
40092
  c = 0;
39594
40093
  importedNames = /* @__PURE__ */ new Set();
40094
+ linkNames = /* @__PURE__ */ new Set();
39595
40095
  delegatedEvents = /* @__PURE__ */ new Set();
39596
40096
  directEvents = /* @__PURE__ */ new Set();
39597
40097
  hydrate = false;
@@ -39648,7 +40148,7 @@ function emitNode2(ctx2, node, tracked2, effectsVar, parentVar, compPrefix = "__
39648
40148
  return emitDynamicBinding2(ctx2, node, tracked2, effectsVar);
39649
40149
  if (node instanceof TrackDecl) {
39650
40150
  const cellName = node.rawName || node.name;
39651
- const init = stripTrackGeneric(node.init);
40151
+ const init = transformTrackedInit2(stripTrackGeneric(node.init), tracked2);
39652
40152
  ctx2.push(`const ${cellName} = ${init};`);
39653
40153
  return null;
39654
40154
  }
@@ -39949,6 +40449,10 @@ function emitComponentCall2(ctx2, node, tracked2, effectsVar, parentVar, compPre
39949
40449
  ctx2.push(`const ${frag} = (() => { const $f = document.createDocumentFragment();`);
39950
40450
  const savedWalker = ctx2.walker;
39951
40451
  const savedEffects = ctx2.effects;
40452
+ const wipeMount = ctx2.linkNames.has(node.componentName);
40453
+ const savedHydrate = ctx2.hydrate;
40454
+ if (wipeMount)
40455
+ ctx2.hydrate = false;
39952
40456
  ctx2.walker = walkerVar;
39953
40457
  ctx2.effects = [];
39954
40458
  for (const child of node.children) {
@@ -39960,6 +40464,7 @@ function emitComponentCall2(ctx2, node, tracked2, effectsVar, parentVar, compPre
39960
40464
  ctx2.push(effectsVar ? `${effectsVar}.push(${effectBlockToHandlerExpr2(eff)});` : eff);
39961
40465
  ctx2.effects = savedEffects;
39962
40466
  ctx2.walker = savedWalker;
40467
+ ctx2.hydrate = savedHydrate;
39963
40468
  ctx2.push(`return $f; })();`);
39964
40469
  propsEntries.push(`children: ${frag}`);
39965
40470
  ctx2.push(`const ${v} = ${awaitKw}${access}({ ${propsEntries.join(", ")} }, __registry, ${walkerVar});`);
@@ -40022,7 +40527,7 @@ function emitTryCatch2(ctx2, node, tracked2, effectsVar, parentVar) {
40022
40527
  ctx2.push(indent3(`const __cl = [];`));
40023
40528
  }
40024
40529
  for (const child of body) {
40025
- const childVar = emitNode2(ctx2, child, tracked2, isCatch ? null : effArr, void 0, compPrefix);
40530
+ const childVar = emitNode2(ctx2, child, tracked2, isCatch ? null : effArr, hydMode ? void 0 : "__p", compPrefix);
40026
40531
  if (childVar) {
40027
40532
  if (hydMode)
40028
40533
  ctx2.push(indent3(`__cl.push(${childVar});`));
@@ -40141,7 +40646,7 @@ function emitOpaque2(ctx2, node, tracked2, effTarget, parentVar) {
40141
40646
  ctx2.push(`if (${condExpr}) { ${asyncKw}${conRenderName}(); }` + (hasElse ? ` else { ${asyncKw}${altRenderName}(); }` : ""));
40142
40647
  const renderBranch = `if (__nv) { ${asyncKw}${conRenderName}(); }` + (hasElse ? ` else { ${asyncKw}${altRenderName}(); }` : "");
40143
40648
  const effectBody = `effect(${ctx2.isAsyncScope ? "async () => {" : "() => {"}
40144
- if (__first) { __first = false; return; }
40649
+ if (__first) { __first = false; __iv = ${condExpr}; return; }
40145
40650
  const __nv = ${condExpr};
40146
40651
  if (__nv !== __iv) {
40147
40652
  for (const e of ${effectsVar}) destroy_block(e);
@@ -40151,6 +40656,8 @@ function emitOpaque2(ctx2, node, tracked2, effTarget, parentVar) {
40151
40656
  __iv = __nv;
40152
40657
  }
40153
40658
  });`;
40659
+ if (!isReactiveExpression2(node.condition, tracked2))
40660
+ return null;
40154
40661
  if (effTarget) {
40155
40662
  ctx2.push(`${effTarget}.push((() => {
40156
40663
  let __iv = ${condExpr};
@@ -40182,33 +40689,37 @@ function emitWhileLoop2(ctx2, node, tracked2, parentVar) {
40182
40689
  ctx2.push(`const ${renderLoop} = ${ctx2.isAsyncScope ? "async () => {" : "() => {"}`);
40183
40690
  if (!hyd)
40184
40691
  ctx2.push(indent3(`const __p = ${anchor}.parentNode;`));
40692
+ if (!hyd)
40693
+ ctx2.push(indent3(`const __b = document.createDocumentFragment();`));
40185
40694
  if (hyd)
40186
40695
  ctx2.push(indent3(`const __cl = [];`));
40187
40696
  if (node.isDoWhile) {
40188
40697
  ctx2.push(indent3(`do {`));
40189
40698
  for (const n of node.bodyTemplate) {
40190
- const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
40699
+ const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__b");
40191
40700
  if (v) {
40192
40701
  if (hyd)
40193
40702
  ctx2.push(indent3(`__cl.push(${v});`));
40194
40703
  else
40195
- ctx2.push(indent3(`__p.insertBefore(${v}, ${endAnchor});`));
40704
+ ctx2.push(indent3(`__b.appendChild(${v});`));
40196
40705
  }
40197
40706
  }
40198
40707
  ctx2.push(indent3(`} while (${condExpr});`));
40199
40708
  } else {
40200
40709
  ctx2.push(indent3(`while (${condExpr}) {`));
40201
40710
  for (const n of node.bodyTemplate) {
40202
- const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
40711
+ const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__b");
40203
40712
  if (v) {
40204
40713
  if (hyd)
40205
40714
  ctx2.push(indent3(`__cl.push(${v});`));
40206
40715
  else
40207
- ctx2.push(indent3(`__p.insertBefore(${v}, ${endAnchor});`));
40716
+ ctx2.push(indent3(`__b.appendChild(${v});`));
40208
40717
  }
40209
40718
  }
40210
40719
  ctx2.push(indent3(`}`));
40211
40720
  }
40721
+ if (!hyd)
40722
+ ctx2.push(indent3(`__p.insertBefore(__b, ${endAnchor});`));
40212
40723
  if (hyd)
40213
40724
  ctx2.push(indent3(`__place(${anchor}, ${endAnchor}, __cl, ${parent});`));
40214
40725
  ctx2.push(`};`);
@@ -40220,7 +40731,7 @@ function emitWhileLoop2(ctx2, node, tracked2, parentVar) {
40220
40731
  let __iv = (${condExpr});
40221
40732
  let __first = true;
40222
40733
  effect(${ctx2.isAsyncScope ? "async () => {" : "() => {"}
40223
- if (__first) { __first = false; return; }
40734
+ if (__first) { __first = false; __iv = (${condExpr}); return; }
40224
40735
  if (__busy) return;
40225
40736
  const __nv = (${condExpr});
40226
40737
  if (__nv !== __iv) {
@@ -40251,39 +40762,46 @@ function emitForLoop2(ctx2, node, tracked2, parentVar) {
40251
40762
  ctx2.push(`const ${renderLoop} = ${ctx2.isAsyncScope ? "async () => {" : "() => {"}`);
40252
40763
  if (!hyd)
40253
40764
  ctx2.push(indent3(`const __p = ${anchor}.parentNode;`));
40765
+ if (!hyd)
40766
+ ctx2.push(indent3(`const __b = document.createDocumentFragment();`));
40254
40767
  if (hyd)
40255
40768
  ctx2.push(indent3(`const __cl = [];`));
40256
40769
  if (node.kind === "for-in") {
40257
40770
  const srcExpr = transformTracked2(node.condition, tracked2);
40258
40771
  ctx2.push(indent3(`for (${node.init} of (Array.isArray(${srcExpr}) ? ${srcExpr} : (${srcExpr} == null ? [] : Object.keys(${srcExpr})))) {`));
40259
40772
  for (const n of node.bodyTemplate) {
40260
- const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
40773
+ const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__b");
40261
40774
  if (v) {
40262
40775
  if (hyd)
40263
40776
  ctx2.push(indent3(`__cl.push(${v});`));
40264
40777
  else
40265
- ctx2.push(indent3(`__p.insertBefore(${v}, ${endAnchor});`));
40778
+ ctx2.push(indent3(`__b.appendChild(${v});`));
40266
40779
  }
40267
40780
  }
40268
40781
  ctx2.push(indent3(`}`));
40269
40782
  } else {
40270
40783
  const condExpr = transformTracked2(node.condition, tracked2);
40271
- if (node.init)
40272
- ctx2.push(indent3(`${node.init}`));
40273
- ctx2.push(indent3(`while (${condExpr}) {`));
40784
+ let initPart = (node.init || "").trim();
40785
+ let updatePart = (node.update || "").trim();
40786
+ if (initPart.endsWith(";"))
40787
+ initPart = initPart.slice(0, -1).trim();
40788
+ if (updatePart.endsWith(";"))
40789
+ updatePart = updatePart.slice(0, -1).trim();
40790
+ const head = initPart ? `${initPart}; ${condExpr}` : `; ${condExpr}`;
40791
+ ctx2.push(indent3(`for (${head}; ${updatePart}) {`));
40274
40792
  for (const n of node.bodyTemplate) {
40275
- const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
40793
+ const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__b");
40276
40794
  if (v) {
40277
40795
  if (hyd)
40278
40796
  ctx2.push(indent3(`__cl.push(${v});`));
40279
40797
  else
40280
- ctx2.push(indent3(`__p.insertBefore(${v}, ${endAnchor});`));
40798
+ ctx2.push(indent3(`__b.appendChild(${v});`));
40281
40799
  }
40282
40800
  }
40283
- if (node.update)
40284
- ctx2.push(indent3(`${node.update}`));
40285
40801
  ctx2.push(indent3(`}`));
40286
40802
  }
40803
+ if (!hyd)
40804
+ ctx2.push(indent3(`__p.insertBefore(__b, ${endAnchor});`));
40287
40805
  if (hyd)
40288
40806
  ctx2.push(indent3(`__place(${anchor}, ${endAnchor}, __cl, ${parent});`));
40289
40807
  ctx2.push(`};`);
@@ -40292,12 +40810,15 @@ function emitForLoop2(ctx2, node, tracked2, parentVar) {
40292
40810
  ctx2.push(`${ctx2.isAsyncScope ? "await " : ""}${renderLoop}();`);
40293
40811
  if (node.kind === "for-in") {
40294
40812
  const srcExpr = transformTracked2(node.condition, tracked2);
40813
+ if (!isReactiveExpression2(node.condition, tracked2)) {
40814
+ return null;
40815
+ }
40295
40816
  ctx2.effects.push(`{
40296
40817
  let __busy = false;
40297
40818
  let __iv = undefined;
40298
40819
  let __first = true;
40299
40820
  effect(${ctx2.isAsyncScope ? "async () => {" : "() => {"}
40300
- if (__first) { __first = false; return; }
40821
+ if (__first) { __first = false; __iv = (${srcExpr}); return; }
40301
40822
  if (__busy) return;
40302
40823
  const __nv = (${srcExpr});
40303
40824
  if (__nv !== __iv) {
@@ -40329,10 +40850,12 @@ function emitSwitchBlock2(ctx2, node, tracked2, parentVar) {
40329
40850
  ctx2.push(`const ${endAnchor} = document.createComment('switch-end');`);
40330
40851
  const renderSwitch = ctx2.n();
40331
40852
  ctx2.push(`const ${renderSwitch} = ${ctx2.isAsyncScope ? "async () => {" : "() => {"}`);
40332
- if (!hyd)
40333
- ctx2.push(indent3(`const __p = ${anchor}.parentNode;`));
40334
- if (hyd)
40853
+ if (hyd) {
40335
40854
  ctx2.push(indent3(`const __cl = [];`));
40855
+ } else {
40856
+ ctx2.push(indent3(`const __p = ${anchor}.parentNode;`));
40857
+ ctx2.push(indent3(`const __c = document.createDocumentFragment();`));
40858
+ }
40336
40859
  ctx2.push(indent3(`switch (${discExpr}) {`));
40337
40860
  for (const c of node.cases) {
40338
40861
  if (c.test) {
@@ -40341,17 +40864,19 @@ function emitSwitchBlock2(ctx2, node, tracked2, parentVar) {
40341
40864
  ctx2.push(indent3(`default:`));
40342
40865
  }
40343
40866
  for (const n of c.body) {
40344
- const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : void 0);
40867
+ const v = emitNode2(ctx2, n, tracked2, effectsVar, hyd ? parentVar : "__c");
40345
40868
  if (v) {
40346
40869
  if (hyd)
40347
40870
  ctx2.push(indent3(`__cl.push(${v});`));
40348
40871
  else
40349
- ctx2.push(indent3(`__p.insertBefore(${v}, ${endAnchor});`));
40872
+ ctx2.push(indent3(`__c.appendChild(${v});`));
40350
40873
  }
40351
40874
  }
40352
40875
  ctx2.push(indent3(`break;`));
40353
40876
  }
40354
40877
  ctx2.push(indent3(`}`));
40878
+ if (!hyd)
40879
+ ctx2.push(indent3(`__p.insertBefore(__c, ${endAnchor});`));
40355
40880
  if (hyd)
40356
40881
  ctx2.push(indent3(`__place(${anchor}, ${endAnchor}, __cl, ${parent});`));
40357
40882
  ctx2.push(`};`);
@@ -40363,7 +40888,7 @@ function emitSwitchBlock2(ctx2, node, tracked2, parentVar) {
40363
40888
  let __iv = (${discExpr});
40364
40889
  let __first = true;
40365
40890
  effect(${ctx2.isAsyncScope ? "async () => {" : "() => {"}
40366
- if (__first) { __first = false; return; }
40891
+ if (__first) { __first = false; __iv = (${discExpr}); return; }
40367
40892
  if (__busy) return;
40368
40893
  const __nv = (${discExpr});
40369
40894
  if (__nv !== __iv) {
@@ -40390,6 +40915,7 @@ function emitMap2(ctx2, node, tracked2, parentVar) {
40390
40915
  const keyed = !!node.keyExpr;
40391
40916
  const hyd = ctx2.hydrate && !keyed;
40392
40917
  const parent = parentVar || "$root";
40918
+ const reactiveSource = isReactiveExpression2(node.expression, tracked2);
40393
40919
  ctx2.push(`const ${anchor} = document.createComment('map');`);
40394
40920
  if (!hyd)
40395
40921
  ctx2.push(`${parent}.appendChild(${anchor});`);
@@ -40401,16 +40927,23 @@ function emitMap2(ctx2, node, tracked2, parentVar) {
40401
40927
  ctx2.push(indent3(`__r = __r || ${endAnchor};`));
40402
40928
  if (node.indexVariable)
40403
40929
  ctx2.push(indent3(`const ${node.indexVariable} = __i;`));
40404
- ctx2.push(indent3(`const __p = ${anchor}.parentNode;`));
40930
+ if (hyd) {
40931
+ ctx2.push(indent3(`const __p = ${anchor}.parentNode;`));
40932
+ } else {
40933
+ ctx2.push(indent3(`const __p = ${anchor}.parentNode;`));
40934
+ ctx2.push(indent3(`const __it = document.createDocumentFragment();`));
40935
+ }
40405
40936
  for (const n of node.bodyTemplate) {
40406
- const v = emitNode2(ctx2, n, tracked2, "__e");
40937
+ const v = emitNode2(ctx2, n, tracked2, "__e", hyd ? void 0 : "__it");
40407
40938
  if (v) {
40408
40939
  if (hyd)
40409
40940
  ctx2.push(indent3(`if (__cl) __cl.push(${v}); else __p.insertBefore(${v}, __r);`));
40410
40941
  else
40411
- ctx2.push(indent3(`__p.insertBefore(${v}, __r);`));
40942
+ ctx2.push(indent3(`__it.appendChild(${v});`));
40412
40943
  }
40413
40944
  }
40945
+ if (!hyd)
40946
+ ctx2.push(indent3(`__p.insertBefore(__it, __r);`));
40414
40947
  ctx2.push(`};`);
40415
40948
  let emptyRenderName = null;
40416
40949
  if (node.alternateNodes.length > 0) {
@@ -40451,11 +40984,13 @@ function emitMap2(ctx2, node, tracked2, parentVar) {
40451
40984
  const isEmptyVar = ctx2.n();
40452
40985
  ctx2.push(`let ${isEmptyVar} = !${hasItems}();`);
40453
40986
  ctx2.push(`if (!${isEmptyVar}) { ${initList}(); } else { ${aw}${emptyRenderName}(); }`);
40987
+ if (!reactiveSource)
40988
+ return null;
40454
40989
  ctx2.effects.push(`{
40455
40990
  let __first = true;
40456
40991
  effect(${effOpen}
40457
40992
  const __new = ${hasItems}();
40458
- if (__first) { __first = false; return; }
40993
+ if (__first) { __first = false; __new; return; }
40459
40994
  if (__new !== ${isEmptyVar}) {
40460
40995
  if (__new) ${reconciler}(${arrExpr});
40461
40996
  return;
@@ -40469,11 +41004,13 @@ function emitMap2(ctx2, node, tracked2, parentVar) {
40469
41004
  }`);
40470
41005
  } else {
40471
41006
  ctx2.push(`${initList}();`);
41007
+ if (!reactiveSource)
41008
+ return null;
40472
41009
  ctx2.effects.push(`{
40473
41010
  let __first = true;
40474
41011
  effect(() => {
40475
41012
  const __nv = ${arrExpr};
40476
- if (__first) { __first = false; return; }
41013
+ if (__first) { __first = false; __nv; ${reconciler}(${arrExpr}); return; }
40477
41014
  ${reconciler}(${arrExpr});
40478
41015
  });
40479
41016
  }`);
@@ -40505,11 +41042,13 @@ function emitMap2(ctx2, node, tracked2, parentVar) {
40505
41042
  ctx2.push(indent3(`} else { ${aw}${emptyRenderName}(${collectVar ? collectVar : ""}); }`));
40506
41043
  if (collectVar)
40507
41044
  ctx2.push(`__place(${anchor}, ${endAnchor}, ${collectVar}, ${parent});`);
41045
+ if (!reactiveSource)
41046
+ return null;
40508
41047
  ctx2.effects.push(`{
40509
41048
  let __first = true;
40510
41049
  effect(${effOpen}
40511
41050
  const __new = ${hasItems}();
40512
- if (__first) { __first = false; return; }
41051
+ if (__first) { __first = false; __new; return; }
40513
41052
  if (__new !== ${isEmptyVar}) {
40514
41053
  if (__new) {
40515
41054
  for (const e of ${effectsVar}) destroy_block(e);
@@ -40535,11 +41074,13 @@ ${renderAllItems(" ", null)}
40535
41074
  ctx2.push(renderAllItems("", collectVar));
40536
41075
  if (collectVar)
40537
41076
  ctx2.push(`__place(${anchor}, ${endAnchor}, ${collectVar}, ${parent});`);
41077
+ if (!reactiveSource)
41078
+ return null;
40538
41079
  ctx2.effects.push(`{
40539
41080
  let __first = true;
40540
41081
  effect(${effOpen}
40541
41082
  const __nv = ${arrExpr};
40542
- if (__first) { __first = false; return; }
41083
+ if (__first) { __first = false; __nv; return; }
40543
41084
  for (const e of ${effectsVar}) destroy_block(e);
40544
41085
  ${effectsVar}.length = 0;
40545
41086
  __cleanup(${anchor}, ${endAnchor});
@@ -40553,10 +41094,11 @@ ${renderAllItems(" ", null)}
40553
41094
  function computeAsyncComponents2(comps) {
40554
41095
  return new Set(comps.filter((c) => c.isAsync).map((c) => c.name));
40555
41096
  }
40556
- function generateComponent2(comp, importedNames = /* @__PURE__ */ new Set(), hydrate = false, asyncComps = /* @__PURE__ */ new Set()) {
41097
+ function generateComponent2(comp, importedNames = /* @__PURE__ */ new Set(), hydrate = false, asyncComps = /* @__PURE__ */ new Set(), linkNames = /* @__PURE__ */ new Set()) {
40557
41098
  const tracked2 = collectTrackedNames2(comp.body);
40558
41099
  const ctx2 = new Ctx2();
40559
41100
  ctx2.importedNames = importedNames;
41101
+ ctx2.linkNames = linkNames;
40560
41102
  ctx2.hydrate = hydrate;
40561
41103
  ctx2.asyncComps = asyncComps;
40562
41104
  ctx2.isAsyncScope = comp.isAsync || asyncComps.has(comp.name);
@@ -40584,7 +41126,7 @@ function generateComponent2(comp, importedNames = /* @__PURE__ */ new Set(), hyd
40584
41126
  const v = emitNode2(ctx2, node, tracked2, null);
40585
41127
  if (v) {
40586
41128
  if (ctx2.hydrate) {
40587
- ctx2.push(indent3(`if (${v}.parentNode !== $root) $root.appendChild(${v});`));
41129
+ ctx2.push(indent3(`if (${v}.parentNode !== $root) { if (!$root || ${v}.parentNode == null || !$root.contains(${v})) $root.appendChild(${v}); }`));
40588
41130
  } else {
40589
41131
  ctx2.push(indent3(`$root.appendChild(${v});`));
40590
41132
  }
@@ -40614,6 +41156,13 @@ function buildComponentMap3(irRoot, hydrate = false) {
40614
41156
  const mapLines = [];
40615
41157
  mapLines.push(`const __components = {};`);
40616
41158
  const asyncComps = computeAsyncComponents2(irRoot.components);
41159
+ const linkNames = /* @__PURE__ */ new Set();
41160
+ for (const imp of irRoot.imports) {
41161
+ for (const pair of importBindingPairs(imp)) {
41162
+ if (pair.imported === "Link" || pair.imported === "NavLink")
41163
+ linkNames.add(pair.local);
41164
+ }
41165
+ }
40617
41166
  const componentNames = new Set(irRoot.components.map((c) => c.name));
40618
41167
  const topValueNames = extractTopLevelNames(irRoot.topLevelCode).filter((n) => !componentNames.has(n));
40619
41168
  const directNames = /* @__PURE__ */ new Set([...extractRuntimeNames(irRoot.imports), ...localValueImportNames(irRoot.imports), ...topValueNames]);
@@ -40623,7 +41172,7 @@ function buildComponentMap3(irRoot, hydrate = false) {
40623
41172
  mapLines.push(`__components[${JSON.stringify(comp.name)}] = ${stub};`);
40624
41173
  continue;
40625
41174
  }
40626
- const code = generateComponent2(comp, directNames, hydrate, asyncComps);
41175
+ const code = generateComponent2(comp, directNames, hydrate, asyncComps, linkNames);
40627
41176
  mapLines.push(`__components[${JSON.stringify(comp.name)}] = ${code};`);
40628
41177
  }
40629
41178
  mapLines.push(`function __cleanup(start, end) {`);
@@ -41810,7 +42359,7 @@ async function runEventHandlers(handlers, name, ctx2) {
41810
42359
  }
41811
42360
 
41812
42361
  // ../adapter/dist/client-bundle.js
41813
- import { readFileSync as readFileSync20, existsSync as existsSync24, writeFileSync as writeFileSync11, unlinkSync as unlinkSync4, statSync as statSync14, rmSync as rmSync4 } from "node:fs";
42362
+ import { readFileSync as readFileSync20, existsSync as existsSync24, writeFileSync as writeFileSync11, unlinkSync as unlinkSync4, statSync as statSync14, rmSync as rmSync4, mkdtempSync as mkdtempSync2 } from "node:fs";
41814
42363
  import { resolve as resolve23, join as join14, dirname as dirname14, relative as relative6, sep as sep3 } from "node:path";
41815
42364
  import { fileURLToPath as fileURLToPath6 } from "node:url";
41816
42365
 
@@ -42008,8 +42557,126 @@ function demoteExports2(code) {
42008
42557
  code = code.slice(0, e.start) + e.text + code.slice(e.end);
42009
42558
  return code;
42010
42559
  }
42011
- function stripChunkImports2(code) {
42012
- return demoteExports2(removeCompiledNodes2(code, isAnyImport2));
42560
+ function hasChunkImports2(code) {
42561
+ try {
42562
+ const ast = parse4(code);
42563
+ return (ast.body ?? []).some((n) => n.type === "ImportDeclaration");
42564
+ } catch {
42565
+ return false;
42566
+ }
42567
+ }
42568
+ function resolveImportSource2(src2, filePath) {
42569
+ if (src2.startsWith("./") || src2.startsWith("../")) {
42570
+ return resolve23(dirname14(filePath), src2) + ".ts";
42571
+ }
42572
+ return src2;
42573
+ }
42574
+ var ChunkImports2 = class {
42575
+ bySource = /* @__PURE__ */ new Map();
42576
+ aborted = false;
42577
+ abortReason = null;
42578
+ fail(reason, code) {
42579
+ if (!this.aborted) {
42580
+ this.aborted = true;
42581
+ this.abortReason = reason;
42582
+ }
42583
+ return code;
42584
+ }
42585
+ /** Folds one file's imports into the merged set and returns the code with its imports stripped. */
42586
+ add(code, filePath) {
42587
+ if (!code || this.aborted)
42588
+ return code;
42589
+ let ast;
42590
+ try {
42591
+ ast = parse4(code);
42592
+ } catch {
42593
+ return this.fail(`unparseable contribution from ${filePath}`, code);
42594
+ }
42595
+ const body = ast.body ?? [];
42596
+ const ranges = [];
42597
+ for (const raw2 of body) {
42598
+ const node = raw2;
42599
+ if (node.type !== "ImportDeclaration" || typeof node.start !== "number" || typeof node.end !== "number")
42600
+ continue;
42601
+ const src2 = node.source?.value;
42602
+ if (typeof src2 !== "string")
42603
+ continue;
42604
+ const resolved = resolveImportSource2(src2, filePath);
42605
+ let group = this.bySource.get(resolved);
42606
+ if (!group) {
42607
+ group = { named: /* @__PURE__ */ new Map() };
42608
+ this.bySource.set(resolved, group);
42609
+ }
42610
+ for (const spec of node.specifiers ?? []) {
42611
+ const s = spec;
42612
+ const local = s.local?.name;
42613
+ if (typeof local !== "string")
42614
+ return this.fail(`nameless specifier from '${resolved}' in ${filePath}`, code);
42615
+ if (s.type === "ImportDefaultSpecifier") {
42616
+ if (group.default && group.default.local !== local)
42617
+ return this.fail(`conflicting default imports from '${resolved}' in ${filePath}`, code);
42618
+ group.default = { kind: "default", local };
42619
+ } else if (s.type === "ImportNamespaceSpecifier") {
42620
+ if (group.namespace && group.namespace.local !== local)
42621
+ return this.fail(`conflicting namespace imports from '${resolved}' in ${filePath}`, code);
42622
+ group.namespace = { kind: "namespace", local };
42623
+ } else if (s.type === "ImportSpecifier") {
42624
+ const imported = s.imported?.name;
42625
+ if (typeof imported !== "string")
42626
+ return this.fail(`nameless named-import from '${resolved}' in ${filePath}`, code);
42627
+ const existing = group.named.get(imported);
42628
+ if (existing && existing.local !== local)
42629
+ return this.fail(`'${imported}' from '${resolved}' bound to both '${existing.local}' and '${local}' in ${filePath}`, code);
42630
+ group.named.set(imported, { kind: "named", local, imported });
42631
+ }
42632
+ }
42633
+ let cut = node.end;
42634
+ if (code[cut] === ";")
42635
+ cut++;
42636
+ ranges.push([node.start, cut]);
42637
+ }
42638
+ if (ranges.length === 0)
42639
+ return code;
42640
+ return removeRanges2(code, ranges);
42641
+ }
42642
+ /** True when every file parsed and merged cleanly (no conflict, no parse abort). */
42643
+ get ok() {
42644
+ return !this.aborted;
42645
+ }
42646
+ /** Why the merge aborted (null when `ok`). Surfaced by the assembler. */
42647
+ get reason() {
42648
+ return this.abortReason;
42649
+ }
42650
+ /** Renders the deduped import block (empty string when there are no imports). */
42651
+ render() {
42652
+ if (this.aborted || this.bySource.size === 0)
42653
+ return "";
42654
+ const lines = [];
42655
+ const sources = [...this.bySource.keys()].sort();
42656
+ for (const src2 of sources) {
42657
+ const g2 = this.bySource.get(src2);
42658
+ const parts = [];
42659
+ if (g2.default)
42660
+ parts.push(`import ${g2.default.local} from ${JSON.stringify(src2)}`);
42661
+ if (g2.namespace)
42662
+ parts.push(`import * as ${g2.namespace.local} from ${JSON.stringify(src2)}`);
42663
+ const named = [...g2.named.values()].sort((a, b) => a.imported < b.imported ? -1 : 1);
42664
+ if (named.length > 0) {
42665
+ const specs = named.map((sp) => sp.imported === sp.local ? sp.local : `${sp.imported} as ${sp.local}`).join(", ");
42666
+ parts.push(`import { ${specs} } from ${JSON.stringify(src2)}`);
42667
+ }
42668
+ lines.push(parts.join("\n"));
42669
+ }
42670
+ return lines.join("\n");
42671
+ }
42672
+ };
42673
+ function removeRanges2(code, ranges) {
42674
+ const sorted = [...ranges].sort((a, b) => b[0] - a[0]);
42675
+ let out = code;
42676
+ for (const [start, end] of sorted) {
42677
+ out = out.slice(0, start) + out.slice(end);
42678
+ }
42679
+ return out.trim();
42013
42680
  }
42014
42681
  function scopeFileContribution2(code) {
42015
42682
  const head = extractCompiledNodes2(code, isModuleLevel2);
@@ -42115,7 +42782,7 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
42115
42782
  function stripExports(code) {
42116
42783
  return removeCompiledNodes2(code, isComponentExport2);
42117
42784
  }
42118
- function compileFile2(filePath, resolvedName, output) {
42785
+ function compileFile2(filePath, resolvedName, output, imports) {
42119
42786
  if (seen.has(filePath))
42120
42787
  return;
42121
42788
  seen.add(filePath);
@@ -42134,8 +42801,10 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
42134
42801
  if (cached && cacheUsable) {
42135
42802
  cachedFileHits++;
42136
42803
  for (const dep of cached.imports)
42137
- compileFile2(dep, cache2?.files.get(dep)?.actualName ?? "", output);
42138
- const cachedFileCode = [cached.compCode, cached.hydCode].filter(Boolean).join("\n");
42804
+ compileFile2(dep, cache2?.files.get(dep)?.actualName ?? "", output, imports);
42805
+ const cachedComp = cached.compCode ? imports.add(cached.compCode, filePath).replace(/^\n+/, "").replace(/\n+$/, "") : "";
42806
+ const cachedHyd = cached.hydCode ? imports.add(cached.hydCode, filePath).replace(/__components/g, "__hydrators").replace(/^\n+/, "").replace(/\n+$/, "") : "";
42807
+ const cachedFileCode = [cachedComp, cachedHyd].filter(Boolean).join("\n");
42139
42808
  if (cachedFileCode.trim())
42140
42809
  output.push(scopeFileContribution2(cachedFileCode));
42141
42810
  for (const n of cached.runtimeNames)
@@ -42152,10 +42821,12 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
42152
42821
  src2 = inlineMdContentAttrs(src2, dirname14(filePath), guessProjectRoots(appDir));
42153
42822
  }
42154
42823
  const namesBefore = cache2 ? new Set(runtimeImportNames) : null;
42155
- const importedPaths = resolveVskImports(filePath, (p, n) => compileFile2(p, n || "", output));
42824
+ const importedPaths = resolveVskImports(filePath, (p, n) => compileFile2(p, n, output, imports));
42156
42825
  const { comp: rawComp, hyd: rawHyd, name: actualName } = compileClientBoth(src2, null, filePath);
42157
- const compCode = rawComp ? stripChunkImports2(stripExports(stripVskImports(stripRuntimeImport(rawComp)))).replace(/^\n+/, "").replace(/\n+$/, "") : "";
42158
- const hydCode = rawHyd ? stripChunkImports2(stripExports(stripVskImports(stripRuntimeImport(rawHyd)))).replace(/__components/g, "__hydrators").replace(/^\n+/, "").replace(/\n+$/, "") : "";
42826
+ const compWithImports = rawComp ? stripExports(stripVskImports(stripRuntimeImport(rawComp))) : "";
42827
+ const hydWithImports = rawHyd ? stripExports(stripVskImports(stripRuntimeImport(rawHyd))) : "";
42828
+ const compCode = compWithImports ? imports.add(compWithImports, filePath).replace(/^\n+/, "").replace(/\n+$/, "") : "";
42829
+ const hydCode = hydWithImports ? imports.add(hydWithImports, filePath).replace(/__components/g, "__hydrators").replace(/^\n+/, "").replace(/\n+$/, "") : "";
42159
42830
  if (rawComp)
42160
42831
  collectRuntimeImports(rawComp);
42161
42832
  if (rawHyd)
@@ -42176,8 +42847,8 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
42176
42847
  cache2.files.set(filePath, {
42177
42848
  mtimeMs: st.mtimeMs,
42178
42849
  size: st.size,
42179
- compCode,
42180
- hydCode,
42850
+ compCode: compWithImports,
42851
+ hydCode: hydWithImports,
42181
42852
  actualName,
42182
42853
  runtimeNames: [...runtimeImportNames].filter((n) => !namesBefore.has(n)),
42183
42854
  imports: importedPaths
@@ -42209,37 +42880,42 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
42209
42880
  let walkSplit2 = function(nodes, _chain) {
42210
42881
  for (const node of nodes) {
42211
42882
  const chunkCode = [];
42883
+ const chunkImports = new ChunkImports2();
42212
42884
  const pagePath = resolve23(appDir, node.sourceDir, "page.vsk");
42213
42885
  if (node.page && existsSync24(pagePath)) {
42214
- compileFile2(pagePath, node.page, chunkCode);
42886
+ compileFile2(pagePath, node.page, chunkCode, chunkImports);
42215
42887
  }
42216
42888
  const layoutPath = resolve23(appDir, node.sourceDir, "layout.vsk");
42217
42889
  if (node.layout && existsSync24(layoutPath)) {
42218
- compileFile2(layoutPath, node.layout, chunkCode);
42890
+ compileFile2(layoutPath, node.layout, chunkCode, chunkImports);
42219
42891
  }
42220
42892
  const errorPath = resolve23(appDir, node.sourceDir, "error.vsk");
42221
42893
  if (node.error && existsSync24(errorPath)) {
42222
- compileFile2(errorPath, node.error, chunkCode);
42894
+ compileFile2(errorPath, node.error, chunkCode, chunkImports);
42223
42895
  }
42224
42896
  const notFoundPath = resolve23(appDir, node.sourceDir, "not-found.vsk");
42225
42897
  if (node.notFound && existsSync24(notFoundPath)) {
42226
- compileFile2(notFoundPath, node.notFound, chunkCode);
42898
+ compileFile2(notFoundPath, node.notFound, chunkCode, chunkImports);
42227
42899
  }
42228
42900
  const offlinePath = resolve23(appDir, node.sourceDir, "offline.vsk");
42229
42901
  if (node.offline && existsSync24(offlinePath)) {
42230
- compileFile2(offlinePath, node.offline, chunkCode);
42902
+ compileFile2(offlinePath, node.offline, chunkCode, chunkImports);
42231
42903
  }
42232
42904
  const networkPath = resolve23(appDir, node.sourceDir, "network.vsk");
42233
42905
  if (node.network && existsSync24(networkPath)) {
42234
- compileFile2(networkPath, node.network, chunkCode);
42906
+ compileFile2(networkPath, node.network, chunkCode, chunkImports);
42235
42907
  }
42236
42908
  const loadingPath = resolve23(appDir, node.sourceDir, "loading.vsk");
42237
42909
  if (node.loading && existsSync24(loadingPath)) {
42238
- compileFile2(loadingPath, node.loading, chunkCode);
42910
+ compileFile2(loadingPath, node.loading, chunkCode, chunkImports);
42239
42911
  }
42240
42912
  if (chunkCode.length > 0) {
42241
42913
  const chunkName = `page-${buildChunkName(node)}.js`;
42242
- chunkEntries.push({ name: chunkName, code: chunkCode.join("\n\n"), node });
42914
+ if (!chunkImports.ok)
42915
+ console.error("[vesk] chunk import merge aborted for", chunkName + ":", chunkImports.reason);
42916
+ const head = chunkImports.render();
42917
+ const code = (head ? head + "\n\n" : "") + chunkCode.join("\n\n");
42918
+ chunkEntries.push({ name: chunkName, code, node });
42243
42919
  }
42244
42920
  walkSplit2(node.children || [], [..._chain, node]);
42245
42921
  }
@@ -42256,25 +42932,62 @@ async function generateClientBundle2(routeTree, appDir, componentMap, options2)
42256
42932
  const chunkEntries = [];
42257
42933
  walkSplit2(routeTree, []);
42258
42934
  const sharedCode = [];
42935
+ const sharedImports = new ChunkImports2();
42259
42936
  const compMap = componentMap || /* @__PURE__ */ new Map();
42260
42937
  for (const [compName, compPath] of compMap) {
42261
- compileFile2(compPath, compName, sharedCode);
42938
+ compileFile2(compPath, compName, sharedCode, sharedImports);
42262
42939
  }
42263
42940
  if (sharedCode.length > 0) {
42264
- chunkEntries.push({ name: "shared.js", code: sharedCode.join("\n\n"), node: null });
42941
+ if (!sharedImports.ok)
42942
+ console.error("[vesk] chunk import merge aborted for shared.js:", sharedImports.reason);
42943
+ const head = sharedImports.render();
42944
+ const code = (head ? head + "\n\n" : "") + sharedCode.join("\n\n");
42945
+ chunkEntries.push({ name: "shared.js", code, node: null });
42265
42946
  }
42266
- for (const entry of chunkEntries) {
42267
- if (entry.code.trim()) {
42268
- chunks.push({
42269
- name: entry.name,
42270
- code: `(()=>{
42947
+ const chunkIIFE = (body) => `(()=>{
42271
42948
  const __components = globalThis.__components || (globalThis.__components = {});
42272
42949
  const __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});
42273
- ${entry.code}
42950
+ ${body}
42274
42951
  })();
42275
- `
42276
- });
42952
+ `;
42953
+ for (const entry of chunkEntries) {
42954
+ if (!entry.code.trim())
42955
+ continue;
42956
+ let finalCode;
42957
+ if (hasChunkImports2(entry.code)) {
42958
+ const tmpBase = mkdtempSync2(join14(resolve23(appDir, ".."), "tmp-vesk-chunk-"));
42959
+ const tmpFile = join14(tmpBase, "entry.js");
42960
+ const toBundle = `const __components = globalThis.__components || (globalThis.__components = {});
42961
+ const __hydrators = globalThis.__hydrators || (globalThis.__hydrators = {});
42962
+ ${entry.code}
42963
+ `;
42964
+ writeFileSync11(tmpFile, toBundle);
42965
+ try {
42966
+ const result2 = await build3({
42967
+ entryPoints: [tmpFile],
42968
+ bundle: true,
42969
+ format: "iife",
42970
+ platform: "browser",
42971
+ write: false,
42972
+ logLevel: "silent",
42973
+ loader: { ".js": "tsx" }
42974
+ });
42975
+ finalCode = result2.outputFiles[0].text;
42976
+ } catch (e) {
42977
+ const err = e;
42978
+ console.error("[vesk] chunk bundle failed", entry.name, err?.errors?.map((x) => x.text).join(" | ") || err?.message || String(e));
42979
+ const stripped = demoteExports2(removeCompiledNodes2(entry.code, isAnyImport2));
42980
+ finalCode = chunkIIFE(stripped);
42981
+ } finally {
42982
+ try {
42983
+ rmSync4(tmpBase, { recursive: true, force: true });
42984
+ } catch {
42985
+ }
42986
+ }
42987
+ } else {
42988
+ finalCode = chunkIIFE(entry.code);
42277
42989
  }
42990
+ chunks.push({ name: entry.name, code: finalCode });
42278
42991
  }
42279
42992
  annotate2(routeTree);
42280
42993
  const mainKey = JSON.stringify(routeTree) + "|" + [...runtimeImportNames].sort().join(",") + `|${!!options2?.hmr}|${!!options2?.importRuntime}|${options2?.routeDataCache ?? ""}`;
@@ -43641,7 +44354,7 @@ var __internals2 = {
43641
44354
  };
43642
44355
 
43643
44356
  // ../adapter/dist/dev-config.js
43644
- import { existsSync as existsSync27, readFileSync as readFileSync23, writeFileSync as writeFileSync13, mkdirSync as mkdirSync10, mkdtempSync, rmSync as rmSync5 } from "node:fs";
44357
+ import { existsSync as existsSync27, readFileSync as readFileSync23, writeFileSync as writeFileSync13, mkdirSync as mkdirSync10, mkdtempSync as mkdtempSync3, rmSync as rmSync5 } from "node:fs";
43645
44358
  import { tmpdir } from "node:os";
43646
44359
  import { resolve as resolve26, dirname as dirname16, join as join16 } from "node:path";
43647
44360
  init_parser();
@@ -43672,7 +44385,7 @@ async function parseConfigSource(source, isTs, projectDir2) {
43672
44385
  ` + js;
43673
44386
  }
43674
44387
  const base = projectDir2 ? (mkdirSync10(join16(projectDir2, ".vesk"), { recursive: true }), join16(projectDir2, ".vesk")) : void 0;
43675
- const dir = base ? mkdtempSync(join16(base, "cfg-")) : mkdtempSync(join16(tmpdir(), "vesk-cfg-"));
44388
+ const dir = base ? mkdtempSync3(join16(base, "cfg-")) : mkdtempSync3(join16(tmpdir(), "vesk-cfg-"));
43676
44389
  const tmpFile = join16(dir, "config.mjs");
43677
44390
  try {
43678
44391
  writeFileSync13(tmpFile, js, "utf-8");
@@ -43828,10 +44541,54 @@ function tryParseJsObject(src2) {
43828
44541
  }
43829
44542
  return out;
43830
44543
  }
44544
+ function skipBalancedParens(src2, i) {
44545
+ if (src2[i] !== "(")
44546
+ return i;
44547
+ let depth = 0;
44548
+ let inStr = null;
44549
+ let esc = false;
44550
+ for (let j = i; j < src2.length; j++) {
44551
+ const ch = src2[j];
44552
+ if (inStr) {
44553
+ if (esc) {
44554
+ esc = false;
44555
+ continue;
44556
+ }
44557
+ if (ch === "\\") {
44558
+ esc = true;
44559
+ continue;
44560
+ }
44561
+ if (ch === inStr)
44562
+ inStr = null;
44563
+ continue;
44564
+ }
44565
+ if (ch === '"' || ch === "'" || ch === "`") {
44566
+ inStr = ch;
44567
+ continue;
44568
+ }
44569
+ if (ch === "(")
44570
+ depth++;
44571
+ if (ch === ")") {
44572
+ depth--;
44573
+ if (depth === 0)
44574
+ return j + 1;
44575
+ }
44576
+ }
44577
+ return i;
44578
+ }
44579
+ function rawSpan(src2, from, to) {
44580
+ return { value: { __veskRaw: src2.slice(from, to) }, next: to };
44581
+ }
43831
44582
  function parseLiteralValue(src2, i) {
43832
44583
  const c = src2[i];
43833
44584
  if (c === void 0)
43834
44585
  return null;
44586
+ if (c === "." && src2.slice(i, i + 3) === "...") {
44587
+ const expr = parseLiteralValue(src2, i + 3);
44588
+ if (expr === null || expr.__invalid)
44589
+ return rawSpan(src2, i, skipToEndOfRaw(src2, i + 3));
44590
+ return { value: { __veskRaw: "..." + serializeValue(expr.value) }, next: expr.next };
44591
+ }
43835
44592
  if (c === "{") {
43836
44593
  const end = findMatchingBrace(src2, i);
43837
44594
  if (end === -1)
@@ -43857,8 +44614,9 @@ function parseLiteralValue(src2, i) {
43857
44614
  continue;
43858
44615
  }
43859
44616
  const r = parseLiteralValue(src2, j2);
43860
- if (r === null || r.__invalid)
43861
- return { value: void 0, next: i, __invalid: true };
44617
+ if (r === null || r.__invalid) {
44618
+ return rawSpan(src2, i, skipToEndOfArray(src2, i));
44619
+ }
43862
44620
  vals.push(r.value);
43863
44621
  j2 = r.next;
43864
44622
  }
@@ -43886,8 +44644,82 @@ function parseLiteralValue(src2, i) {
43886
44644
  return { value: null, next: j };
43887
44645
  if (/^-?\d+(\.\d+)?([eE][+-]?\d+)?$/.test(token))
43888
44646
  return { value: Number(token), next: j };
44647
+ if (j < src2.length && src2[j] === "(") {
44648
+ const end = skipBalancedParens(src2, j);
44649
+ return rawSpan(src2, i, end);
44650
+ }
44651
+ if (token.length > 0)
44652
+ return rawSpan(src2, i, j);
43889
44653
  return { value: void 0, next: i, __invalid: true };
43890
44654
  }
44655
+ function skipToEndOfRaw(src2, i) {
44656
+ let depth = 0;
44657
+ let inStr = null;
44658
+ let esc = false;
44659
+ for (let j = i; j < src2.length; j++) {
44660
+ const ch = src2[j];
44661
+ if (inStr) {
44662
+ if (esc) {
44663
+ esc = false;
44664
+ continue;
44665
+ }
44666
+ if (ch === "\\") {
44667
+ esc = true;
44668
+ continue;
44669
+ }
44670
+ if (ch === inStr)
44671
+ inStr = null;
44672
+ continue;
44673
+ }
44674
+ if (ch === '"' || ch === "'" || ch === "`") {
44675
+ inStr = ch;
44676
+ continue;
44677
+ }
44678
+ if (ch === "(")
44679
+ depth++;
44680
+ if (ch === ")") {
44681
+ if (depth === 0)
44682
+ return j;
44683
+ depth--;
44684
+ }
44685
+ if (depth === 0 && (ch === "," || ch === "}" || ch === "]"))
44686
+ return j;
44687
+ }
44688
+ return src2.length;
44689
+ }
44690
+ function skipToEndOfArray(src2, i) {
44691
+ let depth = 0;
44692
+ let inStr = null;
44693
+ let esc = false;
44694
+ for (let j = i; j < src2.length; j++) {
44695
+ const ch = src2[j];
44696
+ if (inStr) {
44697
+ if (esc) {
44698
+ esc = false;
44699
+ continue;
44700
+ }
44701
+ if (ch === "\\") {
44702
+ esc = true;
44703
+ continue;
44704
+ }
44705
+ if (ch === inStr)
44706
+ inStr = null;
44707
+ continue;
44708
+ }
44709
+ if (ch === '"' || ch === "'" || ch === "`") {
44710
+ inStr = ch;
44711
+ continue;
44712
+ }
44713
+ if (ch === "[")
44714
+ depth++;
44715
+ if (ch === "]") {
44716
+ depth--;
44717
+ if (depth === 0)
44718
+ return j + 1;
44719
+ }
44720
+ }
44721
+ return src2.length;
44722
+ }
43891
44723
  function serializeObject(obj) {
43892
44724
  return Object.keys(obj).map((k) => `${isBareKey(k) ? k : JSON.stringify(k)}: ${serializeValue(obj[k])}`).join(", ");
43893
44725
  }
@@ -43895,6 +44727,9 @@ function isBareKey(k) {
43895
44727
  return /^[a-zA-Z_$][\w$]*$/.test(k);
43896
44728
  }
43897
44729
  function serializeValue(v) {
44730
+ if (v !== null && typeof v === "object" && "__veskRaw" in v) {
44731
+ return String(v.__veskRaw);
44732
+ }
43898
44733
  if (v === null)
43899
44734
  return "null";
43900
44735
  if (typeof v === "string")
@@ -45136,7 +45971,7 @@ import { readFileSync as readFileSync26, writeFileSync as writeFileSync15, exist
45136
45971
  import { resolve as resolve29, dirname as dirname18 } from "node:path";
45137
45972
  var DEFAULT_CONFIG = {
45138
45973
  provider: "openai",
45139
- model: "gpt-4o-mini",
45974
+ model: "",
45140
45975
  mode: "explore",
45141
45976
  maxSteps: 25
45142
45977
  };
@@ -47338,10 +48173,8 @@ function createVeskTools(deps) {
47338
48173
  }
47339
48174
 
47340
48175
  // ../adapter/dist/css.js
47341
- init_scan();
47342
48176
  import { readFileSync as readFileSync29, existsSync as existsSync33 } from "node:fs";
47343
48177
  import { resolve as resolve32 } from "node:path";
47344
- var TAILWIND_CSS_URL2 = "/_vesk/static/_tailwind.css";
47345
48178
  var GLOBAL_CSS_URL2 = "/_vesk/static/global.css";
47346
48179
  function resolveUserCssPath2(appDir) {
47347
48180
  const cssSrc = resolve32(appDir, "..", "src", "global.css");
@@ -47352,38 +48185,13 @@ function resolveUserCssPath2(appDir) {
47352
48185
  return altCssSrc;
47353
48186
  return null;
47354
48187
  }
47355
- function hasUserCss2(appDir) {
48188
+ function hasUserCss(appDir) {
47356
48189
  return resolveUserCssPath2(appDir) !== null;
47357
48190
  }
47358
- function isTailwindPlugin2(plugins) {
47359
- return (plugins || []).some((p) => String(p && p.name).toLowerCase().includes("tailwind"));
47360
- }
47361
48191
  function resolveCssUrls2(opts) {
47362
- const urls = [];
47363
- if (opts.tailwind)
47364
- urls.push(TAILWIND_CSS_URL2);
47365
- if (opts.userCss)
47366
- urls.push(GLOBAL_CSS_URL2);
47367
- return urls;
47368
- }
47369
- function stripTailwindDirectives2(css) {
47370
- const blockStart = /^\s*@(theme\s*\{|layer\s+(components|utilities)\s*\{|utility\s+[\w-]+\s*\{)/;
47371
- let result2 = css.replace(/^\s*@import\s+['"]tailwindcss['"]\s*;?\s*$/gm, "");
47372
- result2 = result2.replace(/^\s*@source\s+['"][^'"]+['"]\s*;?\s*$/gm, "");
47373
- const output = [];
47374
- let pos = 0;
47375
- while (pos < result2.length) {
47376
- const lineEnd = result2.indexOf("\n", pos) === -1 ? result2.length : result2.indexOf("\n", pos) + 1;
47377
- const line = result2.slice(pos, lineEnd);
47378
- if (blockStart.test(line.trim())) {
47379
- const end = cssBlockEnd(result2, pos);
47380
- pos = end;
47381
- continue;
47382
- }
47383
- output.push(line);
47384
- pos = lineEnd;
47385
- }
47386
- return output.join("").trim();
48192
+ if (opts.enabled)
48193
+ return [GLOBAL_CSS_URL2];
48194
+ return [];
47387
48195
  }
47388
48196
 
47389
48197
  // ../adapter/dist/hmr.js
@@ -47789,7 +48597,7 @@ if (process.argv[1] && resolve34(process.argv[1]) === fileURLToPath8(import.meta
47789
48597
 
47790
48598
  // src/action-handler.ts
47791
48599
  import { existsSync as existsSync36, readFileSync as readFileSync32, readdirSync as readdirSync12 } from "node:fs";
47792
- import { resolve as resolve35, join as join20 } from "node:path";
48600
+ import { resolve as resolve35 } from "node:path";
47793
48601
 
47794
48602
  // ../compiler/dist/server-cookies.js
47795
48603
  function parseCookies3(str3) {
@@ -47843,21 +48651,7 @@ function issuesToFieldMap2(issues) {
47843
48651
 
47844
48652
  // src/action-handler.ts
47845
48653
  function actionCssUrls(appDirPath) {
47846
- let tailwind = true;
47847
- try {
47848
- const veskDir = join20(resolve35(appDirPath, ".."), ".vesk");
47849
- const statePath = join20(veskDir, "plugins.json");
47850
- if (existsSync36(statePath)) {
47851
- const raw2 = readFileSync32(statePath, "utf-8");
47852
- const state = JSON.parse(raw2);
47853
- const entries = state?.plugins || [];
47854
- tailwind = !entries.some(
47855
- (p) => String(p.name).toLowerCase().includes("tailwind") && p.active === false
47856
- );
47857
- }
47858
- } catch {
47859
- }
47860
- return resolveCssUrls2({ tailwind, userCss: hasUserCss2(appDirPath) });
48654
+ return resolveCssUrls2({ enabled: hasUserCss(appDirPath) });
47861
48655
  }
47862
48656
  function actionCssLinkTags(appDirPath) {
47863
48657
  return actionCssUrls(appDirPath).map((u) => ` <link rel="stylesheet" href="${u}" />`).join("\n") + "\n";
@@ -48198,9 +48992,9 @@ function resolveRuntimeDir(projectDir2) {
48198
48992
  resolve36(import.meta.dirname ?? ".", "..", "..", "runtime", "dist")
48199
48993
  ];
48200
48994
  for (const dir of candidates) {
48201
- if (existsSync37(join21(dir, "ripple-runtime.js"))) return dir;
48202
- const distDir = join21(dir, "dist");
48203
- if (existsSync37(join21(distDir, "ripple-runtime.js"))) return distDir;
48995
+ if (existsSync37(join20(dir, "ripple-runtime.js"))) return dir;
48996
+ const distDir = join20(dir, "dist");
48997
+ if (existsSync37(join20(distDir, "ripple-runtime.js"))) return distDir;
48204
48998
  }
48205
48999
  return null;
48206
49000
  }
@@ -48264,14 +49058,17 @@ async function readBodyJson(req, maxBodyBytes2) {
48264
49058
  }
48265
49059
  var DevBodyTooLargeError = class extends Error {
48266
49060
  };
48267
- function defaultAgenticModel(providerName) {
48268
- return providerName === "anthropic" ? "claude-sonnet-4-6" : providerName === "google" ? "gemini-2.0-flash" : providerName === "ollama" ? "llama3.1" : providerName === "opencode" ? "claude-sonnet-4-6" : providerName === "opencode-go" ? "opencode-go/kimi-k3" : providerName === "openrouter" ? "openrouter/auto" : "gpt-4o-mini";
49061
+ function defaultAgenticModel(_providerName) {
49062
+ return "";
48269
49063
  }
48270
49064
  async function buildAgenticProvider(projectDir2, providerConfig) {
48271
49065
  const cfg = providerConfig || {};
48272
49066
  const providerName = String(cfg.provider || loadAgenticConfig(projectDir2).provider || "openai");
48273
49067
  const apiKey = cfg.apiKey || getApiKey(projectDir2, providerName) || "";
48274
49068
  const model = cfg.model || loadAgenticConfig(projectDir2).model || defaultAgenticModel(providerName);
49069
+ if (!model) {
49070
+ throw new Error("no model configured \u2014 open Settings \u2192 Agentic and pick a model");
49071
+ }
48275
49072
  const baseUrl = cfg.baseUrl || loadAgenticConfig(projectDir2).baseUrl || void 0;
48276
49073
  const maxTokens = typeof cfg.maxTokens === "number" ? cfg.maxTokens : void 0;
48277
49074
  let provider;
@@ -48353,7 +49150,7 @@ function countFilesNamed(dir, name) {
48353
49150
  if (!existsSync37(dir)) return 0;
48354
49151
  let n = 0;
48355
49152
  for (const entry of readdirSync13(dir, { withFileTypes: true })) {
48356
- const p = join21(dir, entry.name);
49153
+ const p = join20(dir, entry.name);
48357
49154
  if (entry.isDirectory()) n += countFilesNamed(p, name);
48358
49155
  else if (entry.name === name) n++;
48359
49156
  }
@@ -48364,8 +49161,8 @@ async function startDevServer(port2, projectDir2, config, host2) {
48364
49161
  if (!process.env.NODE_ENV) process.env.NODE_ENV = "development";
48365
49162
  const secCfg = config.security || {};
48366
49163
  const maxBodyBytes2 = (typeof secCfg.maxBodyBytes === "number" ? secCfg.maxBodyBytes : void 0) || DEFAULT_MAX_BODY_BYTES;
48367
- const appDirPath = join21(projectDir2, "app");
48368
- const publicDir = join21(projectDir2, "public");
49164
+ const appDirPath = join20(projectDir2, "app");
49165
+ const publicDir = join20(projectDir2, "public");
48369
49166
  installMdReadHook2([publicDir]);
48370
49167
  try {
48371
49168
  ensurePackagesBuilt();
@@ -48378,7 +49175,7 @@ async function startDevServer(port2, projectDir2, config, host2) {
48378
49175
  process.exit(1);
48379
49176
  }
48380
49177
  const runtimeDir = runtimeDirUnchecked;
48381
- const veskStateDir = join21(projectDir2, ".vesk");
49178
+ const veskStateDir = join20(projectDir2, ".vesk");
48382
49179
  const configPluginsRaw = config.plugins || [];
48383
49180
  const configPluginNames = configPluginsRaw.map((p) => typeof p === "string" ? p : p?.name).filter((n) => !!n);
48384
49181
  const rawDevPlugins = config.plugins || [];
@@ -48467,25 +49264,19 @@ async function startDevServer(port2, projectDir2, config, host2) {
48467
49264
  }
48468
49265
  }
48469
49266
  }
48470
- function isTailwindActive() {
48471
- return isTailwindPlugin2(getActiveDevPlugins());
48472
- }
48473
49267
  function activeCssUrls() {
48474
49268
  return resolveCssUrls2({
48475
- tailwind: isTailwindActive(),
48476
- userCss: hasUserCss2(appDirPath)
49269
+ enabled: hasUserCss(appDirPath)
48477
49270
  });
48478
49271
  }
48479
49272
  function cssLinkTags() {
48480
49273
  return activeCssUrls().map((u) => ` <link rel="stylesheet" href="${u}" />`).join("\n") + "\n";
48481
49274
  }
48482
- let devUserCssContent = "";
48483
- let devTailwindCssContent = "";
49275
+ let devGlobalCssContent = "";
48484
49276
  let lastServedCssGlobal = "";
48485
- let lastServedCssTailwind = "";
48486
- const srcDir = join21(projectDir2, "src");
48487
- const cssPath = join21(srcDir, "global.css");
48488
- const altCssPath = join21(srcDir, "app.css");
49277
+ const srcDir = join20(projectDir2, "src");
49278
+ const cssPath = join20(srcDir, "global.css");
49279
+ const altCssPath = join20(srcDir, "app.css");
48489
49280
  let rawCss = "";
48490
49281
  if (existsSync37(cssPath)) {
48491
49282
  rawCss = readFileSync33(cssPath, "utf-8");
@@ -48499,25 +49290,16 @@ async function startDevServer(port2, projectDir2, config, host2) {
48499
49290
  await plugin.onBuildStart();
48500
49291
  }
48501
49292
  }
48502
- devUserCssContent = stripTailwindDirectives2(rawCss);
48503
- if (!isTailwindActive()) {
48504
- devTailwindCssContent = "";
48505
- } else {
48506
- devTailwindCssContent = rawCss;
48507
- for (const plugin of activeAtStart) {
48508
- if (typeof plugin.onCSS === "function") {
48509
- const result2 = await plugin.onCSS(rawCss, cssPath);
48510
- if (result2 !== null && typeof result2 === "string") {
48511
- devTailwindCssContent = result2;
48512
- }
49293
+ devGlobalCssContent = rawCss;
49294
+ for (const plugin of activeAtStart) {
49295
+ if (typeof plugin.onCSS === "function") {
49296
+ const result2 = await plugin.onCSS(rawCss, cssPath);
49297
+ if (result2 !== null && typeof result2 === "string") {
49298
+ devGlobalCssContent = result2;
48513
49299
  }
48514
49300
  }
48515
- if (devUserCssContent === devTailwindCssContent || devUserCssContent === rawCss) {
48516
- devTailwindCssContent = devUserCssContent;
48517
- }
48518
49301
  }
48519
- lastServedCssGlobal = devUserCssContent;
48520
- lastServedCssTailwind = devTailwindCssContent;
49302
+ lastServedCssGlobal = devGlobalCssContent;
48521
49303
  }
48522
49304
  let routeTree = scanRoutes(appDirPath);
48523
49305
  let clientBundle = "";
@@ -48710,30 +49492,19 @@ async function startDevServer(port2, projectDir2, config, host2) {
48710
49492
  async function rebuildTailwindCss() {
48711
49493
  if (!rawCss) return false;
48712
49494
  try {
48713
- const nextUser = stripTailwindDirectives2(rawCss);
48714
- let nextTailwind;
48715
- if (!isTailwindActive()) {
48716
- nextTailwind = "";
48717
- } else {
48718
- const active = getActiveDevPlugins();
48719
- nextTailwind = rawCss;
48720
- for (const plugin of active) {
48721
- if (typeof plugin.onCSS === "function") {
48722
- const result2 = await plugin.onCSS(rawCss, cssPath);
48723
- if (result2 !== null && typeof result2 === "string") {
48724
- nextTailwind = result2;
48725
- }
49495
+ let nextGlobal = rawCss;
49496
+ const active = getActiveDevPlugins();
49497
+ for (const plugin of active) {
49498
+ if (typeof plugin.onCSS === "function") {
49499
+ const result2 = await plugin.onCSS(rawCss, cssPath);
49500
+ if (result2 !== null && typeof result2 === "string") {
49501
+ nextGlobal = result2;
48726
49502
  }
48727
49503
  }
48728
- if (nextUser === nextTailwind || nextUser === rawCss) {
48729
- nextTailwind = nextUser;
48730
- }
48731
49504
  }
48732
- const changed = nextUser !== lastServedCssGlobal || nextTailwind !== lastServedCssTailwind;
48733
- devUserCssContent = nextUser;
48734
- devTailwindCssContent = nextTailwind;
48735
- lastServedCssGlobal = nextUser;
48736
- lastServedCssTailwind = nextTailwind;
49505
+ const changed = nextGlobal !== lastServedCssGlobal;
49506
+ devGlobalCssContent = nextGlobal;
49507
+ lastServedCssGlobal = nextGlobal;
48737
49508
  return changed;
48738
49509
  } catch (e) {
48739
49510
  LOG.err(`CSS rebuild error:`, e.message);
@@ -48744,181 +49515,181 @@ async function startDevServer(port2, projectDir2, config, host2) {
48744
49515
  try {
48745
49516
  let debounceTimer = null;
48746
49517
  let cssDebounceTimer = null;
48747
- const watchDirs = [appDirPath];
48748
- if (existsSync37(srcDir)) watchDirs.push(srcDir);
48749
- for (const watchDir of watchDirs) {
48750
- watch(watchDir, { recursive: true }, (eventType, filename) => {
48751
- if (!filename) return;
48752
- const isVsk = filename.endsWith(".vsk") || filename.endsWith(".md") || filename.endsWith(".markdown");
48753
- const isCss = filename.endsWith(".css");
48754
- const isApiRoute = filename.endsWith(".ts") || filename.endsWith(".js") || filename.endsWith(".tsx");
48755
- const isEvents = filename === "_events.ts" || filename === "_events.js";
48756
- if (!isVsk && !isCss && !isApiRoute && !isEvents) return;
48757
- const fullPath = filename.startsWith("/") ? filename : join21(watchDir, filename);
48758
- const fileExists = existsSync37(fullPath);
48759
- if (isEvents) {
48760
- if (debounceTimer) clearTimeout(debounceTimer);
48761
- debounceTimer = setTimeout(async () => {
48762
- try {
48763
- await runAppStop(false);
48764
- await reloadAppEvents();
48765
- await runAppStart(false);
48766
- const bcast = globalThis.__vesk_broadcastHmr;
48767
- if (typeof bcast === "function") bcast({ type: "reload" });
48768
- LOG.info(`events reloaded (${filename})`);
48769
- } catch (e) {
48770
- LOG.err(`events reload error: ${e.message}`);
49518
+ const skipDirs = /* @__PURE__ */ new Set(["node_modules", ".vesk", "tarballs"]);
49519
+ const watchDir = projectDir2;
49520
+ watch(watchDir, { recursive: true }, (eventType, filename) => {
49521
+ if (!filename) return;
49522
+ if (skipDirs.has(filename.split("/")[0]) || filename.includes("node_modules/") || filename.includes(".vesk/") || filename.includes("tmp-vesk-chunk-")) return;
49523
+ const isVsk = filename.endsWith(".vsk") || filename.endsWith(".md") || filename.endsWith(".markdown");
49524
+ const isCss = filename.endsWith(".css");
49525
+ const isApiRoute = filename.endsWith(".ts") || filename.endsWith(".js") || filename.endsWith(".tsx");
49526
+ const isEvents = filename === "_events.ts" || filename === "_events.js";
49527
+ if (!isVsk && !isCss && !isApiRoute && !isEvents) return;
49528
+ const fullPath = filename.startsWith("/") ? filename : join20(watchDir, filename);
49529
+ const fileExists = existsSync37(fullPath);
49530
+ if (isEvents) {
49531
+ if (debounceTimer) clearTimeout(debounceTimer);
49532
+ debounceTimer = setTimeout(async () => {
49533
+ try {
49534
+ await runAppStop(false);
49535
+ await reloadAppEvents();
49536
+ await runAppStart(false);
49537
+ const bcast = globalThis.__vesk_broadcastHmr;
49538
+ if (typeof bcast === "function") bcast({ type: "reload" });
49539
+ LOG.info(`events reloaded (${filename})`);
49540
+ } catch (e) {
49541
+ LOG.err(`events reload error: ${e.message}`);
49542
+ }
49543
+ }, HMR_DEBOUNCE_MS);
49544
+ } else if (isVsk) {
49545
+ if (debounceTimer) clearTimeout(debounceTimer);
49546
+ debounceTimer = setTimeout(async () => {
49547
+ const t0 = Date.now();
49548
+ try {
49549
+ if (typeof globalThis.__vesk_broadcastHmr === "function") {
49550
+ globalThis.__vesk_broadcastHmr({ type: "compiling" });
48771
49551
  }
48772
- }, HMR_DEBOUNCE_MS);
48773
- } else if (isVsk) {
48774
- if (debounceTimer) clearTimeout(debounceTimer);
48775
- debounceTimer = setTimeout(async () => {
48776
- const t0 = Date.now();
49552
+ const stripAnnots = (t) => JSON.stringify(t, (k, v) => k === "chunk" || k === "chunkError" ? void 0 : v);
49553
+ const prevTree = stripAnnots(routeTree);
49554
+ routeTree = scanRoutes(appDirPath);
49555
+ updateSourceMapping();
49556
+ const changedComponents = sourceToComponents.get(fullPath) || [];
49557
+ const treeChanged = prevTree !== stripAnnots(routeTree);
49558
+ const isOutsideApp = !fullPath.startsWith(appDirPath + "/") && fullPath !== appDirPath;
49559
+ const cssPromise = rebuildTailwindCss();
49560
+ let bundleError = null;
49561
+ let hotEditedSource = null;
49562
+ let hotActualName = null;
48777
49563
  try {
48778
- if (typeof globalThis.__vesk_broadcastHmr === "function") {
48779
- globalThis.__vesk_broadcastHmr({ type: "compiling" });
48780
- }
48781
- const stripAnnots = (t) => JSON.stringify(t, (k, v) => k === "chunk" || k === "chunkError" ? void 0 : v);
48782
- const prevTree = stripAnnots(routeTree);
48783
- routeTree = scanRoutes(appDirPath);
48784
- updateSourceMapping();
48785
- const changedComponents = sourceToComponents.get(fullPath) || [];
48786
- const treeChanged = prevTree !== stripAnnots(routeTree);
48787
- const cssPromise = rebuildTailwindCss();
48788
- let bundleError = null;
48789
- let hotEditedSource = null;
48790
- let hotActualName = null;
48791
- try {
48792
- if (treeChanged) {
48793
- await buildClientBundle();
48794
- await bundleRuntime2();
48795
- } else {
48796
- const hot = await buildClientChunks(fullPath);
48797
- bundleError = hot.err;
48798
- hotEditedSource = hot.editedSource;
48799
- hotActualName = hot.actualName;
48800
- }
48801
- } catch (e) {
48802
- bundleError = e;
48803
- LOG.err(`client build error:`, e.message);
49564
+ if (treeChanged || isOutsideApp) {
49565
+ await buildClientBundle();
49566
+ await bundleRuntime2();
49567
+ } else {
49568
+ const hot = await buildClientChunks(fullPath);
49569
+ bundleError = hot.err;
49570
+ hotEditedSource = hot.editedSource;
49571
+ hotActualName = hot.actualName;
48804
49572
  }
48805
- if (typeof globalThis.__vesk_broadcastHmr === "function") {
48806
- const hadErrorState = devLastError !== null;
48807
- if (changedComponents.length > 0) {
48808
- let fnSources;
48809
- let errorMessage = bundleError ? bundleError.message : "";
48810
- if (!treeChanged && !bundleError && hotEditedSource !== null) {
48811
- let compCode = hotEditedSource;
48812
- for (const cname of changedComponents) {
48813
- if (hotActualName && hotActualName !== cname) {
48814
- compCode += `
49573
+ } catch (e) {
49574
+ bundleError = e;
49575
+ LOG.err(`client build error:`, e.message);
49576
+ }
49577
+ if (typeof globalThis.__vesk_broadcastHmr === "function") {
49578
+ const hadErrorState = devLastError !== null;
49579
+ if (changedComponents.length > 0) {
49580
+ let fnSources;
49581
+ let errorMessage = bundleError ? bundleError.message : "";
49582
+ if (!treeChanged && !bundleError && hotEditedSource !== null) {
49583
+ let compCode = hotEditedSource;
49584
+ for (const cname of changedComponents) {
49585
+ if (hotActualName && hotActualName !== cname) {
49586
+ compCode += `
48815
49587
  Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __components[${JSON.stringify(hotActualName)}], configurable: true });
48816
49588
  `;
48817
- }
48818
49589
  }
48819
- if (compCode.trim()) fnSources = { _raw: compCode };
48820
- } else if (fileExists && !bundleError) {
48821
- try {
48822
- const src2 = readFileSync33(fullPath, "utf-8");
48823
- let compCode = buildHmrEvalSnippet2(
48824
- compileClient2(src2, null, { forceClient: true, sourcePath: fullPath, mdRoots: [projectDir2] })
48825
- );
48826
- const actualName = extractCompName2(src2);
48827
- for (const cname of changedComponents) {
48828
- if (actualName && actualName !== cname) {
48829
- compCode += `
49590
+ }
49591
+ if (compCode.trim()) fnSources = { _raw: compCode };
49592
+ } else if (fileExists && !bundleError) {
49593
+ try {
49594
+ const src2 = readFileSync33(fullPath, "utf-8");
49595
+ let compCode = buildHmrEvalSnippet2(
49596
+ compileClient2(src2, null, { forceClient: true, sourcePath: fullPath, mdRoots: [projectDir2] })
49597
+ );
49598
+ const actualName = extractCompName2(src2);
49599
+ for (const cname of changedComponents) {
49600
+ if (actualName && actualName !== cname) {
49601
+ compCode += `
48830
49602
  Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __components[${JSON.stringify(actualName)}], configurable: true });
48831
49603
  `;
48832
- }
48833
49604
  }
48834
- if (compCode.trim()) fnSources = { _raw: compCode };
48835
- } catch (e) {
48836
- errorMessage = e.message;
48837
- bundleError = e;
48838
49605
  }
48839
- } else if (!fileExists) {
48840
- LOG.warn(`HMR source not found: ${fullPath}`);
49606
+ if (compCode.trim()) fnSources = { _raw: compCode };
49607
+ } catch (e) {
49608
+ errorMessage = e.message;
49609
+ bundleError = e;
48841
49610
  }
48842
- if (fnSources) {
48843
- devLastError = null;
48844
- const bcast = globalThis.__vesk_broadcastHmr;
48845
- if (hadErrorState) {
48846
- bcast({ type: "reload" });
48847
- } else {
48848
- bcast({
48849
- type: "update",
48850
- time: Date.now() - t0,
48851
- components: Object.fromEntries(changedComponents.map((name) => [name, true])),
48852
- fnSources
48853
- });
48854
- }
48855
- } else if (errorMessage) {
48856
- const payload = buildDevErrorPayload({
48857
- err: bundleError,
48858
- errorMessage,
48859
- filename,
48860
- fullPath,
48861
- appDir: appDirPath,
48862
- fileExists
48863
- });
48864
- const displayFile = payload.file || filename || "";
48865
- LOG.err(`[vsk:error] ${displayFile}${payload.line ? `:${payload.line}:${payload.column || 1}` : ""} \u2014 ${payload.message}`);
48866
- devLastError = payload;
48867
- recordDiagnostic({
48868
- severity: "error",
48869
- code: "HMR_COMPILE",
48870
- file: displayFile || null,
48871
- line: payload.line,
48872
- column: payload.column,
48873
- message: payload.message,
48874
- hint: payload.tips && payload.tips[0] || null
48875
- });
48876
- globalThis.__vesk_broadcastHmr({
48877
- type: "error",
48878
- ...payload
48879
- });
49611
+ } else if (!fileExists) {
49612
+ LOG.warn(`HMR source not found: ${fullPath}`);
49613
+ }
49614
+ if (fnSources) {
49615
+ devLastError = null;
49616
+ const bcast = globalThis.__vesk_broadcastHmr;
49617
+ if (hadErrorState) {
49618
+ bcast({ type: "reload" });
48880
49619
  } else {
48881
- devLastError = null;
48882
- globalThis.__vesk_broadcastHmr({ type: "reload" });
49620
+ bcast({
49621
+ type: "update",
49622
+ time: Date.now() - t0,
49623
+ components: Object.fromEntries(changedComponents.map((name) => [name, true])),
49624
+ fnSources
49625
+ });
48883
49626
  }
49627
+ } else if (errorMessage) {
49628
+ const payload = buildDevErrorPayload({
49629
+ err: bundleError,
49630
+ errorMessage,
49631
+ filename,
49632
+ fullPath,
49633
+ appDir: appDirPath,
49634
+ fileExists
49635
+ });
49636
+ const displayFile = payload.file || filename || "";
49637
+ LOG.err(`[vsk:error] ${displayFile}${payload.line ? `:${payload.line}:${payload.column || 1}` : ""} \u2014 ${payload.message}`);
49638
+ devLastError = payload;
49639
+ recordDiagnostic({
49640
+ severity: "error",
49641
+ code: "HMR_COMPILE",
49642
+ file: displayFile || null,
49643
+ line: payload.line,
49644
+ column: payload.column,
49645
+ message: payload.message,
49646
+ hint: payload.tips && payload.tips[0] || null
49647
+ });
49648
+ globalThis.__vesk_broadcastHmr({
49649
+ type: "error",
49650
+ ...payload
49651
+ });
48884
49652
  } else {
48885
49653
  devLastError = null;
48886
49654
  globalThis.__vesk_broadcastHmr({ type: "reload" });
48887
49655
  }
49656
+ } else {
49657
+ devLastError = null;
49658
+ globalThis.__vesk_broadcastHmr({ type: "reload" });
48888
49659
  }
48889
- const cssChanged = await cssPromise;
48890
- if (cssChanged && typeof globalThis.__vesk_broadcastHmr === "function") {
48891
- globalThis.__vesk_broadcastHmr({ type: "css-update" });
48892
- }
48893
- LOG.info(`rebuilt (${filename}) \u2014 ${Date.now() - t0}ms`);
48894
- } catch (e) {
48895
- LOG.err(`rebuild error:`, e.message);
48896
49660
  }
48897
- }, HMR_DEBOUNCE_MS);
48898
- } else if (isCss) {
48899
- if (cssDebounceTimer) clearTimeout(cssDebounceTimer);
48900
- cssDebounceTimer = setTimeout(async () => {
48901
- try {
48902
- if (fileExists) {
48903
- rawCss = readFileSync33(fullPath, "utf-8");
48904
- }
48905
- const cssChanged = await rebuildTailwindCss();
48906
- if (cssChanged && typeof globalThis.__vesk_broadcastHmr === "function") {
48907
- globalThis.__vesk_broadcastHmr({ type: "css-update" });
48908
- }
48909
- LOG.info("CSS rebuilt");
48910
- } catch (e) {
48911
- LOG.err(`CSS rebuild error:`, e.message);
49661
+ const cssChanged = await cssPromise;
49662
+ if (cssChanged && typeof globalThis.__vesk_broadcastHmr === "function") {
49663
+ globalThis.__vesk_broadcastHmr({ type: "css-update" });
48912
49664
  }
48913
- }, HMR_DEBOUNCE_MS);
48914
- } else if (isApiRoute) {
48915
- const isInApi = fullPath.includes("/api/");
48916
- if (isInApi && fileExists) {
48917
- apiWatchCache.set(fullPath, Date.now());
49665
+ LOG.info(`rebuilt (${filename}) \u2014 ${Date.now() - t0}ms`);
49666
+ } catch (e) {
49667
+ LOG.err(`rebuild error:`, e.message);
48918
49668
  }
49669
+ }, HMR_DEBOUNCE_MS);
49670
+ } else if (isCss) {
49671
+ if (cssDebounceTimer) clearTimeout(cssDebounceTimer);
49672
+ cssDebounceTimer = setTimeout(async () => {
49673
+ try {
49674
+ if (fileExists) {
49675
+ rawCss = readFileSync33(fullPath, "utf-8");
49676
+ }
49677
+ const cssChanged = await rebuildTailwindCss();
49678
+ if (cssChanged && typeof globalThis.__vesk_broadcastHmr === "function") {
49679
+ globalThis.__vesk_broadcastHmr({ type: "css-update" });
49680
+ }
49681
+ LOG.info("CSS rebuilt");
49682
+ } catch (e) {
49683
+ LOG.err(`CSS rebuild error:`, e.message);
49684
+ }
49685
+ }, HMR_DEBOUNCE_MS);
49686
+ } else if (isApiRoute) {
49687
+ const isInApi = fullPath.includes("/api/");
49688
+ if (isInApi && fileExists) {
49689
+ apiWatchCache.set(fullPath, Date.now());
48919
49690
  }
48920
- });
48921
- }
49691
+ }
49692
+ });
48922
49693
  } catch (e) {
48923
49694
  LOG.warn("file watching unavailable, serving without auto-rebuild");
48924
49695
  }
@@ -48926,6 +49697,8 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48926
49697
  ".svg": "image/svg+xml",
48927
49698
  ".css": "text/css",
48928
49699
  "": "application/javascript",
49700
+ ".js": "application/javascript",
49701
+ ".mjs": "application/javascript",
48929
49702
  ".png": "image/png",
48930
49703
  ".jpg": "image/jpeg",
48931
49704
  ".ico": "image/x-icon",
@@ -48933,8 +49706,8 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
48933
49706
  ".json": "application/json",
48934
49707
  ".webmanifest": "application/manifest+json"
48935
49708
  };
48936
- const hmrJsPath = join21(runtimeDir, "hmr-client.js");
48937
- const hmrTsPath = join21(runtimeDir, "hmr-client.ts");
49709
+ const hmrJsPath = join20(runtimeDir, "hmr-client.js");
49710
+ const hmrTsPath = join20(runtimeDir, "hmr-client.ts");
48938
49711
  const hmrClientPath = existsSync37(hmrJsPath) ? hmrJsPath : existsSync37(hmrTsPath) ? hmrTsPath : null;
48939
49712
  function extractCompName2(src2) {
48940
49713
  return resolveComponentName(src2);
@@ -49026,12 +49799,7 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
49026
49799
  }
49027
49800
  if (url.pathname === "/_vesk/static/global.css") {
49028
49801
  res.writeHead(200, { "Content-Type": "text/css" });
49029
- res.end(devUserCssContent);
49030
- return;
49031
- }
49032
- if (url.pathname === "/_vesk/static/_tailwind.css") {
49033
- res.writeHead(200, { "Content-Type": "text/css" });
49034
- res.end(isTailwindActive() ? devTailwindCssContent : "");
49802
+ res.end(devGlobalCssContent);
49035
49803
  return;
49036
49804
  }
49037
49805
  if (url.pathname === "/_vesk/hmr" || url.pathname === "/_vesk/hmr.js") {
@@ -49099,7 +49867,7 @@ Object.defineProperty(__components, ${JSON.stringify(cname)}, { get: () => __com
49099
49867
  return;
49100
49868
  }
49101
49869
  const mwChain = collectMiddlewareChain(routeTree, url.pathname, appDirPath);
49102
- const apiDirPath = join21(appDirPath, "api");
49870
+ const apiDirPath = join20(appDirPath, "api");
49103
49871
  if (url.pathname.startsWith("/api") && existsSync37(apiDirPath)) {
49104
49872
  const apiRoutes = await scanApiRoutes(apiDirPath);
49105
49873
  const apiMatch = matchApiUrl(apiRoutes, req.url || url.pathname);
@@ -49510,7 +50278,7 @@ ${err.stack}</pre></body></html>`);
49510
50278
  LOG.ok(`dev server at http://localhost:${port2} (listening on ${bindHost})`);
49511
50279
  const routes = collectRoutePaths(routeTree);
49512
50280
  const pageCount = countPages(routeTree);
49513
- const apiCount = countFilesNamed(join21(appDirPath, "api"), "route.ts");
50281
+ const apiCount = countFilesNamed(join20(appDirPath, "api"), "route.ts");
49514
50282
  LOG.info(`${projectDir2}`);
49515
50283
  LOG.info(`${pageCount} page${pageCount === 1 ? "" : "s"}: ${routes.join(", ") || "(none)"}`);
49516
50284
  if (apiCount > 0) LOG.info(`${apiCount} api route${apiCount === 1 ? "" : "s"} (app/api)`);
@@ -49544,6 +50312,23 @@ ${err.stack}</pre></body></html>`);
49544
50312
  if (ws.readyState === 1) ws.send(msg);
49545
50313
  }
49546
50314
  };
50315
+ const logsCfg = config?.logs;
50316
+ const logsEnabled = logsCfg !== false;
50317
+ const logsLevels = typeof logsCfg === "object" && logsCfg !== null ? { log: true, warn: true, error: true, info: true, debug: true, ...logsCfg } : { log: true, warn: true, error: true, info: true, debug: true };
50318
+ if (logsEnabled) {
50319
+ const origFns = {};
50320
+ for (const lvl of ["log", "warn", "error", "info", "debug"]) {
50321
+ origFns[lvl] = console[lvl].bind(console);
50322
+ console[lvl] = (...args2) => {
50323
+ origFns[lvl](...args2);
50324
+ if (!logsLevels[lvl]) return;
50325
+ const msg = JSON.stringify({ type: "console", level: lvl, message: args2.map(String).join(" "), nonce: hmrNonce });
50326
+ for (const ws of hmrClients) {
50327
+ if (ws.readyState === 1) ws.send(msg);
50328
+ }
50329
+ };
50330
+ }
50331
+ }
49547
50332
  let stopping = false;
49548
50333
  const shutdown2 = (signal) => {
49549
50334
  if (stopping) return;
@@ -49792,8 +50577,8 @@ if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
49792
50577
  }
49793
50578
  function loadEnvFiles(projectDir2) {
49794
50579
  const files = [
49795
- join23(projectDir2, ".env"),
49796
- join23(projectDir2, ".env.local")
50580
+ join22(projectDir2, ".env"),
50581
+ join22(projectDir2, ".env.local")
49797
50582
  ];
49798
50583
  for (const filePath of files) {
49799
50584
  if (!existsSync38(filePath)) continue;
@@ -49816,8 +50601,8 @@ function loadEnvFiles(projectDir2) {
49816
50601
  }
49817
50602
  async function loadConfig(projectDir2) {
49818
50603
  loadEnvFiles(projectDir2);
49819
- const jsPath = join23(projectDir2, "vesk.config.js");
49820
- const tsPath = join23(projectDir2, "vesk.config.ts");
50604
+ const jsPath = join22(projectDir2, "vesk.config.js");
50605
+ const tsPath = join22(projectDir2, "vesk.config.ts");
49821
50606
  let configPath3 = null;
49822
50607
  if (existsSync38(jsPath)) configPath3 = jsPath;
49823
50608
  else if (existsSync38(tsPath)) configPath3 = tsPath;
@@ -49830,7 +50615,7 @@ async function loadConfig(projectDir2) {
49830
50615
  js = js.replace(/import\s+\{[^}]*\}\s*from\s+['"]@vesk\/compiler['"]\s*;?\s*/g, "");
49831
50616
  js = `const { defineConfig, definePlugin, preset } = globalThis.__vesk_inject;
49832
50617
  ` + js;
49833
- const tmpFile = join23(projectDir2, ".vesk", "config.tmp.js");
50618
+ const tmpFile = join22(projectDir2, ".vesk", "config.tmp.js");
49834
50619
  mkdirSync16(dirname23(tmpFile), { recursive: true });
49835
50620
  writeFileSync19(tmpFile, js, "utf-8");
49836
50621
  globalThis.__vesk_inject = { defineConfig, definePlugin, preset };
@@ -49852,8 +50637,8 @@ async function loadConfig(projectDir2) {
49852
50637
  }
49853
50638
  if (cmd === "build") {
49854
50639
  const projectDir2 = process.cwd();
49855
- const appDirPath = join23(projectDir2, "app");
49856
- const publicDir = join23(projectDir2, "public");
50640
+ const appDirPath = join22(projectDir2, "app");
50641
+ const publicDir = join22(projectDir2, "public");
49857
50642
  if (!existsSync38(appDirPath)) {
49858
50643
  console.error(`vesk build: no app/ directory found in ${projectDir2}`);
49859
50644
  process.exit(1);
@@ -49924,7 +50709,7 @@ ${code}`;
49924
50709
  }
49925
50710
  if (cmd === "seo") {
49926
50711
  const projectDir2 = process.cwd();
49927
- const appDirPath = join23(projectDir2, "app");
50712
+ const appDirPath = join22(projectDir2, "app");
49928
50713
  if (!existsSync38(appDirPath)) {
49929
50714
  console.error(`vesk seo: no app/ directory found in ${projectDir2}`);
49930
50715
  process.exit(1);
@@ -49939,7 +50724,7 @@ if (cmd === "seo") {
49939
50724
  }
49940
50725
  if (cmd === "typecheck") {
49941
50726
  const projectDir2 = process.cwd();
49942
- const appDirPath = join23(projectDir2, "app");
50727
+ const appDirPath = join22(projectDir2, "app");
49943
50728
  if (!existsSync38(appDirPath)) {
49944
50729
  console.error(`vesk typecheck: no app/ directory found in ${projectDir2}`);
49945
50730
  process.exit(1);
@@ -49964,7 +50749,7 @@ if (cmd === "typecheck") {
49964
50749
  }
49965
50750
  if (cmd === "start") {
49966
50751
  const projectDir2 = process.cwd();
49967
- const outDir2 = join23(projectDir2, ".vesk");
50752
+ const outDir2 = join22(projectDir2, ".vesk");
49968
50753
  const port2 = parsePortArg(args);
49969
50754
  const host2 = parseHostArg(args);
49970
50755
  startProdServer(outDir2, { port: port2, host: host2 });
@@ -49973,8 +50758,8 @@ if (cmd === "start") {
49973
50758
  }
49974
50759
  if (cmd === "init") {
49975
50760
  const projectDir2 = process.cwd();
49976
- const srcDir = join23(projectDir2, "src");
49977
- const target = join23(srcDir, "global.css");
50761
+ const srcDir = join22(projectDir2, "src");
50762
+ const target = join22(srcDir, "global.css");
49978
50763
  if (existsSync38(target)) {
49979
50764
  console.error(`vesk init: ${target} already exists \u2014 skipping`);
49980
50765
  process.exit(0);
@@ -49993,7 +50778,7 @@ if (cmd === "init") {
49993
50778
  }
49994
50779
  if (cmd === "dev") {
49995
50780
  const projectDir2 = process.cwd();
49996
- const appDirPath = join23(projectDir2, "app");
50781
+ const appDirPath = join22(projectDir2, "app");
49997
50782
  const port2 = parsePortArg(args);
49998
50783
  const host2 = parseHostArg(args);
49999
50784
  if (!existsSync38(appDirPath)) {