bun-plugin-stx 0.2.339 → 0.2.341

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.
@@ -2696,26 +2696,58 @@ else {
2696
2696
  navigate(location.pathname+location.search+location.hash,false);
2697
2697
  });
2698
2698
 
2699
- // \u2500\u2500 Prefetch on hover \u2500\u2500
2699
+ // \u2500\u2500 Prefetch \u2500\u2500
2700
+ // A link's page, fetched before it is followed into the cache navigate
2701
+ // reads, so following it is a swap rather than a round trip.
2702
+ function prefetchLink(link){
2703
+ // Same opt-out set as the click path. Without it, hovering a link the
2704
+ // router is not allowed to claim still fired a real GET at it \u2014 a
2705
+ // logout or OAuth URL was requested on hover alone.
2706
+ if(isRouterExcluded(link))return;
2707
+ var href=withCurrentLocale(link.getAttribute('href'));
2708
+ var key=cacheKey(href);
2709
+ if(cache[key]||prefetching[key])return;
2710
+ prefetching[key]=true;
2711
+ var wantsFragment=shouldUseFragmentResponse();
2712
+ fetch(href,{headers:wantsFragment?{'X-STX-Router':'true','Accept':'text/html'}:{'Accept':'text/html'}}).then(function(r){
2713
+ return readPrefetchResponse(r,wantsFragment);
2714
+ }).then(function(result){
2715
+ if(result&&o.cache)setCache(key,result.html,result.layout,result.layoutGroup,result.title,result.containerAttrs);
2716
+ }).catch(function(){}).finally(function(){delete prefetching[key]});
2717
+ }
2718
+
2719
+ // Links marked data-stx-prefetch="eager", fetched once the page is idle, so
2720
+ // even their first tap is served from the cache: the way a phone's tab bar
2721
+ // switches instantly. Not on a connection that asked to save data.
2722
+ var eagerQueued=false;
2723
+ function prefetchEager(){
2724
+ if(!o.prefetch||!o.cache||eagerQueued)return;
2725
+ eagerQueued=true;
2726
+ var run=function(){
2727
+ eagerQueued=false;
2728
+ var connection=navigator.connection;
2729
+ if(connection&&(connection.saveData||/2g/.test(connection.effectiveType||'')))return;
2730
+ var here=cacheKey(location.pathname+location.search);
2731
+ var links=document.querySelectorAll('[data-stx-link][data-stx-prefetch="eager"]');
2732
+ for(var i=0;i<links.length;i++){
2733
+ var href=links[i].getAttribute('href');
2734
+ if(href&&cacheKey(withCurrentLocale(href))!==here)prefetchLink(links[i]);
2735
+ }
2736
+ };
2737
+ if(window.requestIdleCallback)window.requestIdleCallback(run,{timeout:2000});
2738
+ else setTimeout(run,300);
2739
+ }
2740
+
2700
2741
  if(o.prefetch){
2701
- document.addEventListener('mouseover',function(e){
2742
+ // A mouse hovers before it clicks. A finger does not hover, but it
2743
+ // touches down a tap's length before the click: start the fetch there.
2744
+ var onIntent=function(e){
2702
2745
  if(!e.target||!e.target.closest)return;
2703
- var link=e.target.closest('[data-stx-link]');
2704
- // Same opt-out set as the click path. Without it, hovering a link the
2705
- // router is not allowed to claim still fired a real GET at it \u2014 a
2706
- // logout or OAuth URL was requested on hover alone.
2707
- if(isRouterExcluded(link))return;
2708
- var href=withCurrentLocale(link.getAttribute('href'));
2709
- var key=cacheKey(href);
2710
- if(cache[key]||prefetching[key])return;
2711
- prefetching[key]=true;
2712
- var wantsFragment=shouldUseFragmentResponse();
2713
- fetch(href,{headers:wantsFragment?{'X-STX-Router':'true','Accept':'text/html'}:{'Accept':'text/html'}}).then(function(r){
2714
- return readPrefetchResponse(r,wantsFragment);
2715
- }).then(function(result){
2716
- if(result&&o.cache)setCache(key,result.html,result.layout,result.layoutGroup,result.title,result.containerAttrs);
2717
- }).catch(function(){}).finally(function(){delete prefetching[key]});
2718
- },true);
2746
+ prefetchLink(e.target.closest('[data-stx-link]'));
2747
+ };
2748
+ document.addEventListener('mouseover',onIntent,true);
2749
+ document.addEventListener('touchstart',onIntent,{capture:true,passive:true});
2750
+ window.addEventListener('stx:load',prefetchEager);
2719
2751
  }
2720
2752
 
2721
2753
  // \u2500\u2500 Active link management \u2500\u2500
@@ -2917,6 +2949,7 @@ else {
2917
2949
  injectStyles();
2918
2950
  injectViewTransitionCSS();
2919
2951
  refreshCurrentLinks();
2952
+ prefetchEager();
2920
2953
  }
2921
2954
 
2922
2955
  if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',init);else init();
package/dist/serve.d.ts CHANGED
@@ -275,6 +275,8 @@ export declare const ROUTE_PARAMS_PLACEHOLDER: '__STX_ROUTE_PARAMS__';
275
275
  export declare const CSRF_COOKIE: 'X-CSRF-Token';
276
276
  /** `/_stx/runtime.js`, `/_stx/router.<16 hex>.js`, … — the shared client scripts. */
277
277
  export declare const SHARED_SCRIPT_PATH: unknown;
278
+ /** `/_stx/modules.<16 hex>.js` — a page's module bundle, named by its content. */
279
+ export declare const MODULE_BUNDLE_PATH: unknown;
278
280
  /** Default for `imageWarmupBindBudgetMs`: well inside ts-cloud's 180s bind window. */
279
281
  export declare const DEFAULT_IMAGE_WARMUP_BIND_BUDGET_MS: unknown;
280
282
  /**
package/dist/serve.js CHANGED
@@ -8970,6 +8970,7 @@ function staticCacheControl(pathname, production = isProductionServe()) {
8970
8970
  return fingerprinted ? "public, max-age=31536000, immutable" : "public, max-age=3600";
8971
8971
  }
8972
8972
  var SHARED_SCRIPT_PATH = /^\/_stx\/(runtime|router)(?:\.([0-9a-f]{16}))?\.js$/;
8973
+ var MODULE_BUNDLE_PATH = /^\/_stx\/modules\.([0-9a-f]{16})\.js$/;
8973
8974
  function sharedScriptCacheControl(requestedHash, currentHash) {
8974
8975
  return requestedHash === currentHash ? "public, max-age=31536000, immutable" : "no-cache";
8975
8976
  }
@@ -9791,7 +9792,7 @@ function __stxOverlay(errs){
9791
9792
  rebuildDiscoveredPagePaths(kept);
9792
9793
  await indexPageMiddleware(kept);
9793
9794
  try {
9794
- const { Router } = await import("./chunk-zd4nfpfq.js");
9795
+ const { Router } = await import("./chunk-nr0dabfh.js");
9795
9796
  const pagesDirs = patterns.map((p) => p.replace(/\/$/, "")).filter(Boolean);
9796
9797
  const router = new Router(process19.cwd(), { pagesDirs, stateDir: stateDirName(), exclude: options.exclude });
9797
9798
  if (!options.quiet)
@@ -10567,6 +10568,25 @@ ${block}`;
10567
10568
  }
10568
10569
  });
10569
10570
  }
10571
+ const moduleBundle = path.match(MODULE_BUNDLE_PATH);
10572
+ if (moduleBundle) {
10573
+ const stx = await stxModule;
10574
+ const content2 = stx.getServeModuleBundle(moduleBundle[1]);
10575
+ if (content2 === undefined)
10576
+ return new Response("/* stx: unknown module bundle */", { status: 404, headers: { "Content-Type": "application/javascript; charset=utf-8", "Cache-Control": "no-store", ...corsHeaders } });
10577
+ const etag = `"${moduleBundle[1]}"`;
10578
+ const headers = {
10579
+ "Content-Type": "application/javascript; charset=utf-8",
10580
+ "Cache-Control": "public, max-age=31536000, immutable",
10581
+ ETag: etag,
10582
+ ...corsHeaders
10583
+ };
10584
+ if (req.headers.get("if-none-match") === etag)
10585
+ return new Response(null, { status: 304, headers });
10586
+ if (req.method === "HEAD")
10587
+ return new Response(null, { headers });
10588
+ return new Response(content2, { headers });
10589
+ }
10570
10590
  const sharedScript = path.match(SHARED_SCRIPT_PATH);
10571
10591
  if (sharedScript) {
10572
10592
  const stx = await stxModule;
@@ -11333,6 +11353,7 @@ export {
11333
11353
  boundedCache,
11334
11354
  SHARED_SCRIPT_PATH,
11335
11355
  ROUTE_PARAMS_PLACEHOLDER,
11356
+ MODULE_BUNDLE_PATH,
11336
11357
  DEFAULT_IMAGE_WARMUP_BIND_BUDGET_MS,
11337
11358
  CSRF_COOKIE
11338
11359
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bun-plugin-stx",
3
3
  "type": "module",
4
- "version": "0.2.339",
4
+ "version": "0.2.341",
5
5
  "description": "A Bun plugin that allows for using Laravel Blade-like syntax.",
6
6
  "author": "Chris Breuer <chris@stacksjs.org>",
7
7
  "license": "MIT",
@@ -74,7 +74,7 @@
74
74
  "typecheck": "bun tsc --noEmit"
75
75
  },
76
76
  "dependencies": {
77
- "@stacksjs/stx": "0.2.339",
78
- "stx-router": "0.2.339"
77
+ "@stacksjs/stx": "0.2.341",
78
+ "stx-router": "0.2.341"
79
79
  }
80
80
  }