@reckona/mreact-router 0.0.141 → 0.0.143

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 (62) hide show
  1. package/README.md +4 -2
  2. package/dist/actions.d.ts +1 -1
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +28 -8
  5. package/dist/actions.js.map +1 -1
  6. package/dist/adapters/cloudflare.d.ts.map +1 -1
  7. package/dist/adapters/cloudflare.js +31 -12
  8. package/dist/adapters/cloudflare.js.map +1 -1
  9. package/dist/build.d.ts.map +1 -1
  10. package/dist/build.js +470 -12
  11. package/dist/build.js.map +1 -1
  12. package/dist/cli-options.js +1 -1
  13. package/dist/cli-options.js.map +1 -1
  14. package/dist/client-route-inference.d.ts +1 -1
  15. package/dist/client-route-inference.d.ts.map +1 -1
  16. package/dist/client-route-inference.js +1 -1
  17. package/dist/client-route-inference.js.map +1 -1
  18. package/dist/client.d.ts +8 -1
  19. package/dist/client.d.ts.map +1 -1
  20. package/dist/client.js +16 -0
  21. package/dist/client.js.map +1 -1
  22. package/dist/config.js +1 -1
  23. package/dist/config.js.map +1 -1
  24. package/dist/import-policy.js +7 -0
  25. package/dist/import-policy.js.map +1 -1
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +1 -0
  29. package/dist/index.js.map +1 -1
  30. package/dist/metadata.d.ts +1 -0
  31. package/dist/metadata.d.ts.map +1 -1
  32. package/dist/metadata.js +288 -1
  33. package/dist/metadata.js.map +1 -1
  34. package/dist/middleware.d.ts +5 -0
  35. package/dist/middleware.d.ts.map +1 -1
  36. package/dist/middleware.js +13 -0
  37. package/dist/middleware.js.map +1 -1
  38. package/dist/render.d.ts.map +1 -1
  39. package/dist/render.js +41 -9
  40. package/dist/render.js.map +1 -1
  41. package/dist/typed-routes.d.ts +24 -0
  42. package/dist/typed-routes.d.ts.map +1 -0
  43. package/dist/typed-routes.js +60 -0
  44. package/dist/typed-routes.js.map +1 -0
  45. package/dist/vite.d.ts.map +1 -1
  46. package/dist/vite.js +22 -1
  47. package/dist/vite.js.map +1 -1
  48. package/package.json +11 -11
  49. package/src/actions.ts +39 -12
  50. package/src/adapters/cloudflare.ts +48 -12
  51. package/src/build.ts +491 -11
  52. package/src/cli-options.ts +1 -1
  53. package/src/client-route-inference.ts +1 -0
  54. package/src/client.ts +28 -1
  55. package/src/config.ts +1 -1
  56. package/src/import-policy.ts +8 -0
  57. package/src/index.ts +9 -0
  58. package/src/metadata.ts +388 -1
  59. package/src/middleware.ts +22 -0
  60. package/src/render.ts +58 -7
  61. package/src/typed-routes.ts +121 -0
  62. package/src/vite.ts +25 -0
@@ -5,6 +5,7 @@ import {
5
5
  __MREACT_QUERY_STATE_SCRIPT_ID,
6
6
  createQueryClient,
7
7
  dehydrate,
8
+ isQueryClientScopeUnavailableError,
8
9
  runWithQueryClient,
9
10
  type DehydratedQueryClient,
10
11
  type QueryClient,
@@ -26,7 +27,9 @@ import {
26
27
  } from "../logger.js";
27
28
  import { normalizeRoutePath } from "../route-path.js";
28
29
  import type { AppRoute } from "../routes.js";
30
+ import { contentSecurityPolicy } from "../csp.js";
29
31
  import { isNotFoundError } from "../navigation.js";
32
+ import { validateRouteMetadata } from "../metadata.js";
30
33
  import { routeSecurityHeaders } from "../security-headers.js";
31
34
  import type { AppRouterPrerenderStore } from "../serve.js";
32
35
  import { emitRouterDevtoolsEvent } from "./devtools.js";
@@ -361,7 +364,7 @@ export function createCloudflareRouteModuleRenderer<Env = unknown>(
361
364
  data =
362
365
  pageModule.loader === undefined
363
366
  ? undefined
364
- : await runWithQueryClient(queryClient, () => pageModule.loader!(loaderContext));
367
+ : await runWithCloudflareQueryClient(queryClient, () => pageModule.loader!(loaderContext));
365
368
  } catch (error) {
366
369
  if (error instanceof Response) {
367
370
  return error;
@@ -382,7 +385,7 @@ export function createCloudflareRouteModuleRenderer<Env = unknown>(
382
385
  let rendered: Awaited<ReturnType<typeof component>>;
383
386
 
384
387
  try {
385
- rendered = await runWithQueryClient(queryClient, () => component(props));
388
+ rendered = await runWithCloudflareQueryClient(queryClient, () => component(props));
386
389
  } catch (error) {
387
390
  if (isNotFoundError(error)) {
388
391
  return cloudflareNotFoundResponse(request);
@@ -391,14 +394,15 @@ export function createCloudflareRouteModuleRenderer<Env = unknown>(
391
394
  throw error;
392
395
  }
393
396
 
397
+ const metadata = await runWithCloudflareQueryClient(queryClient, () =>
398
+ resolveCloudflareRouteMetadata([pageModule], props),
399
+ );
400
+
394
401
  if (rendered instanceof Response) {
395
- return withDefaultSecurityHeaders(rendered, request);
402
+ return withDefaultSecurityHeaders(rendered, request, metadata);
396
403
  }
397
404
 
398
405
  const modulePreload = cloudflareModulePreloadTag(context.clientManifest, context.route.path);
399
- const metadata = await runWithQueryClient(queryClient, () =>
400
- resolveCloudflareRouteMetadata([pageModule], props),
401
- );
402
406
  const body = withCloudflareHydrationMarkers({
403
407
  data,
404
408
  html: rendered,
@@ -410,7 +414,7 @@ export function createCloudflareRouteModuleRenderer<Env = unknown>(
410
414
  const documented =
411
415
  options.document === undefined
412
416
  ? defaultCloudflareDocument(body, modulePreload, metadata)
413
- : await runWithQueryClient(queryClient, () =>
417
+ : await runWithCloudflareQueryClient(queryClient, () =>
414
418
  options.document!({
415
419
  ...props,
416
420
  body,
@@ -429,6 +433,7 @@ export function createCloudflareRouteModuleRenderer<Env = unknown>(
429
433
  headers: { "content-type": "text/html; charset=utf-8" },
430
434
  }),
431
435
  request,
436
+ metadata,
432
437
  );
433
438
  };
434
439
  }
@@ -469,6 +474,18 @@ function injectCloudflareQueryStateScript(html: string, state: DehydratedQueryCl
469
474
  : `${html}${script}`;
470
475
  }
471
476
 
477
+ function runWithCloudflareQueryClient<T>(queryClient: QueryClient, fn: () => T): T {
478
+ try {
479
+ return runWithQueryClient(queryClient, fn);
480
+ } catch (error) {
481
+ if (isQueryClientScopeUnavailableError(error)) {
482
+ return fn();
483
+ }
484
+
485
+ throw error;
486
+ }
487
+ }
488
+
472
489
  async function dispatchCloudflareServerRoute<Env>(
473
490
  module: CloudflareServerRouteModule<Env>,
474
491
  request: Request,
@@ -675,10 +692,25 @@ function cloudflareDocumentReloadNavigationResponse(): Response {
675
692
  });
676
693
  }
677
694
 
678
- function withDefaultSecurityHeaders(response: Response, request: Request): Response {
695
+ function withDefaultSecurityHeaders(
696
+ response: Response,
697
+ request: Request,
698
+ metadata?: RouteMetadata | undefined,
699
+ ): Response {
679
700
  const headers = new Headers(response.headers);
701
+ const csp = contentSecurityPolicy(metadata?.csp);
680
702
 
681
- for (const [name, value] of Object.entries(routeSecurityHeaders({ request, security: undefined }))) {
703
+ if (
704
+ isHtmlContentType(headers.get("content-type")) &&
705
+ csp !== undefined &&
706
+ !headers.has("content-security-policy")
707
+ ) {
708
+ headers.set("content-security-policy", csp);
709
+ }
710
+
711
+ for (const [name, value] of Object.entries(
712
+ routeSecurityHeaders({ request, security: metadata?.security }),
713
+ )) {
682
714
  if (!headers.has(name)) {
683
715
  headers.set(name, value);
684
716
  }
@@ -1343,11 +1375,15 @@ async function resolveCloudflareRouteMetadata<Data, Env>(
1343
1375
  const metadata: RouteMetadata[] = [];
1344
1376
 
1345
1377
  for (const module of modules) {
1346
- let next = module.metadata;
1378
+ let next = validateRouteMetadata(module.metadata);
1347
1379
 
1348
1380
  if (module.generateMetadata !== undefined) {
1349
1381
  const generated = await module.generateMetadata(context);
1350
- next = mergeCloudflareRouteMetadata([next, generated].filter(isCloudflareRouteMetadata));
1382
+ next = mergeCloudflareRouteMetadata(
1383
+ [next, validateRouteMetadata(generated, "generateMetadata")].filter(
1384
+ isCloudflareRouteMetadata,
1385
+ ),
1386
+ );
1351
1387
  }
1352
1388
 
1353
1389
  if (next !== undefined) {
@@ -1355,7 +1391,7 @@ async function resolveCloudflareRouteMetadata<Data, Env>(
1355
1391
  }
1356
1392
  }
1357
1393
 
1358
- return mergeCloudflareRouteMetadata(metadata);
1394
+ return validateRouteMetadata(mergeCloudflareRouteMetadata(metadata));
1359
1395
  }
1360
1396
 
1361
1397
  function isCloudflareRouteMetadata(value: RouteMetadata | undefined): value is RouteMetadata {