@reckona/mreact-router 0.0.84 → 0.0.85

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reckona/mreact-router",
3
- "version": "0.0.84",
3
+ "version": "0.0.85",
4
4
  "description": "File-system app router, SSR, actions, and deployment adapters for mreact.",
5
5
  "keywords": [
6
6
  "jsx",
@@ -105,20 +105,20 @@
105
105
  },
106
106
  "dependencies": {
107
107
  "typescript": "^6.0.3",
108
- "@reckona/mreact-compat": "0.0.84",
109
- "@reckona/mreact": "0.0.84",
110
- "@reckona/mreact-devtools": "0.0.84",
111
- "@reckona/mreact-query": "0.0.84",
112
- "@reckona/mreact-reactive-core": "0.0.84",
113
- "@reckona/mreact-compiler": "0.0.84",
114
- "@reckona/mreact-reactive-dom": "0.0.84",
115
- "@reckona/mreact-shared": "0.0.84",
116
- "@reckona/mreact-server": "0.0.84"
108
+ "@reckona/mreact": "0.0.85",
109
+ "@reckona/mreact-compat": "0.0.85",
110
+ "@reckona/mreact-devtools": "0.0.85",
111
+ "@reckona/mreact-query": "0.0.85",
112
+ "@reckona/mreact-reactive-core": "0.0.85",
113
+ "@reckona/mreact-compiler": "0.0.85",
114
+ "@reckona/mreact-reactive-dom": "0.0.85",
115
+ "@reckona/mreact-shared": "0.0.85",
116
+ "@reckona/mreact-server": "0.0.85"
117
117
  },
118
118
  "peerDependencies": {
119
119
  "vite": ">=8 <9"
120
120
  },
121
121
  "optionalDependencies": {
122
- "@reckona/mreact-router-native": "0.0.84"
122
+ "@reckona/mreact-router-native": "0.0.85"
123
123
  }
124
124
  }
package/src/client.ts CHANGED
@@ -1611,8 +1611,10 @@ export async function buildClientRouteEntrySource(
1611
1611
  to: null,
1612
1612
  type: null,
1613
1613
  },
1614
+ fetchRevalidationInstalled: false,
1614
1615
  installed: false,
1615
1616
  prefetchedScripts: new Set(),
1617
+ reloadNextNavigationFetch: false,
1616
1618
  routePrefetchManifest: undefined,
1617
1619
  routePrefetchManifestText: undefined,
1618
1620
  viewportAnchors: new WeakSet(),
@@ -1767,6 +1769,7 @@ function __mreactResolveRouteNode(value) {
1767
1769
  ? ""
1768
1770
  : `${routeCellHydrationIndent}if (!__mreactHasNonSerializableClientBoundaries(__mreactMarker) && __mreactHydrateClientBoundaries(document, __mreactClientReferences, __mreactClientReferenceComponents)) {
1769
1771
  ${routeCellHydrationIndent} __mreactMarker.setAttribute(${JSON.stringify(routeHydrationContract.hydratedAttribute)}, "true");
1772
+ ${routeCellHydrationIndent} __mreactMarkRouteHydrated();
1770
1773
  ${routeCellHydrationIndent} return;
1771
1774
  ${routeCellHydrationIndent}}
1772
1775
  `;
@@ -1812,10 +1815,31 @@ ${routeCellHydrationStart}${routeCleanupHydrationStart}${boundaryOnlyHydrationBl
1812
1815
  ${routeCellHydrationIndent}__mreactResumeRoute(__mreactMarker, __mreactNode);
1813
1816
  ${routeCellHydrationIndent}__mreactHydrateClientBoundaries(document, __mreactClientReferences, __mreactClientReferenceComponents);
1814
1817
  ${routeCellHydrationIndent}__mreactMarker.setAttribute(__mreactRouteHydratedAttribute, "true");
1818
+ ${routeCellHydrationIndent}__mreactMarkRouteHydrated();
1815
1819
  ${routeCellHydrationEnd}}
1816
1820
  ${routeCellDropFunction}
1817
1821
  ${routeCleanupFunction}
1818
1822
 
1823
+ function __mreactMarkRouteHydrated() {
1824
+ if (typeof document !== "undefined") {
1825
+ document.documentElement.setAttribute(__mreactRouteHydratedAttribute, "true");
1826
+ }
1827
+
1828
+ if (typeof window !== "undefined" && typeof CustomEvent === "function") {
1829
+ window.dispatchEvent(new CustomEvent("mreact:hydrated", {
1830
+ detail: { routeId: __mreactRouteId },
1831
+ }));
1832
+ }
1833
+ }
1834
+
1835
+ function __mreactMarkRouteHydrating() {
1836
+ if (typeof document === "undefined") {
1837
+ return;
1838
+ }
1839
+
1840
+ document.documentElement.removeAttribute(__mreactRouteHydratedAttribute);
1841
+ }
1842
+
1819
1843
  __mreactHydrateRoute();
1820
1844
  ${clientNavigation ? "__mreactInstallNavigation();" : ""}
1821
1845
 
@@ -2135,9 +2159,19 @@ export function __mreactInvalidateNavigationCache(path) {
2135
2159
  }
2136
2160
  }
2137
2161
 
2162
+ function __mreactInvalidateAllNavigationCache() {
2163
+ __mreactNavigationState.cache.clear();
2164
+ }
2165
+
2138
2166
  function __mreactFetchNavigationHtml(href) {
2167
+ const reloadRouteCache = __mreactNavigationState.reloadNextNavigationFetch === true;
2168
+ __mreactNavigationState.reloadNextNavigationFetch = false;
2169
+ const headers = reloadRouteCache
2170
+ ? { "x-mreact-navigation": "1", "x-mreact-navigation-cache": "reload" }
2171
+ : { "x-mreact-navigation": "1" };
2172
+
2139
2173
  return fetch(href, {
2140
- headers: { "x-mreact-navigation": "1" },
2174
+ headers,
2141
2175
  }).then((response) => {
2142
2176
  __mreactApplyRevalidationHeader(response);
2143
2177
  if (__mreactNavigationResponseRequiresDocumentReload(response)) {
@@ -2153,7 +2187,9 @@ function __mreactNavigationResponseRequiresDocumentReload(response) {
2153
2187
  }
2154
2188
 
2155
2189
  function __mreactApplyRevalidationHeader(response) {
2156
- const header = response.headers.get("x-mreact-revalidate");
2190
+ const header = typeof response?.headers?.get === "function"
2191
+ ? response.headers.get("x-mreact-revalidate")
2192
+ : null;
2157
2193
 
2158
2194
  if (header === null || header.trim() === "") {
2159
2195
  return;
@@ -2208,6 +2244,7 @@ function __mreactApplyNavigationHtml(html, url) {
2208
2244
  const currentRouteId = currentMarker.getAttribute("${routeHydrationContract.routeMarkerAttribute}");
2209
2245
  const nextRouteId = nextMarker.getAttribute("${routeHydrationContract.routeMarkerAttribute}");
2210
2246
 
2247
+ __mreactMarkRouteHydrating();
2211
2248
  __mreactSyncHeadMetadata(template.content, html);
2212
2249
  __mreactResumeNode(currentMarker, nextMarker);
2213
2250
  ${routeCleanupNavigationDispose} __mreactSyncRouteDataScripts(template.content, currentRouteId, nextRouteId);
@@ -2215,6 +2252,8 @@ ${routeCleanupNavigationDispose} __mreactSyncRouteDataScripts(template.content,
2215
2252
  const script = template.content.querySelector('script[type="module"][src]')?.getAttribute("src");
2216
2253
  if (script !== null && script !== undefined) {
2217
2254
  void import(/* @vite-ignore */ script).then((module) => module.${routeHydrationContract.routeHydrateExport}?.());
2255
+ } else {
2256
+ __mreactMarkRouteHydrated();
2218
2257
  }
2219
2258
 
2220
2259
  __mreactApplyOutOfOrderFragments(document);
@@ -2522,6 +2561,7 @@ function __mreactInstallNavigation() {
2522
2561
  }
2523
2562
 
2524
2563
  __mreactNavigationState.installed = true;
2564
+ __mreactInstallNavigationFetchRevalidation();
2525
2565
  __mreactEnableManualScrollRestoration();
2526
2566
  __mreactSaveCurrentHistoryState();
2527
2567
  addEventListener("popstate", (event) => {
@@ -2592,6 +2632,50 @@ function __mreactInstallNavigation() {
2592
2632
  });
2593
2633
  }
2594
2634
 
2635
+ function __mreactInstallNavigationFetchRevalidation() {
2636
+ if (
2637
+ __mreactNavigationState.fetchRevalidationInstalled ||
2638
+ typeof globalThis.fetch !== "function"
2639
+ ) {
2640
+ return;
2641
+ }
2642
+
2643
+ __mreactNavigationState.fetchRevalidationInstalled = true;
2644
+ const fetchImpl = globalThis.fetch;
2645
+ globalThis.fetch = function(input, init) {
2646
+ const mutating = __mreactIsMutatingFetchRequest(input, init);
2647
+
2648
+ return Promise.resolve(fetchImpl.call(this, input, init)).then((response) => {
2649
+ __mreactApplyRevalidationHeader(response);
2650
+
2651
+ if (mutating) {
2652
+ __mreactInvalidateAllNavigationCache();
2653
+ __mreactNavigationState.reloadNextNavigationFetch = true;
2654
+ }
2655
+
2656
+ return response;
2657
+ });
2658
+ };
2659
+ }
2660
+
2661
+ function __mreactIsMutatingFetchRequest(input, init) {
2662
+ const method = __mreactFetchRequestMethod(input, init);
2663
+
2664
+ return method !== "GET" && method !== "HEAD";
2665
+ }
2666
+
2667
+ function __mreactFetchRequestMethod(input, init) {
2668
+ if (typeof init?.method === "string" && init.method !== "") {
2669
+ return init.method.toUpperCase();
2670
+ }
2671
+
2672
+ if (typeof Request !== "undefined" && input instanceof Request) {
2673
+ return input.method.toUpperCase();
2674
+ }
2675
+
2676
+ return "GET";
2677
+ }
2678
+
2595
2679
  function __mreactAnchorFromEvent(event) {
2596
2680
  const target = event.target;
2597
2681
  const anchor = target instanceof Element ? target.closest("a[href]") : null;
package/src/render.ts CHANGED
@@ -912,8 +912,9 @@ async function renderAppRequestInternal(options: RenderAppRequestOptions): Promi
912
912
  cachePolicy === undefined
913
913
  ? originalAnalysis.usesRuntimeCacheControl
914
914
  : cachePolicy.revalidateSeconds !== 0;
915
+ const reloadRouteCache = isNavigationRouteCacheReloadRequest(options.request);
915
916
  phaseStartedAt = renderTimingPhaseStartedAt(timing);
916
- const cachedResponse = !mayUseRouteCache
917
+ const cachedResponse = !mayUseRouteCache || reloadRouteCache
917
918
  ? undefined
918
919
  : await cachedRouteResponse({
919
920
  cache: options.routeCache,
@@ -1593,6 +1594,10 @@ function isNavigationRequest(request: Request): boolean {
1593
1594
  return request.headers.get("x-mreact-navigation") === "1";
1594
1595
  }
1595
1596
 
1597
+ function isNavigationRouteCacheReloadRequest(request: Request): boolean {
1598
+ return isNavigationRequest(request) && request.headers.get("x-mreact-navigation-cache") === "reload";
1599
+ }
1600
+
1596
1601
  async function nearestBoundaryFileForPage(options: {
1597
1602
  appDir: string;
1598
1603
  filename: string;