@richie-router/react 0.1.1 → 0.1.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.
@@ -104,9 +104,6 @@ var OutletContext = import_react.default.createContext(null);
104
104
  var MatchContext = import_react.default.createContext(null);
105
105
  var MANAGED_HEAD_ATTRIBUTE = "data-richie-router-head";
106
106
  var EMPTY_HEAD = { meta: [], links: [], scripts: [], styles: [] };
107
- function isHeadTagReference(head) {
108
- return typeof head === "string";
109
- }
110
107
  function routeHasRecord(value) {
111
108
  return typeof value === "object" && value !== null;
112
109
  }
@@ -303,13 +300,9 @@ class Router {
303
300
  });
304
301
  }
305
302
  resolveSearch(route, rawSearch) {
306
- const fromHeadTagSchema = route.searchSchema ? route.searchSchema.parse(rawSearch) : {};
307
- const fromRoute = route.options.validateSearch ? route.options.validateSearch(rawSearch) : {};
308
- if (routeHasRecord(fromHeadTagSchema) || routeHasRecord(fromRoute)) {
309
- return {
310
- ...routeHasRecord(fromHeadTagSchema) ? fromHeadTagSchema : {},
311
- ...routeHasRecord(fromRoute) ? fromRoute : {}
312
- };
303
+ const fromSchema = route.searchSchema ? route.searchSchema.parse(rawSearch) : {};
304
+ if (routeHasRecord(fromSchema)) {
305
+ return fromSchema;
313
306
  }
314
307
  return rawSearch;
315
308
  }
@@ -355,17 +348,16 @@ class Router {
355
348
  async resolveLocationHead(matches, location, request) {
356
349
  const resolvedHeadByRoute = new Map;
357
350
  for (const match of matches) {
358
- const headOption = match.route.options.head;
359
- if (!isHeadTagReference(headOption)) {
351
+ if (!match.route.serverHead) {
360
352
  continue;
361
353
  }
362
- resolvedHeadByRoute.set(match.route.fullPath, await this.loadRouteHead(match.route, headOption, match.params, match.search, location, request));
354
+ resolvedHeadByRoute.set(match.route.fullPath, await this.loadRouteHead(match.route, match.params, match.search, location, request));
363
355
  }
364
356
  return import_core.resolveHeadConfig(matches, resolvedHeadByRoute);
365
357
  }
366
- async loadRouteHead(route, headTagName, params, search, location, request) {
358
+ async loadRouteHead(route, params, search, location, request) {
367
359
  const cacheKey = JSON.stringify({
368
- headTagName,
360
+ routeId: route.fullPath,
369
361
  params,
370
362
  search
371
363
  });
@@ -375,31 +367,31 @@ class Router {
375
367
  }
376
368
  const response = this.options.loadRouteHead !== undefined ? await this.options.loadRouteHead({
377
369
  route,
378
- headTagName,
370
+ routeId: route.fullPath,
379
371
  params,
380
372
  search,
381
373
  location,
382
374
  request
383
- }) : await this.fetchRouteHead(route, headTagName, params, search);
375
+ }) : await this.fetchRouteHead(route, params, search);
384
376
  this.headCache.set(cacheKey, {
385
377
  head: response.head,
386
378
  expiresAt: Date.now() + (response.staleTime ?? 0)
387
379
  });
388
380
  return response.head;
389
381
  }
390
- async fetchRouteHead(route, headTagName, params, search) {
382
+ async fetchRouteHead(route, params, search) {
391
383
  const basePath = this.options.headBasePath ?? "/head-api";
392
384
  const searchParams = new URLSearchParams({
393
385
  routeId: route.fullPath,
394
386
  params: JSON.stringify(params),
395
387
  search: JSON.stringify(search)
396
388
  });
397
- const response = await fetch(`${basePath}/${encodeURIComponent(headTagName)}?${searchParams.toString()}`);
389
+ const response = await fetch(`${basePath}?${searchParams.toString()}`);
398
390
  if (!response.ok) {
399
391
  if (response.status === 404) {
400
392
  throw import_core.notFound();
401
393
  }
402
- throw new Error(`Failed to resolve head tag "${headTagName}" for route "${route.fullPath}"`);
394
+ throw new Error(`Failed to resolve server head for route "${route.fullPath}"`);
403
395
  }
404
396
  return await response.json();
405
397
  }
@@ -27,9 +27,6 @@ var OutletContext = React.createContext(null);
27
27
  var MatchContext = React.createContext(null);
28
28
  var MANAGED_HEAD_ATTRIBUTE = "data-richie-router-head";
29
29
  var EMPTY_HEAD = { meta: [], links: [], scripts: [], styles: [] };
30
- function isHeadTagReference(head) {
31
- return typeof head === "string";
32
- }
33
30
  function routeHasRecord(value) {
34
31
  return typeof value === "object" && value !== null;
35
32
  }
@@ -226,13 +223,9 @@ class Router {
226
223
  });
227
224
  }
228
225
  resolveSearch(route, rawSearch) {
229
- const fromHeadTagSchema = route.searchSchema ? route.searchSchema.parse(rawSearch) : {};
230
- const fromRoute = route.options.validateSearch ? route.options.validateSearch(rawSearch) : {};
231
- if (routeHasRecord(fromHeadTagSchema) || routeHasRecord(fromRoute)) {
232
- return {
233
- ...routeHasRecord(fromHeadTagSchema) ? fromHeadTagSchema : {},
234
- ...routeHasRecord(fromRoute) ? fromRoute : {}
235
- };
226
+ const fromSchema = route.searchSchema ? route.searchSchema.parse(rawSearch) : {};
227
+ if (routeHasRecord(fromSchema)) {
228
+ return fromSchema;
236
229
  }
237
230
  return rawSearch;
238
231
  }
@@ -278,17 +271,16 @@ class Router {
278
271
  async resolveLocationHead(matches, location, request) {
279
272
  const resolvedHeadByRoute = new Map;
280
273
  for (const match of matches) {
281
- const headOption = match.route.options.head;
282
- if (!isHeadTagReference(headOption)) {
274
+ if (!match.route.serverHead) {
283
275
  continue;
284
276
  }
285
- resolvedHeadByRoute.set(match.route.fullPath, await this.loadRouteHead(match.route, headOption, match.params, match.search, location, request));
277
+ resolvedHeadByRoute.set(match.route.fullPath, await this.loadRouteHead(match.route, match.params, match.search, location, request));
286
278
  }
287
279
  return resolveHeadConfig(matches, resolvedHeadByRoute);
288
280
  }
289
- async loadRouteHead(route, headTagName, params, search, location, request) {
281
+ async loadRouteHead(route, params, search, location, request) {
290
282
  const cacheKey = JSON.stringify({
291
- headTagName,
283
+ routeId: route.fullPath,
292
284
  params,
293
285
  search
294
286
  });
@@ -298,31 +290,31 @@ class Router {
298
290
  }
299
291
  const response = this.options.loadRouteHead !== undefined ? await this.options.loadRouteHead({
300
292
  route,
301
- headTagName,
293
+ routeId: route.fullPath,
302
294
  params,
303
295
  search,
304
296
  location,
305
297
  request
306
- }) : await this.fetchRouteHead(route, headTagName, params, search);
298
+ }) : await this.fetchRouteHead(route, params, search);
307
299
  this.headCache.set(cacheKey, {
308
300
  head: response.head,
309
301
  expiresAt: Date.now() + (response.staleTime ?? 0)
310
302
  });
311
303
  return response.head;
312
304
  }
313
- async fetchRouteHead(route, headTagName, params, search) {
305
+ async fetchRouteHead(route, params, search) {
314
306
  const basePath = this.options.headBasePath ?? "/head-api";
315
307
  const searchParams = new URLSearchParams({
316
308
  routeId: route.fullPath,
317
309
  params: JSON.stringify(params),
318
310
  search: JSON.stringify(search)
319
311
  });
320
- const response = await fetch(`${basePath}/${encodeURIComponent(headTagName)}?${searchParams.toString()}`);
312
+ const response = await fetch(`${basePath}?${searchParams.toString()}`);
321
313
  if (!response.ok) {
322
314
  if (response.status === 404) {
323
315
  throw notFound();
324
316
  }
325
- throw new Error(`Failed to resolve head tag "${headTagName}" for route "${route.fullPath}"`);
317
+ throw new Error(`Failed to resolve server head for route "${route.fullPath}"`);
326
318
  }
327
319
  return await response.json();
328
320
  }
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { RouteNode, isNotFound, isRedirect, notFound, redirect } from '@richie-router/core';
3
- import type { AnyComponent, AnyRoute, DehydratedHeadState, HeadConfig, NormalizeRouteId, ParsedLocation, ResolveAllParams, RouteMatch, RouteOptions as CoreRouteOptions, Simplify } from '@richie-router/core';
3
+ import type { AnyComponent, AnyRoute, DehydratedHeadState, HeadConfig, NormalizeRouteId, ParsedLocation, ResolveAllParams, RouteMatch, RouteOptions as CoreRouteOptions } from '@richie-router/core';
4
4
  import { createBrowserHistory, createHashHistory, createMemoryHistory } from './history';
5
5
  import type { MemoryHistoryOptions, RouterHistory } from './history';
6
6
  declare global {
@@ -10,12 +10,9 @@ declare global {
10
10
  }
11
11
  export interface Register {
12
12
  }
13
- type RegisteredHeadTagMap = Register extends {
14
- headTagMap: infer THeadTagMap;
15
- } ? THeadTagMap : Record<string, string>;
16
- type RegisteredHeadTagSearchSchema = Register extends {
17
- headTagSearchSchema: infer THeadTagSearchSchema;
18
- } ? THeadTagSearchSchema : Record<string, {}>;
13
+ type RegisteredRouteSearchSchema = Register extends {
14
+ routeSearchSchema: infer TRouteSearchSchema;
15
+ } ? TRouteSearchSchema : Record<string, {}>;
19
16
  type RegisteredRouteTree = Register extends {
20
17
  routeTree: infer TRouteTree;
21
18
  } ? TRouteTree : AnyRoute;
@@ -65,8 +62,7 @@ type MatchOfRoute<TRoute> = {
65
62
  type SafeRouteByTo<TTo extends string> = [RouteById<TTo>] extends [never] ? AnyRoute : RouteById<TTo>;
66
63
  type ParamsForTo<TTo extends string> = ParamsOfRoute<SafeRouteByTo<TTo>>;
67
64
  type SearchForTo<TTo extends string> = SearchOfRoute<SafeRouteByTo<TTo>>;
68
- type SearchForFullPath<TPath extends string> = TPath extends keyof RegisteredHeadTagSearchSchema ? RegisteredHeadTagSearchSchema[TPath] : {};
69
- type HeadTagNameForFullPath<TPath extends string> = TPath extends keyof RegisteredHeadTagMap ? RegisteredHeadTagMap[TPath] : string;
65
+ type SearchForRouteId<TPath extends string> = TPath extends keyof RegisteredRouteSearchSchema ? RegisteredRouteSearchSchema[TPath] : {};
70
66
  type ParamsInput<TParams> = TParams | ((previous: TParams) => TParams);
71
67
  type SearchInput<TSearch> = TSearch | ((previous: TSearch) => TSearch) | true;
72
68
  type ParamsOption<TParams> = keyof TParams extends never ? {
@@ -79,11 +75,12 @@ type ClientHeadOption<TPath extends string, TSearch> = HeadConfig | ((ctx: {
79
75
  search: TSearch;
80
76
  matches: RouteMatch[];
81
77
  }) => HeadConfig);
82
- type RouteHeadOption<TPath extends string, TSearch> = ClientHeadOption<TPath, TSearch> | (HeadTagNameForFullPath<TPath> extends never ? never : HeadTagNameForFullPath<TPath>);
83
78
  type RouteOptionsInput<TPath extends string, TSearch> = Omit<CoreRouteOptions<TPath, TSearch>, 'head'> & {
84
- head?: RouteHeadOption<TPath, TSearch>;
79
+ head?: ClientHeadOption<TPath, TSearch>;
80
+ };
81
+ type FileRouteInstance<TPath extends string, TSearch, TFileTypes = unknown, THasInlineHead extends boolean = boolean> = RouteNode<TPath, NormalizeRouteId<TPath>, ResolveAllParams<TPath>, TSearch, TFileTypes> & RouteApiMethods<RouteNode<TPath, NormalizeRouteId<TPath>, ResolveAllParams<TPath>, TSearch, TFileTypes>> & {
82
+ __hasInlineHead: THasInlineHead;
85
83
  };
86
- type FileRouteInstance<TPath extends string, TSearch, TFileTypes = unknown> = RouteNode<TPath, NormalizeRouteId<TPath>, ResolveAllParams<TPath>, TSearch, TFileTypes> & RouteApiMethods<RouteNode<TPath, NormalizeRouteId<TPath>, ResolveAllParams<TPath>, TSearch, TFileTypes>>;
87
84
  export interface TypedRouteMatch<TPath extends string, TSearch, TRoute extends AnyRoute = AnyRoute> extends Omit<RouteMatch<TRoute>, 'params' | 'search'> {
88
85
  params: ResolveAllParams<TPath>;
89
86
  search: TSearch;
@@ -142,7 +139,7 @@ export interface RouterOptions<TRouteTree extends AnyRoute> {
142
139
  stringifySearch?: (search: Record<string, unknown>) => string;
143
140
  loadRouteHead?: (ctx: {
144
141
  route: AnyRoute;
145
- headTagName: string;
142
+ routeId: string;
146
143
  params: Record<string, string>;
147
144
  search: unknown;
148
145
  location: ParsedLocation;
@@ -156,12 +153,12 @@ type InternalRouteMatch = RouteMatch & {
156
153
  id: string;
157
154
  };
158
155
  type Selector<TSelection> = (state: RouterState) => TSelection;
159
- export declare function createFileRoute<TPath extends string>(path: TPath): <TCustomSearch = {}>(options: RouteOptionsInput<TPath, Simplify<SearchForFullPath<TPath> & TCustomSearch>> & {
160
- validateSearch?: (raw: Record<string, unknown>) => TCustomSearch;
161
- }) => FileRouteInstance<TPath, Simplify<SearchForFullPath<TPath> & TCustomSearch>>;
162
- export declare function createRootRoute<TCustomSearch = {}>(options: CoreRouteOptions<'__root__', TCustomSearch> & {
163
- validateSearch?: (raw: Record<string, unknown>) => TCustomSearch;
164
- }): FileRouteInstance<'__root__', TCustomSearch>;
156
+ export declare function createFileRoute<TPath extends string>(path: TPath): <TOptions extends RouteOptionsInput<TPath, SearchForRouteId<TPath>>>(options: TOptions) => FileRouteInstance<TPath, SearchForRouteId<TPath>, unknown, TOptions extends {
157
+ head: any;
158
+ } ? true : false>;
159
+ export declare function createRootRoute<TOptions extends RouteOptionsInput<'__root__', SearchForRouteId<'__root__'>>>(options: TOptions): FileRouteInstance<'__root__', SearchForRouteId<'__root__'>, unknown, TOptions extends {
160
+ head: any;
161
+ } ? true : false>;
165
162
  export declare class Router<TRouteTree extends AnyRoute> {
166
163
  readonly routeTree: TRouteTree;
167
164
  readonly history: RouterHistory;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@richie-router/react",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "React runtime, components, and hooks for Richie Router",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -13,7 +13,7 @@
13
13
  }
14
14
  },
15
15
  "dependencies": {
16
- "@richie-router/core": "^0.1.1"
16
+ "@richie-router/core": "^0.1.2"
17
17
  },
18
18
  "peerDependencies": {
19
19
  "react": "^19"