@reckona/mreact-router 0.0.84 → 0.0.86

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.86",
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-compat": "0.0.86",
109
+ "@reckona/mreact": "0.0.86",
110
+ "@reckona/mreact-compiler": "0.0.86",
111
+ "@reckona/mreact-query": "0.0.86",
112
+ "@reckona/mreact-devtools": "0.0.86",
113
+ "@reckona/mreact-reactive-core": "0.0.86",
114
+ "@reckona/mreact-reactive-dom": "0.0.86",
115
+ "@reckona/mreact-server": "0.0.86",
116
+ "@reckona/mreact-shared": "0.0.86"
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.86"
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(),
@@ -1656,11 +1658,13 @@ __mreactGlobal.__mreactRouteCell = (nativeCell, initial) => {
1656
1658
  const routeCellHydrationStart = routeUsesCells
1657
1659
  ? ` const __mreactPreviousState = __mreactRouteStates.get(__mreactRouteId);
1658
1660
  const __mreactState = __mreactPreviousState?.marker === __mreactMarker &&
1659
- __mreactPreviousState?.signature === __mreactRouteStateSignature
1661
+ __mreactPreviousState?.signature === __mreactRouteStateSignature &&
1662
+ __mreactPreviousState?.propsText === (__mreactPropsText ?? "")
1660
1663
  ? __mreactPreviousState
1661
1664
  : {
1662
1665
  cells: new Map(),
1663
1666
  marker: __mreactMarker,
1667
+ propsText: __mreactPropsText ?? "",
1664
1668
  signature: __mreactRouteStateSignature,
1665
1669
  };
1666
1670
  __mreactDropMismatchedRouteState(__mreactPreviousState, __mreactState);
@@ -1767,6 +1771,7 @@ function __mreactResolveRouteNode(value) {
1767
1771
  ? ""
1768
1772
  : `${routeCellHydrationIndent}if (!__mreactHasNonSerializableClientBoundaries(__mreactMarker) && __mreactHydrateClientBoundaries(document, __mreactClientReferences, __mreactClientReferenceComponents)) {
1769
1773
  ${routeCellHydrationIndent} __mreactMarker.setAttribute(${JSON.stringify(routeHydrationContract.hydratedAttribute)}, "true");
1774
+ ${routeCellHydrationIndent} __mreactMarkRouteHydrated();
1770
1775
  ${routeCellHydrationIndent} return;
1771
1776
  ${routeCellHydrationIndent}}
1772
1777
  `;
@@ -1795,9 +1800,10 @@ export function __mreactHydrateRoute() {
1795
1800
  const __mreactMarker = document.querySelector(\`[\${__mreactRouteMarkerAttribute}="\${__mreactRouteId}"]\`);
1796
1801
  const __mreactPropsElement = document.getElementById(\`\${__mreactPropsScriptPrefix}\${__mreactRouteId}\`);
1797
1802
  const __mreactClientReferencesElement = document.getElementById(\`\${__mreactClientReferencesScriptPrefix}\${__mreactRouteId}\`);
1798
- const __mreactProps = __mreactPropsElement?.textContent === undefined
1803
+ const __mreactPropsText = __mreactPropsElement?.textContent;
1804
+ const __mreactProps = __mreactPropsText === undefined
1799
1805
  ? {}
1800
- : JSON.parse(__mreactPropsElement.textContent);
1806
+ : JSON.parse(__mreactPropsText);
1801
1807
  const __mreactClientReferences = __mreactClientReferencesElement?.textContent === undefined
1802
1808
  ? []
1803
1809
  : JSON.parse(__mreactClientReferencesElement.textContent);
@@ -1812,10 +1818,31 @@ ${routeCellHydrationStart}${routeCleanupHydrationStart}${boundaryOnlyHydrationBl
1812
1818
  ${routeCellHydrationIndent}__mreactResumeRoute(__mreactMarker, __mreactNode);
1813
1819
  ${routeCellHydrationIndent}__mreactHydrateClientBoundaries(document, __mreactClientReferences, __mreactClientReferenceComponents);
1814
1820
  ${routeCellHydrationIndent}__mreactMarker.setAttribute(__mreactRouteHydratedAttribute, "true");
1821
+ ${routeCellHydrationIndent}__mreactMarkRouteHydrated();
1815
1822
  ${routeCellHydrationEnd}}
1816
1823
  ${routeCellDropFunction}
1817
1824
  ${routeCleanupFunction}
1818
1825
 
1826
+ function __mreactMarkRouteHydrated() {
1827
+ if (typeof document !== "undefined") {
1828
+ document.documentElement.setAttribute(__mreactRouteHydratedAttribute, "true");
1829
+ }
1830
+
1831
+ if (typeof window !== "undefined" && typeof CustomEvent === "function") {
1832
+ window.dispatchEvent(new CustomEvent("mreact:hydrated", {
1833
+ detail: { routeId: __mreactRouteId },
1834
+ }));
1835
+ }
1836
+ }
1837
+
1838
+ function __mreactMarkRouteHydrating() {
1839
+ if (typeof document === "undefined") {
1840
+ return;
1841
+ }
1842
+
1843
+ document.documentElement.removeAttribute(__mreactRouteHydratedAttribute);
1844
+ }
1845
+
1819
1846
  __mreactHydrateRoute();
1820
1847
  ${clientNavigation ? "__mreactInstallNavigation();" : ""}
1821
1848
 
@@ -2135,9 +2162,19 @@ export function __mreactInvalidateNavigationCache(path) {
2135
2162
  }
2136
2163
  }
2137
2164
 
2165
+ function __mreactInvalidateAllNavigationCache() {
2166
+ __mreactNavigationState.cache.clear();
2167
+ }
2168
+
2138
2169
  function __mreactFetchNavigationHtml(href) {
2170
+ const reloadRouteCache = __mreactNavigationState.reloadNextNavigationFetch === true;
2171
+ __mreactNavigationState.reloadNextNavigationFetch = false;
2172
+ const headers = reloadRouteCache
2173
+ ? { "x-mreact-navigation": "1", "x-mreact-navigation-cache": "reload" }
2174
+ : { "x-mreact-navigation": "1" };
2175
+
2139
2176
  return fetch(href, {
2140
- headers: { "x-mreact-navigation": "1" },
2177
+ headers,
2141
2178
  }).then((response) => {
2142
2179
  __mreactApplyRevalidationHeader(response);
2143
2180
  if (__mreactNavigationResponseRequiresDocumentReload(response)) {
@@ -2153,7 +2190,9 @@ function __mreactNavigationResponseRequiresDocumentReload(response) {
2153
2190
  }
2154
2191
 
2155
2192
  function __mreactApplyRevalidationHeader(response) {
2156
- const header = response.headers.get("x-mreact-revalidate");
2193
+ const header = typeof response?.headers?.get === "function"
2194
+ ? response.headers.get("x-mreact-revalidate")
2195
+ : null;
2157
2196
 
2158
2197
  if (header === null || header.trim() === "") {
2159
2198
  return;
@@ -2208,6 +2247,7 @@ function __mreactApplyNavigationHtml(html, url) {
2208
2247
  const currentRouteId = currentMarker.getAttribute("${routeHydrationContract.routeMarkerAttribute}");
2209
2248
  const nextRouteId = nextMarker.getAttribute("${routeHydrationContract.routeMarkerAttribute}");
2210
2249
 
2250
+ __mreactMarkRouteHydrating();
2211
2251
  __mreactSyncHeadMetadata(template.content, html);
2212
2252
  __mreactResumeNode(currentMarker, nextMarker);
2213
2253
  ${routeCleanupNavigationDispose} __mreactSyncRouteDataScripts(template.content, currentRouteId, nextRouteId);
@@ -2215,6 +2255,8 @@ ${routeCleanupNavigationDispose} __mreactSyncRouteDataScripts(template.content,
2215
2255
  const script = template.content.querySelector('script[type="module"][src]')?.getAttribute("src");
2216
2256
  if (script !== null && script !== undefined) {
2217
2257
  void import(/* @vite-ignore */ script).then((module) => module.${routeHydrationContract.routeHydrateExport}?.());
2258
+ } else {
2259
+ __mreactMarkRouteHydrated();
2218
2260
  }
2219
2261
 
2220
2262
  __mreactApplyOutOfOrderFragments(document);
@@ -2522,6 +2564,7 @@ function __mreactInstallNavigation() {
2522
2564
  }
2523
2565
 
2524
2566
  __mreactNavigationState.installed = true;
2567
+ __mreactInstallNavigationFetchRevalidation();
2525
2568
  __mreactEnableManualScrollRestoration();
2526
2569
  __mreactSaveCurrentHistoryState();
2527
2570
  addEventListener("popstate", (event) => {
@@ -2592,6 +2635,50 @@ function __mreactInstallNavigation() {
2592
2635
  });
2593
2636
  }
2594
2637
 
2638
+ function __mreactInstallNavigationFetchRevalidation() {
2639
+ if (
2640
+ __mreactNavigationState.fetchRevalidationInstalled ||
2641
+ typeof globalThis.fetch !== "function"
2642
+ ) {
2643
+ return;
2644
+ }
2645
+
2646
+ __mreactNavigationState.fetchRevalidationInstalled = true;
2647
+ const fetchImpl = globalThis.fetch;
2648
+ globalThis.fetch = function(input, init) {
2649
+ const mutating = __mreactIsMutatingFetchRequest(input, init);
2650
+
2651
+ return Promise.resolve(fetchImpl.call(this, input, init)).then((response) => {
2652
+ __mreactApplyRevalidationHeader(response);
2653
+
2654
+ if (mutating) {
2655
+ __mreactInvalidateAllNavigationCache();
2656
+ __mreactNavigationState.reloadNextNavigationFetch = true;
2657
+ }
2658
+
2659
+ return response;
2660
+ });
2661
+ };
2662
+ }
2663
+
2664
+ function __mreactIsMutatingFetchRequest(input, init) {
2665
+ const method = __mreactFetchRequestMethod(input, init);
2666
+
2667
+ return method !== "GET" && method !== "HEAD";
2668
+ }
2669
+
2670
+ function __mreactFetchRequestMethod(input, init) {
2671
+ if (typeof init?.method === "string" && init.method !== "") {
2672
+ return init.method.toUpperCase();
2673
+ }
2674
+
2675
+ if (typeof Request !== "undefined" && input instanceof Request) {
2676
+ return input.method.toUpperCase();
2677
+ }
2678
+
2679
+ return "GET";
2680
+ }
2681
+
2595
2682
  function __mreactAnchorFromEvent(event) {
2596
2683
  const target = event.target;
2597
2684
  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;