@reckona/mreact-router 0.0.202 → 0.0.203

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 (60) hide show
  1. package/README.md +5 -2
  2. package/dist/actions.d.ts +2 -3
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +61 -41
  5. package/dist/actions.js.map +1 -1
  6. package/dist/adapters/cloudflare.d.ts +3 -1
  7. package/dist/adapters/cloudflare.d.ts.map +1 -1
  8. package/dist/adapters/cloudflare.js +26 -10
  9. package/dist/adapters/cloudflare.js.map +1 -1
  10. package/dist/build.d.ts +3 -1
  11. package/dist/build.d.ts.map +1 -1
  12. package/dist/build.js +98 -12
  13. package/dist/build.js.map +1 -1
  14. package/dist/cache.d.ts +1 -1
  15. package/dist/cache.d.ts.map +1 -1
  16. package/dist/cache.js +5 -4
  17. package/dist/cache.js.map +1 -1
  18. package/dist/cli-options.d.ts +3 -0
  19. package/dist/cli-options.d.ts.map +1 -1
  20. package/dist/cli-options.js +10 -2
  21. package/dist/cli-options.js.map +1 -1
  22. package/dist/cli.js +2 -2
  23. package/dist/cli.js.map +1 -1
  24. package/dist/client.d.ts +5 -0
  25. package/dist/client.d.ts.map +1 -1
  26. package/dist/client.js +11 -2
  27. package/dist/client.js.map +1 -1
  28. package/dist/navigation-marker.d.ts +2 -0
  29. package/dist/navigation-marker.d.ts.map +1 -0
  30. package/dist/navigation-marker.js +294 -0
  31. package/dist/navigation-marker.js.map +1 -0
  32. package/dist/navigation-runtime.d.ts +1 -1
  33. package/dist/navigation-runtime.d.ts.map +1 -1
  34. package/dist/navigation-runtime.js +1 -1
  35. package/dist/navigation-runtime.js.map +1 -1
  36. package/dist/prerender-entry.d.ts +3 -1
  37. package/dist/prerender-entry.d.ts.map +1 -1
  38. package/dist/prerender-entry.js +61 -3
  39. package/dist/prerender-entry.js.map +1 -1
  40. package/dist/render.d.ts +7 -1
  41. package/dist/render.d.ts.map +1 -1
  42. package/dist/render.js +51 -23
  43. package/dist/render.js.map +1 -1
  44. package/dist/serve.d.ts +3 -0
  45. package/dist/serve.d.ts.map +1 -1
  46. package/dist/serve.js +54 -30
  47. package/dist/serve.js.map +1 -1
  48. package/package.json +11 -11
  49. package/src/actions.ts +72 -56
  50. package/src/adapters/cloudflare.ts +40 -10
  51. package/src/build.ts +107 -10
  52. package/src/cache.ts +10 -4
  53. package/src/cli-options.ts +15 -2
  54. package/src/cli.ts +2 -1
  55. package/src/client.ts +15 -2
  56. package/src/navigation-marker.ts +353 -0
  57. package/src/navigation-runtime.ts +1 -0
  58. package/src/prerender-entry.ts +78 -5
  59. package/src/render.ts +80 -24
  60. package/src/serve.ts +71 -34
package/dist/render.js CHANGED
@@ -7,7 +7,7 @@ import { formatDiagnostic, transform } from "@reckona/mreact-compiler";
7
7
  import { createQueryClient, dehydrate, __MREACT_QUERY_STATE_SCRIPT_ID, installQueryAsyncStorage, runWithQueryClient, } from "@reckona/mreact-query";
8
8
  import { createStringSink, renderAsyncBoundary, renderOutOfOrderReorderScript, renderReactNodeToString, renderToReadableStream, } from "@reckona/mreact-server";
9
9
  import { createClientRouteInferenceCache, formatClientRouteInferenceDiagnostic, inferClientRouteModule, } from "./client-route-inference.js";
10
- import { hydrationMarkerParts, routeIdForPath, withHydrationMarkers, withRouteMarkers, } from "./navigation-runtime.js";
10
+ import { hydrationMarkerParts, routeMarkerParts, routeIdForPath, withHydrationMarkers, } from "./navigation-runtime.js";
11
11
  import { assetPath } from "./assets.js";
12
12
  import { escapeHtmlAttribute } from "@reckona/mreact-shared/html-escape";
13
13
  import { matchRoute, scanAppRoutes } from "./routes.js";
@@ -493,6 +493,7 @@ async function renderAppRequestInternal(options) {
493
493
  let trackedRequest;
494
494
  let sourceUsesRequestInput = true;
495
495
  let invalidConfiguredHsts = false;
496
+ let renderedStrictTransportSecurity;
496
497
  return (await withRouteCacheContext(options.routeCache, async () => {
497
498
  try {
498
499
  if (matched.route.kind === "asset") {
@@ -561,7 +562,8 @@ async function renderAppRequestInternal(options) {
561
562
  finishRenderTimingPhase(timing, phaseStartedAt, "sourceAnalysisMs");
562
563
  const cachePolicy = originalAnalysis.cachePolicy;
563
564
  const navigationScript = options.navigationScripts?.get(matched.route.path);
564
- const cacheKey = routeCacheKey(options.appDir, matched.route.path, url);
565
+ const navigationRequest = isNavigationRequest(options.request);
566
+ const cacheKey = routeCacheKey(options.appDir, matched.route.path, url, navigationRequest ? "navigation" : "document");
565
567
  const mayUseRouteCache = !sourceUsesRequestInput &&
566
568
  (cachePolicy === undefined
567
569
  ? originalAnalysis.usesRuntimeCacheControl
@@ -655,7 +657,7 @@ async function renderAppRequestInternal(options) {
655
657
  clientRoute,
656
658
  props: {
657
659
  params: matched.params,
658
- request: { url: options.request.url },
660
+ request: { url: url.pathname },
659
661
  },
660
662
  routePath: matched.route.path,
661
663
  script: clientScript,
@@ -728,16 +730,11 @@ async function renderAppRequestInternal(options) {
728
730
  script: clientScript,
729
731
  props: {
730
732
  params: matched.params,
731
- request: { url: options.request.url },
733
+ request: { url: url.pathname },
732
734
  data,
733
735
  },
734
736
  })
735
- : isNavigationRequest(options.request)
736
- ? withRouteMarkers({
737
- html: pageHtml,
738
- routePath: matched.route.path,
739
- })
740
- : pageHtml;
737
+ : withServerOnlyRouteMarkers(pageHtml, matched.route.path, options.request);
741
738
  let html = await runWithQueryClient(queryClient, () => applyLayouts({
742
739
  appDir: options.appDir,
743
740
  pageFile: matched.route.file,
@@ -782,7 +779,7 @@ async function renderAppRequestInternal(options) {
782
779
  serverModuleCacheVersion: options.serverModuleCacheVersion,
783
780
  });
784
781
  html = injectAuthSessionClaims(html, originalAnalysis.authIncludesClaims ? currentAuthClaims() : undefined);
785
- html = injectQueryState(html, dehydrate(queryClient));
782
+ html = injectQueryState(html, dehydrate(queryClient, options.dehydrateOptions));
786
783
  const response = withOptionalActionCookie(htmlResponse(applyActionHtmlReplacements(`<!DOCTYPE html>${clientNavigationHeadTags({
787
784
  assetBaseUrl: options.assetBaseUrl,
788
785
  currentStyleSheets: clientStyleSheets,
@@ -794,6 +791,7 @@ async function renderAppRequestInternal(options) {
794
791
  "x-mreact-stream": "1",
795
792
  }),
796
793
  }), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
794
+ appendNavigationVary(response.headers);
797
795
  emitRenderTiming(options, timing, response.status);
798
796
  return response;
799
797
  }
@@ -860,10 +858,12 @@ async function renderAppRequestInternal(options) {
860
858
  data: streamDataPromise,
861
859
  define: options.define,
862
860
  loadingFile,
861
+ markerRequest: options.request,
863
862
  pageFile: matched.route.file,
864
863
  params: matched.params,
865
864
  queryClient,
866
865
  request: appRequest,
866
+ requestUrl: url.pathname,
867
867
  trackedRequest,
868
868
  routePath: matched.route.path,
869
869
  routeScripts: options.clientScripts,
@@ -880,6 +880,7 @@ async function renderAppRequestInternal(options) {
880
880
  const response = withOptionalActionCookie(new Response(stream, {
881
881
  headers: streamShellResponseHeaders,
882
882
  }), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
883
+ appendNavigationVary(response.headers);
883
884
  emitRenderTiming(options, timing, response.status);
884
885
  return response;
885
886
  }
@@ -894,7 +895,9 @@ async function renderAppRequestInternal(options) {
894
895
  appDir: options.appDir,
895
896
  assetBaseUrl: options.assetBaseUrl,
896
897
  pageFile: matched.route.file,
898
+ markerRequest: options.request,
897
899
  props,
900
+ requestUrl: url.pathname,
898
901
  routePath: matched.route.path,
899
902
  routeScripts: options.clientScripts,
900
903
  serverModules: options.serverModules,
@@ -912,6 +915,7 @@ async function renderAppRequestInternal(options) {
912
915
  const response = withOptionalActionCookie(new Response(stream, {
913
916
  headers: streamShellResponseHeaders,
914
917
  }), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
918
+ appendNavigationVary(response.headers);
915
919
  emitRenderTiming(options, timing, response.status);
916
920
  return response;
917
921
  }
@@ -974,16 +978,11 @@ async function renderAppRequestInternal(options) {
974
978
  script: clientScript,
975
979
  props: {
976
980
  params: matched.params,
977
- request: { url: options.request.url },
981
+ request: { url: url.pathname },
978
982
  data,
979
983
  },
980
984
  })
981
- : isNavigationRequest(options.request)
982
- ? withRouteMarkers({
983
- html: pageHtml,
984
- routePath: matched.route.path,
985
- })
986
- : pageHtml;
985
+ : withServerOnlyRouteMarkers(pageHtml, matched.route.path, options.request);
987
986
  phaseStartedAt = renderTimingPhaseStartedAt(timing);
988
987
  let html = await runWithQueryClient(queryClient, () => applyLayouts({
989
988
  appDir: options.appDir,
@@ -1032,7 +1031,7 @@ async function renderAppRequestInternal(options) {
1032
1031
  serverModuleCacheVersion: options.serverModuleCacheVersion,
1033
1032
  });
1034
1033
  html = injectAuthSessionClaims(html, originalAnalysis.authIncludesClaims ? currentAuthClaims() : undefined);
1035
- html = injectQueryState(html, dehydrate(queryClient));
1034
+ html = injectQueryState(html, dehydrate(queryClient, options.dehydrateOptions));
1036
1035
  const response = withOptionalActionCookie(htmlResponse(applyActionHtmlReplacements(`<!DOCTYPE html>${clientNavigationHeadTags({
1037
1036
  assetBaseUrl: options.assetBaseUrl,
1038
1037
  currentStyleSheets: clientStyleSheets,
@@ -1042,8 +1041,10 @@ async function renderAppRequestInternal(options) {
1042
1041
  })}${html}`, preparedActions.htmlReplacements), {
1043
1042
  headers: responseHeadersForMetadata(metadata, options.request),
1044
1043
  }), preparedActions.csrfToken, preparedActions.csrfTokenIsNew === true);
1044
+ appendNavigationVary(response.headers);
1045
1045
  const effectiveCachePolicy = cachePolicy ?? activeRouteCacheContext()?.cachePolicy;
1046
1046
  const configuredHsts = configuredHstsHeader(metadata?.security);
1047
+ renderedStrictTransportSecurity = configuredHsts;
1047
1048
  invalidConfiguredHsts = hasInvalidConfiguredHsts(metadata?.security);
1048
1049
  const finalResponse = preparedActions.hasFormActions
1049
1050
  ? withRouteCacheHeader(response, effectiveCachePolicy)
@@ -1137,6 +1138,7 @@ async function renderAppRequestInternal(options) {
1137
1138
  if (options.renderSignals !== undefined) {
1138
1139
  const tracked = trackedRequest;
1139
1140
  options.renderSignals.headerDependent = () => sourceUsesRequestInput || invalidConfiguredHsts || (tracked?.requestDependent() ?? true);
1141
+ options.renderSignals.strictTransportSecurity = () => renderedStrictTransportSecurity;
1140
1142
  }
1141
1143
  }
1142
1144
  })).value;
@@ -1274,6 +1276,32 @@ function routePrefetchManifestScript(routeScripts, assetBaseUrl) {
1274
1276
  function isNavigationRequest(request) {
1275
1277
  return request.headers.get("x-mreact-navigation") === "1";
1276
1278
  }
1279
+ function withServerOnlyRouteMarkers(html, routePath, request) {
1280
+ const marker = serverOnlyRouteMarkerParts(routePath, request);
1281
+ return marker === undefined ? html : `${marker.prefix}${html}${marker.suffix}`;
1282
+ }
1283
+ function serverOnlyRouteMarkerParts(routePath, request) {
1284
+ if (request.headers.get("x-mreact-prerender-variant-capture") === "1") {
1285
+ return prerenderVariantMarkerParts(routePath);
1286
+ }
1287
+ return isNavigationRequest(request) ? routeMarkerParts(routePath) : undefined;
1288
+ }
1289
+ export function prerenderVariantMarkerParts(routePath) {
1290
+ const routeId = routeIdForPath(routePath);
1291
+ return {
1292
+ prefix: `<!--mreact-route-variant-start:${routeId}-->`,
1293
+ suffix: `<!--mreact-route-variant-end:${routeId}-->`,
1294
+ };
1295
+ }
1296
+ function appendNavigationVary(headers) {
1297
+ const vary = headers.get("vary");
1298
+ if (vary
1299
+ ?.split(",")
1300
+ .some((value) => value.trim().toLowerCase() === "x-mreact-navigation") === true) {
1301
+ return;
1302
+ }
1303
+ headers.append("vary", "x-mreact-navigation");
1304
+ }
1277
1305
  function isNavigationRouteCacheReloadRequest(request) {
1278
1306
  return (isNavigationRequest(request) && request.headers.get("x-mreact-navigation-cache") === "reload");
1279
1307
  }
@@ -2184,11 +2212,11 @@ function runServerStreamModule(code, options) {
2184
2212
  script: options.script,
2185
2213
  props: {
2186
2214
  params: options.props.params,
2187
- request: { url: options.props.request.url },
2215
+ request: { url: options.requestUrl },
2188
2216
  data: options.props.data,
2189
2217
  },
2190
2218
  })
2191
- : undefined;
2219
+ : serverOnlyRouteMarkerParts(options.routePath, options.markerRequest);
2192
2220
  sink.append("<!DOCTYPE html>");
2193
2221
  sink.append(clientNavigationHeadTags({
2194
2222
  assetBaseUrl: options.assetBaseUrl,
@@ -2317,10 +2345,10 @@ async function runServerStreamModuleWithLoading(code, options) {
2317
2345
  script: options.script,
2318
2346
  props: {
2319
2347
  params: options.params,
2320
- request: { url: options.request.url },
2348
+ request: { url: options.requestUrl },
2321
2349
  },
2322
2350
  })
2323
- : undefined;
2351
+ : serverOnlyRouteMarkerParts(options.routePath, options.markerRequest);
2324
2352
  return renderToReadableStream((sink) => {
2325
2353
  sink.append("<!DOCTYPE html>");
2326
2354
  sink.append(clientNavigationHeadTags({