fimo-react-router 2.6.0 → 2.7.0-staging.2

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.
@@ -1,15 +1,13 @@
1
+ import { type FimoRouteParamConfig } from 'fimo/routes';
1
2
  import React from 'react';
2
3
  export { getPreviewLocationChange, getPreviewLocationPath } from 'fimo/preview';
3
- export interface ParamInfo {
4
- schema: string;
5
- queryField: string;
6
- displayField: string;
7
- }
4
+ /** A route param as `.fimo/config.json` declares it: Studio reads it verbatim. */
5
+ export type ParamInfo = FimoRouteParamConfig;
8
6
  export interface DisplayRoute {
9
7
  id: string;
10
8
  name: string;
11
9
  path: string;
12
- params?: Record<string, ParamInfo>;
10
+ params?: Record<string, FimoRouteParamConfig>;
13
11
  }
14
12
  /**
15
13
  * The routes the running app can actually navigate to right now.
@@ -2,8 +2,9 @@ export declare function resolveFimoLocaleForUrl(url: string): import("fimo-react
2
2
  /**
3
3
  * Fetch route data for SEO meta resolution.
4
4
  *
5
- * Only entry params are fetched: a locale param is resolved from the URL and
6
- * never corresponds to a CMS schema, so it must not produce a request.
5
+ * Only entry params are fetched. A locale param is resolved from the URL, and
6
+ * an external param names a value the application owns; neither corresponds to
7
+ * a CMS schema, so neither ever produces a request.
7
8
  */
8
9
  export declare function resolveMetaEntries(url: string): Promise<Record<string, unknown> | undefined>;
9
10
  //# sourceMappingURL=prefetch.d.ts.map
package/dist/prefetch.js CHANGED
@@ -8,8 +8,9 @@ export function resolveFimoLocaleForUrl(url) {
8
8
  /**
9
9
  * Fetch route data for SEO meta resolution.
10
10
  *
11
- * Only entry params are fetched: a locale param is resolved from the URL and
12
- * never corresponds to a CMS schema, so it must not produce a request.
11
+ * Only entry params are fetched. A locale param is resolved from the URL, and
12
+ * an external param names a value the application owns; neither corresponds to
13
+ * a CMS schema, so neither ever produces a request.
13
14
  */
14
15
  export async function resolveMetaEntries(url) {
15
16
  // @ts-ignore – import.meta.env is a Vite feature, replaced at build time for both client and SSR
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The page URL a loader is rendering, from the request it received.
3
+ *
4
+ * A data request spells the same page differently: prerender and client
5
+ * navigation ask for `/blog/hello.data`, `/blog/hello/_.data` when the path
6
+ * kept its trailing slash, and `/_root.data` for the root, plus a `_routes`
7
+ * search parameter naming the routes being fetched. Reading that pathname as
8
+ * the page would look up an entry whose slug literally ends in `.data`.
9
+ *
10
+ * React Router 8 hands loaders the normalized `url` beside the raw request, so
11
+ * an explicit `url` is authoritative and returned as-is. React Router 7
12
+ * normalizes `request.url` itself unless pass-through requests are enabled,
13
+ * which is why stripping here has to be safe on an already-normalized URL.
14
+ * The rules mirror React Router's own `getNormalizedPath`. A page whose own
15
+ * slug ends in `.data` cannot exist: React Router routes every such pathname
16
+ * to its data handler before any loader runs, so stripping it here never
17
+ * changes which page a document request renders.
18
+ */
19
+ export declare function normalizeLoaderUrl(request: Request, url?: URL | string): string;
20
+ //# sourceMappingURL=request-url.d.ts.map
@@ -0,0 +1,44 @@
1
+ // `_.data` carries the trailing slash the request matched: `/blog/hello/_.data`
2
+ // is the data request for `/blog/hello/`, so the slash survives the strip.
3
+ const TRAILING_SLASH_DATA_SUFFIX = '/_.data';
4
+ const ROOT_DATA_SUFFIX = '/_root.data';
5
+ const DATA_SUFFIX = '.data';
6
+ function stripDataSuffix(pathname) {
7
+ if (pathname.endsWith(TRAILING_SLASH_DATA_SUFFIX)) {
8
+ return pathname.slice(0, -(TRAILING_SLASH_DATA_SUFFIX.length - 1));
9
+ }
10
+ if (pathname.endsWith(ROOT_DATA_SUFFIX)) {
11
+ return pathname.slice(0, -ROOT_DATA_SUFFIX.length) || '/';
12
+ }
13
+ if (pathname.endsWith(DATA_SUFFIX)) {
14
+ return pathname.slice(0, -DATA_SUFFIX.length);
15
+ }
16
+ return pathname;
17
+ }
18
+ /**
19
+ * The page URL a loader is rendering, from the request it received.
20
+ *
21
+ * A data request spells the same page differently: prerender and client
22
+ * navigation ask for `/blog/hello.data`, `/blog/hello/_.data` when the path
23
+ * kept its trailing slash, and `/_root.data` for the root, plus a `_routes`
24
+ * search parameter naming the routes being fetched. Reading that pathname as
25
+ * the page would look up an entry whose slug literally ends in `.data`.
26
+ *
27
+ * React Router 8 hands loaders the normalized `url` beside the raw request, so
28
+ * an explicit `url` is authoritative and returned as-is. React Router 7
29
+ * normalizes `request.url` itself unless pass-through requests are enabled,
30
+ * which is why stripping here has to be safe on an already-normalized URL.
31
+ * The rules mirror React Router's own `getNormalizedPath`. A page whose own
32
+ * slug ends in `.data` cannot exist: React Router routes every such pathname
33
+ * to its data handler before any loader runs, so stripping it here never
34
+ * changes which page a document request renders.
35
+ */
36
+ export function normalizeLoaderUrl(request, url) {
37
+ if (url !== undefined) {
38
+ return String(url);
39
+ }
40
+ const normalized = new URL(request.url);
41
+ normalized.pathname = stripDataSuffix(normalized.pathname);
42
+ normalized.searchParams.delete('_routes');
43
+ return normalized.toString();
44
+ }
package/dist/seo.d.ts CHANGED
@@ -84,9 +84,18 @@ export declare function fimoHtmlProps(localeOrOptions?: string | {
84
84
  lang: string;
85
85
  dir: 'ltr' | 'rtl';
86
86
  };
87
- /** Root-loader helper: per-route SEO entry data plus the resolved locale. */
88
- export declare function loadFimoMetaData({ request }: {
87
+ /**
88
+ * Root-loader helper: per-route SEO entry data plus the resolved locale.
89
+ *
90
+ * Pass the whole loader arguments object. React Router 8 puts the normalized
91
+ * page URL on `url` beside the raw `request`, which still carries the `.data`
92
+ * pathname of a data request; React Router 7 normalizes `request.url` itself
93
+ * unless pass-through requests are enabled. Taking both keeps the lookup on
94
+ * the page being rendered under either version.
95
+ */
96
+ export declare function loadFimoMetaData({ request, url }: {
89
97
  request: Request;
98
+ url?: URL | string;
90
99
  }): Promise<{
91
100
  fimoMetaData: Record<string, unknown> | undefined;
92
101
  fimoLocale: import("fimo-react").FimoLocaleResolution;
package/dist/seo.js CHANGED
@@ -3,6 +3,7 @@ import { normalizePathname, resolveSeoForPath } from 'fimo/seo';
3
3
  // @ts-ignore - virtual module provided by fimoConfigPlugin in fimo-vite
4
4
  import rawConfig from 'virtual:fimo-config';
5
5
  import { resolveFimoLocaleForUrl, resolveMetaEntries } from './prefetch.js';
6
+ import { normalizeLoaderUrl } from './request-url.js';
6
7
  const config = rawConfig;
7
8
  export function getSeoForPath(pathname, routeData) {
8
9
  return resolveSeoForPath(pathname, config, routeData);
@@ -77,9 +78,18 @@ export function fimoHtmlProps(localeOrOptions) {
77
78
  const locale = explicitLocale ?? config.i18n?.defaultLocale ?? 'en';
78
79
  return { lang: toHtmlLang(locale), dir: getFimoTextDirection(locale) };
79
80
  }
80
- /** Root-loader helper: per-route SEO entry data plus the resolved locale. */
81
- export async function loadFimoMetaData({ request }) {
82
- const fimoMetaData = await resolveMetaEntries(request.url);
83
- const fimoLocale = resolveFimoLocaleForUrl(request.url);
81
+ /**
82
+ * Root-loader helper: per-route SEO entry data plus the resolved locale.
83
+ *
84
+ * Pass the whole loader arguments object. React Router 8 puts the normalized
85
+ * page URL on `url` beside the raw `request`, which still carries the `.data`
86
+ * pathname of a data request; React Router 7 normalizes `request.url` itself
87
+ * unless pass-through requests are enabled. Taking both keeps the lookup on
88
+ * the page being rendered under either version.
89
+ */
90
+ export async function loadFimoMetaData({ request, url }) {
91
+ const target = normalizeLoaderUrl(request, url);
92
+ const fimoMetaData = await resolveMetaEntries(target);
93
+ const fimoLocale = resolveFimoLocaleForUrl(target);
84
94
  return { fimoMetaData, fimoLocale };
85
95
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fimo-react-router",
3
- "version": "2.6.0",
3
+ "version": "2.7.0-staging.2",
4
4
  "description": "Fimo runtime, routing and build integration for React Router projects. Pairs with the fimo package at the same version.",
5
5
  "files": [
6
6
  "dist/",
@@ -42,14 +42,14 @@
42
42
  "react-error-boundary": "^6.0.0"
43
43
  },
44
44
  "devDependencies": {
45
- "@fimo/tsconfig": "2.6.0",
45
+ "@fimo/tsconfig": "2.7.0-staging.2",
46
46
  "@tanstack/react-query": "^5.80.6",
47
47
  "@types/node": "22.18.6",
48
48
  "@types/react": "19.2.14",
49
49
  "@types/react-dom": "19.2.3",
50
- "fimo": "2.6.0",
51
- "fimo-react": "2.6.0",
52
- "fimo-vite": "2.6.0",
50
+ "fimo": "2.7.0-staging.2",
51
+ "fimo-react": "2.7.0-staging.2",
52
+ "fimo-vite": "2.7.0-staging.2",
53
53
  "react": "19.2.4",
54
54
  "react-dom": "19.2.4",
55
55
  "react-router": "7.18.2",
@@ -59,7 +59,7 @@
59
59
  },
60
60
  "peerDependencies": {
61
61
  "@tanstack/react-query": "^5.80.6",
62
- "fimo": ">=2.0.1",
62
+ "fimo": "2.7.0-staging.2",
63
63
  "fimo-react": ">=2.0.1",
64
64
  "fimo-vite": ">=2.0.1",
65
65
  "react": "^18.2.0 || ^19.0.0",