@tanstack/react-router 1.87.1 → 1.87.3

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,4 +1,5 @@
1
1
  import { Store, NoInfer } from '@tanstack/react-store';
2
+ import { DeferredPromiseState } from './defer.cjs';
2
3
  import { HistoryState, RouterHistory } from '@tanstack/history';
3
4
  import { Manifest } from './manifest.cjs';
4
5
  import { AnyContext, AnyRoute, AnyRouteWithContext, ErrorRouteComponent, NotFoundRouteComponent, RootRoute, RouteComponent, RouteMask } from './route.cjs';
@@ -44,15 +45,22 @@ export type HydrationCtx = {
44
45
  payload: Record<string, any>;
45
46
  };
46
47
  export type InferRouterContext<TRouteTree extends AnyRoute> = TRouteTree extends RootRoute<any, infer TRouterContext extends AnyContext, any, any, any, any, any, any> ? TRouterContext : AnyContext;
47
- export type ExtractedEntry = {
48
+ export interface ExtractedBaseEntry {
48
49
  dataType: '__beforeLoadContext' | 'loaderData';
49
- type: 'promise' | 'stream';
50
+ type: string;
50
51
  path: Array<string>;
51
- value: any;
52
52
  id: number;
53
- streamState?: StreamState;
54
53
  matchIndex: number;
55
- };
54
+ }
55
+ export interface ExtractedStream extends ExtractedBaseEntry {
56
+ type: 'stream';
57
+ streamState: StreamState;
58
+ }
59
+ export interface ExtractedPromise extends ExtractedBaseEntry {
60
+ type: 'promise';
61
+ promiseState: DeferredPromiseState<any>;
62
+ }
63
+ export type ExtractedEntry = ExtractedStream | ExtractedPromise;
56
64
  export type StreamState = {
57
65
  promises: Array<ControlledPromise<string | null>>;
58
66
  };
@@ -9,7 +9,7 @@ function Transitioner() {
9
9
  const isLoading = useRouterState({
10
10
  select: ({ isLoading: isLoading2 }) => isLoading2
11
11
  });
12
- const [isTransitioning, startReactTransition_] = React.useTransition();
12
+ const [isTransitioning, setIsTransitioning] = React.useState(false);
13
13
  const hasPendingMatches = useRouterState({
14
14
  select: (s) => s.matches.some((d) => d.status === "pending"),
15
15
  structuralSharing: true
@@ -20,7 +20,13 @@ function Transitioner() {
20
20
  const isPagePending = isLoading || hasPendingMatches;
21
21
  const previousIsPagePending = usePrevious(isPagePending);
22
22
  if (!router.isServer) {
23
- router.startReactTransition = startReactTransition_;
23
+ router.startReactTransition = (fn) => {
24
+ setIsTransitioning(true);
25
+ React.startTransition(() => {
26
+ fn();
27
+ setIsTransitioning(false);
28
+ });
29
+ };
24
30
  }
25
31
  React.useEffect(() => {
26
32
  const unsub = router.history.subscribe(router.load);
@@ -1 +1 @@
1
- {"version":3,"file":"Transitioner.js","sources":["../../src/Transitioner.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useLayoutEffect, usePrevious } from './utils'\nimport { useRouter } from './useRouter'\nimport { useRouterState } from './useRouterState'\nimport { trimPathRight } from './path'\n\nexport function Transitioner() {\n const router = useRouter()\n const mountLoadForRouter = React.useRef({ router, mounted: false })\n const isLoading = useRouterState({\n select: ({ isLoading }) => isLoading,\n })\n\n const [isTransitioning, startReactTransition_] = React.useTransition()\n // Track pending state changes\n const hasPendingMatches = useRouterState({\n select: (s) => s.matches.some((d) => d.status === 'pending'),\n structuralSharing: true,\n })\n\n const previousIsLoading = usePrevious(isLoading)\n\n const isAnyPending = isLoading || isTransitioning || hasPendingMatches\n const previousIsAnyPending = usePrevious(isAnyPending)\n\n const isPagePending = isLoading || hasPendingMatches\n const previousIsPagePending = usePrevious(isPagePending)\n\n if (!router.isServer) {\n router.startReactTransition = startReactTransition_\n }\n\n // Subscribe to location changes\n // and try to load the new location\n React.useEffect(() => {\n const unsub = router.history.subscribe(router.load)\n\n const nextLocation = router.buildLocation({\n to: router.latestLocation.pathname,\n search: true,\n params: true,\n hash: true,\n state: true,\n _includeValidateSearch: true,\n })\n\n if (\n trimPathRight(router.latestLocation.href) !==\n trimPathRight(nextLocation.href)\n ) {\n router.commitLocation({ ...nextLocation, replace: true })\n }\n\n return () => {\n unsub()\n }\n }, [router, router.history])\n\n // Try to load the initial location\n useLayoutEffect(() => {\n if (\n (typeof window !== 'undefined' && window.__TSR__?.dehydrated) ||\n (mountLoadForRouter.current.router === router &&\n mountLoadForRouter.current.mounted)\n ) {\n return\n }\n mountLoadForRouter.current = { router, mounted: true }\n\n const tryLoad = async () => {\n try {\n await router.load()\n } catch (err) {\n console.error(err)\n }\n }\n\n tryLoad()\n }, [router])\n\n useLayoutEffect(() => {\n // The router was loading and now it's not\n if (previousIsLoading && !isLoading) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n const hrefChanged = fromLocation.href !== toLocation.href\n\n router.emit({\n type: 'onLoad', // When the new URL has committed, when the new matches have been loaded into state.matches\n fromLocation,\n toLocation,\n pathChanged,\n hrefChanged,\n })\n }\n }, [previousIsLoading, router, isLoading])\n\n useLayoutEffect(() => {\n // emit onBeforeRouteMount\n if (previousIsPagePending && !isPagePending) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n const hrefChanged = fromLocation.href !== toLocation.href\n\n router.emit({\n type: 'onBeforeRouteMount',\n fromLocation,\n toLocation,\n pathChanged,\n hrefChanged,\n })\n }\n }, [isPagePending, previousIsPagePending, router])\n\n useLayoutEffect(() => {\n // The router was pending and now it's not\n if (previousIsAnyPending && !isAnyPending) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n const hrefChanged = fromLocation.href !== toLocation.href\n\n router.emit({\n type: 'onResolved',\n fromLocation,\n toLocation,\n pathChanged,\n hrefChanged,\n })\n\n router.__store.setState((s) => ({\n ...s,\n status: 'idle',\n resolvedLocation: s.location,\n }))\n\n if (typeof document !== 'undefined' && (document as any).querySelector) {\n if (router.state.location.hash !== '') {\n const el = document.getElementById(router.state.location.hash)\n if (el) {\n el.scrollIntoView()\n }\n }\n }\n }\n }, [isAnyPending, previousIsAnyPending, router])\n\n return null\n}\n"],"names":["isLoading"],"mappings":";;;;;AAMO,SAAS,eAAe;AAC7B,QAAM,SAAS,UAAU;AACzB,QAAM,qBAAqB,MAAM,OAAO,EAAE,QAAQ,SAAS,OAAO;AAClE,QAAM,YAAY,eAAe;AAAA,IAC/B,QAAQ,CAAC,EAAE,WAAAA,iBAAgBA;AAAAA,EAAA,CAC5B;AAED,QAAM,CAAC,iBAAiB,qBAAqB,IAAI,MAAM,cAAc;AAErE,QAAM,oBAAoB,eAAe;AAAA,IACvC,QAAQ,CAAC,MAAM,EAAE,QAAQ,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS;AAAA,IAC3D,mBAAmB;AAAA,EAAA,CACpB;AAEK,QAAA,oBAAoB,YAAY,SAAS;AAEzC,QAAA,eAAe,aAAa,mBAAmB;AAC/C,QAAA,uBAAuB,YAAY,YAAY;AAErD,QAAM,gBAAgB,aAAa;AAC7B,QAAA,wBAAwB,YAAY,aAAa;AAEnD,MAAA,CAAC,OAAO,UAAU;AACpB,WAAO,uBAAuB;AAAA,EAAA;AAKhC,QAAM,UAAU,MAAM;AACpB,UAAM,QAAQ,OAAO,QAAQ,UAAU,OAAO,IAAI;AAE5C,UAAA,eAAe,OAAO,cAAc;AAAA,MACxC,IAAI,OAAO,eAAe;AAAA,MAC1B,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,wBAAwB;AAAA,IAAA,CACzB;AAGC,QAAA,cAAc,OAAO,eAAe,IAAI,MACxC,cAAc,aAAa,IAAI,GAC/B;AACA,aAAO,eAAe,EAAE,GAAG,cAAc,SAAS,MAAM;AAAA,IAAA;AAG1D,WAAO,MAAM;AACL,YAAA;AAAA,IACR;AAAA,EACC,GAAA,CAAC,QAAQ,OAAO,OAAO,CAAC;AAG3B,kBAAgB,MAAM;;AACpB,QACG,OAAO,WAAW,iBAAe,YAAO,YAAP,mBAAgB,eACjD,mBAAmB,QAAQ,WAAW,UACrC,mBAAmB,QAAQ,SAC7B;AACA;AAAA,IAAA;AAEF,uBAAmB,UAAU,EAAE,QAAQ,SAAS,KAAK;AAErD,UAAM,UAAU,YAAY;AACtB,UAAA;AACF,cAAM,OAAO,KAAK;AAAA,eACX,KAAK;AACZ,gBAAQ,MAAM,GAAG;AAAA,MAAA;AAAA,IAErB;AAEQ,YAAA;AAAA,EAAA,GACP,CAAC,MAAM,CAAC;AAEX,kBAAgB,MAAM;AAEhB,QAAA,qBAAqB,CAAC,WAAW;AAC7B,YAAA,aAAa,OAAO,MAAM;AAC1B,YAAA,eAAe,OAAO,MAAM;AAC5B,YAAA,cAAc,aAAa,aAAa,WAAW;AACnD,YAAA,cAAc,aAAa,SAAS,WAAW;AAErD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IAAA;AAAA,EAEF,GAAA,CAAC,mBAAmB,QAAQ,SAAS,CAAC;AAEzC,kBAAgB,MAAM;AAEhB,QAAA,yBAAyB,CAAC,eAAe;AACrC,YAAA,aAAa,OAAO,MAAM;AAC1B,YAAA,eAAe,OAAO,MAAM;AAC5B,YAAA,cAAc,aAAa,aAAa,WAAW;AACnD,YAAA,cAAc,aAAa,SAAS,WAAW;AAErD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAAA,IAAA;AAAA,EAEF,GAAA,CAAC,eAAe,uBAAuB,MAAM,CAAC;AAEjD,kBAAgB,MAAM;AAEhB,QAAA,wBAAwB,CAAC,cAAc;AACnC,YAAA,aAAa,OAAO,MAAM;AAC1B,YAAA,eAAe,OAAO,MAAM;AAC5B,YAAA,cAAc,aAAa,aAAa,WAAW;AACnD,YAAA,cAAc,aAAa,SAAS,WAAW;AAErD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA,CACD;AAEM,aAAA,QAAQ,SAAS,CAAC,OAAO;AAAA,QAC9B,GAAG;AAAA,QACH,QAAQ;AAAA,QACR,kBAAkB,EAAE;AAAA,MAAA,EACpB;AAEF,UAAI,OAAO,aAAa,eAAgB,SAAiB,eAAe;AACtE,YAAI,OAAO,MAAM,SAAS,SAAS,IAAI;AACrC,gBAAM,KAAK,SAAS,eAAe,OAAO,MAAM,SAAS,IAAI;AAC7D,cAAI,IAAI;AACN,eAAG,eAAe;AAAA,UAAA;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,EAED,GAAA,CAAC,cAAc,sBAAsB,MAAM,CAAC;AAExC,SAAA;AACT;"}
1
+ {"version":3,"file":"Transitioner.js","sources":["../../src/Transitioner.tsx"],"sourcesContent":["import * as React from 'react'\nimport { useLayoutEffect, usePrevious } from './utils'\nimport { useRouter } from './useRouter'\nimport { useRouterState } from './useRouterState'\nimport { trimPathRight } from './path'\n\nexport function Transitioner() {\n const router = useRouter()\n const mountLoadForRouter = React.useRef({ router, mounted: false })\n const isLoading = useRouterState({\n select: ({ isLoading }) => isLoading,\n })\n\n const [isTransitioning, setIsTransitioning] = React.useState(false)\n // Track pending state changes\n const hasPendingMatches = useRouterState({\n select: (s) => s.matches.some((d) => d.status === 'pending'),\n structuralSharing: true,\n })\n\n const previousIsLoading = usePrevious(isLoading)\n\n const isAnyPending = isLoading || isTransitioning || hasPendingMatches\n const previousIsAnyPending = usePrevious(isAnyPending)\n\n const isPagePending = isLoading || hasPendingMatches\n const previousIsPagePending = usePrevious(isPagePending)\n\n if (!router.isServer) {\n router.startReactTransition = (fn: () => void) => {\n setIsTransitioning(true)\n React.startTransition(() => {\n fn()\n setIsTransitioning(false)\n })\n }\n }\n\n // Subscribe to location changes\n // and try to load the new location\n React.useEffect(() => {\n const unsub = router.history.subscribe(router.load)\n\n const nextLocation = router.buildLocation({\n to: router.latestLocation.pathname,\n search: true,\n params: true,\n hash: true,\n state: true,\n _includeValidateSearch: true,\n })\n\n if (\n trimPathRight(router.latestLocation.href) !==\n trimPathRight(nextLocation.href)\n ) {\n router.commitLocation({ ...nextLocation, replace: true })\n }\n\n return () => {\n unsub()\n }\n }, [router, router.history])\n\n // Try to load the initial location\n useLayoutEffect(() => {\n if (\n (typeof window !== 'undefined' && window.__TSR__?.dehydrated) ||\n (mountLoadForRouter.current.router === router &&\n mountLoadForRouter.current.mounted)\n ) {\n return\n }\n mountLoadForRouter.current = { router, mounted: true }\n\n const tryLoad = async () => {\n try {\n await router.load()\n } catch (err) {\n console.error(err)\n }\n }\n\n tryLoad()\n }, [router])\n\n useLayoutEffect(() => {\n // The router was loading and now it's not\n if (previousIsLoading && !isLoading) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n const hrefChanged = fromLocation.href !== toLocation.href\n\n router.emit({\n type: 'onLoad', // When the new URL has committed, when the new matches have been loaded into state.matches\n fromLocation,\n toLocation,\n pathChanged,\n hrefChanged,\n })\n }\n }, [previousIsLoading, router, isLoading])\n\n useLayoutEffect(() => {\n // emit onBeforeRouteMount\n if (previousIsPagePending && !isPagePending) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n const hrefChanged = fromLocation.href !== toLocation.href\n\n router.emit({\n type: 'onBeforeRouteMount',\n fromLocation,\n toLocation,\n pathChanged,\n hrefChanged,\n })\n }\n }, [isPagePending, previousIsPagePending, router])\n\n useLayoutEffect(() => {\n // The router was pending and now it's not\n if (previousIsAnyPending && !isAnyPending) {\n const toLocation = router.state.location\n const fromLocation = router.state.resolvedLocation\n const pathChanged = fromLocation.pathname !== toLocation.pathname\n const hrefChanged = fromLocation.href !== toLocation.href\n\n router.emit({\n type: 'onResolved',\n fromLocation,\n toLocation,\n pathChanged,\n hrefChanged,\n })\n\n router.__store.setState((s) => ({\n ...s,\n status: 'idle',\n resolvedLocation: s.location,\n }))\n\n if (typeof document !== 'undefined' && (document as any).querySelector) {\n if (router.state.location.hash !== '') {\n const el = document.getElementById(router.state.location.hash)\n if (el) {\n el.scrollIntoView()\n }\n }\n }\n }\n }, [isAnyPending, previousIsAnyPending, router])\n\n return null\n}\n"],"names":["isLoading"],"mappings":"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"}
@@ -3,37 +3,37 @@ import * as React from "react";
3
3
  import warning from "tiny-warning";
4
4
  import { useRouter } from "./useRouter.js";
5
5
  import { defaultSerializeError } from "./router.js";
6
- import { defer } from "./defer.js";
6
+ import { defer, TSR_DEFERRED_PROMISE } from "./defer.js";
7
7
  import { isServerSideError, defaultDeserializeError } from "./isServerSideError.js";
8
8
  function useAwaited({
9
9
  promise: _promise
10
10
  }) {
11
11
  var _a, _b;
12
12
  const router = useRouter();
13
- const promise = _promise;
14
- defer(promise);
15
- if (promise.status === "pending") {
13
+ const promise = defer(_promise);
14
+ if (promise[TSR_DEFERRED_PROMISE].status === "pending") {
16
15
  throw promise;
17
16
  }
18
- if (promise.status === "error") {
17
+ if (promise[TSR_DEFERRED_PROMISE].status === "error") {
19
18
  if (typeof document !== "undefined") {
20
- if (isServerSideError(promise.error)) {
21
- throw (((_a = router.options.errorSerializer) == null ? void 0 : _a.deserialize) ?? defaultDeserializeError)(promise.error.data);
19
+ if (isServerSideError(promise[TSR_DEFERRED_PROMISE].error)) {
20
+ throw (((_a = router.options.errorSerializer) == null ? void 0 : _a.deserialize) ?? defaultDeserializeError)(promise[TSR_DEFERRED_PROMISE].error.data);
22
21
  } else {
23
22
  warning(
24
23
  false,
25
24
  "Encountered a server-side error that doesn't fit the expected shape"
26
25
  );
27
- throw promise.error;
26
+ throw promise[TSR_DEFERRED_PROMISE].error;
28
27
  }
29
28
  } else {
30
29
  throw {
31
- data: (((_b = router.options.errorSerializer) == null ? void 0 : _b.serialize) ?? defaultSerializeError)(promise.error),
30
+ data: (((_b = router.options.errorSerializer) == null ? void 0 : _b.serialize) ?? defaultSerializeError)(promise[TSR_DEFERRED_PROMISE].error),
32
31
  __isServerError: true
33
32
  };
34
33
  }
35
34
  }
36
- return [promise.data, promise];
35
+ console.log("useAwaited", promise[TSR_DEFERRED_PROMISE]);
36
+ return [promise[TSR_DEFERRED_PROMISE].data, promise];
37
37
  }
38
38
  function Await(props) {
39
39
  const inner = /* @__PURE__ */ jsx(AwaitInner, { ...props });
@@ -44,6 +44,7 @@ function Await(props) {
44
44
  }
45
45
  function AwaitInner(props) {
46
46
  const [data] = useAwaited(props);
47
+ console.log("AwaitInner", data);
47
48
  return props.children(data);
48
49
  }
49
50
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"awaited.js","sources":["../../src/awaited.tsx"],"sourcesContent":["import * as React from 'react'\nimport warning from 'tiny-warning'\nimport { useRouter } from './useRouter'\nimport { defaultSerializeError } from './router'\nimport { defer } from './defer'\nimport { defaultDeserializeError, isServerSideError } from './isServerSideError'\nimport type { DeferredPromise } from './defer'\n\nexport type AwaitOptions<T> = {\n promise: Promise<T>\n}\n\nexport function useAwaited<T>({\n promise: _promise,\n}: AwaitOptions<T>): [T, DeferredPromise<T>] {\n const router = useRouter()\n const promise = _promise as DeferredPromise<T>\n\n defer(promise)\n\n if (promise.status === 'pending') {\n throw promise\n }\n\n if (promise.status === 'error') {\n if (typeof document !== 'undefined') {\n if (isServerSideError(promise.error)) {\n throw (\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n )(promise.error.data as any)\n } else {\n warning(\n false,\n \"Encountered a server-side error that doesn't fit the expected shape\",\n )\n throw promise.error\n }\n } else {\n throw {\n data: (\n router.options.errorSerializer?.serialize ?? defaultSerializeError\n )(promise.error),\n __isServerError: true,\n }\n }\n }\n\n return [promise.data as any, promise]\n}\n\nexport function Await<T>(\n props: AwaitOptions<T> & {\n fallback?: React.ReactNode\n children: (result: T) => React.ReactNode\n },\n) {\n const inner = <AwaitInner {...props} />\n if (props.fallback) {\n return <React.Suspense fallback={props.fallback}>{inner}</React.Suspense>\n }\n return inner\n}\n\nfunction AwaitInner<T>(\n props: AwaitOptions<T> & {\n fallback?: React.ReactNode\n children: (result: T) => React.ReactNode\n },\n): React.JSX.Element {\n const [data] = useAwaited(props)\n return props.children(data) as React.JSX.Element\n}\n"],"names":[],"mappings":";;;;;;;AAYO,SAAS,WAAc;AAAA,EAC5B,SAAS;AACX,GAA6C;;AAC3C,QAAM,SAAS,UAAU;AACzB,QAAM,UAAU;AAEhB,QAAM,OAAO;AAET,MAAA,QAAQ,WAAW,WAAW;AAC1B,UAAA;AAAA,EAAA;AAGJ,MAAA,QAAQ,WAAW,SAAS;AAC1B,QAAA,OAAO,aAAa,aAAa;AAC/B,UAAA,kBAAkB,QAAQ,KAAK,GAAG;AACpC,iBACE,YAAO,QAAQ,oBAAf,mBAAgC,gBAAe,yBAC/C,QAAQ,MAAM,IAAW;AAAA,MAAA,OACtB;AACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AACA,cAAM,QAAQ;AAAA,MAAA;AAAA,IAChB,OACK;AACC,YAAA;AAAA,QACJ,SACE,YAAO,QAAQ,oBAAf,mBAAgC,cAAa,uBAC7C,QAAQ,KAAK;AAAA,QACf,iBAAiB;AAAA,MACnB;AAAA,IAAA;AAAA,EACF;AAGK,SAAA,CAAC,QAAQ,MAAa,OAAO;AACtC;AAEO,SAAS,MACd,OAIA;AACA,QAAM,QAAQ,oBAAC,YAAY,EAAA,GAAG,MAAO,CAAA;AACrC,MAAI,MAAM,UAAU;AAClB,+BAAQ,MAAM,UAAN,EAAe,UAAU,MAAM,UAAW,UAAM,OAAA;AAAA,EAAA;AAEnD,SAAA;AACT;AAEA,SAAS,WACP,OAImB;AACnB,QAAM,CAAC,IAAI,IAAI,WAAW,KAAK;AACxB,SAAA,MAAM,SAAS,IAAI;AAC5B;"}
1
+ {"version":3,"file":"awaited.js","sources":["../../src/awaited.tsx"],"sourcesContent":["import * as React from 'react'\nimport warning from 'tiny-warning'\nimport { useRouter } from './useRouter'\nimport { defaultSerializeError } from './router'\nimport { TSR_DEFERRED_PROMISE, defer } from './defer'\nimport { defaultDeserializeError, isServerSideError } from './isServerSideError'\nimport type { DeferredPromise } from './defer'\n\nexport type AwaitOptions<T> = {\n promise: Promise<T>\n}\n\nexport function useAwaited<T>({\n promise: _promise,\n}: AwaitOptions<T>): [T, DeferredPromise<T>] {\n const router = useRouter()\n const promise = defer(_promise)\n\n if (promise[TSR_DEFERRED_PROMISE].status === 'pending') {\n throw promise\n }\n\n if (promise[TSR_DEFERRED_PROMISE].status === 'error') {\n if (typeof document !== 'undefined') {\n if (isServerSideError(promise[TSR_DEFERRED_PROMISE].error)) {\n throw (\n router.options.errorSerializer?.deserialize ?? defaultDeserializeError\n )(promise[TSR_DEFERRED_PROMISE].error.data as any)\n } else {\n warning(\n false,\n \"Encountered a server-side error that doesn't fit the expected shape\",\n )\n throw promise[TSR_DEFERRED_PROMISE].error\n }\n } else {\n throw {\n data: (\n router.options.errorSerializer?.serialize ?? defaultSerializeError\n )(promise[TSR_DEFERRED_PROMISE].error),\n __isServerError: true,\n }\n }\n }\n console.log('useAwaited', promise[TSR_DEFERRED_PROMISE])\n return [promise[TSR_DEFERRED_PROMISE].data, promise]\n}\n\nexport function Await<T>(\n props: AwaitOptions<T> & {\n fallback?: React.ReactNode\n children: (result: T) => React.ReactNode\n },\n) {\n const inner = <AwaitInner {...props} />\n if (props.fallback) {\n return <React.Suspense fallback={props.fallback}>{inner}</React.Suspense>\n }\n return inner\n}\n\nfunction AwaitInner<T>(\n props: AwaitOptions<T> & {\n fallback?: React.ReactNode\n children: (result: T) => React.ReactNode\n },\n): React.JSX.Element {\n const [data] = useAwaited(props)\n console.log('AwaitInner', data)\n\n return props.children(data) as React.JSX.Element\n}\n"],"names":[],"mappings":";;;;;;;AAYO,SAAS,WAAc;AAAA,EAC5B,SAAS;AACX,GAA6C;;AAC3C,QAAM,SAAS,UAAU;AACnB,QAAA,UAAU,MAAM,QAAQ;AAE9B,MAAI,QAAQ,oBAAoB,EAAE,WAAW,WAAW;AAChD,UAAA;AAAA,EAAA;AAGR,MAAI,QAAQ,oBAAoB,EAAE,WAAW,SAAS;AAChD,QAAA,OAAO,aAAa,aAAa;AACnC,UAAI,kBAAkB,QAAQ,oBAAoB,EAAE,KAAK,GAAG;AAExD,iBAAA,YAAO,QAAQ,oBAAf,mBAAgC,gBAAe,yBAC/C,QAAQ,oBAAoB,EAAE,MAAM,IAAW;AAAA,MAAA,OAC5C;AACL;AAAA,UACE;AAAA,UACA;AAAA,QACF;AACM,cAAA,QAAQ,oBAAoB,EAAE;AAAA,MAAA;AAAA,IACtC,OACK;AACC,YAAA;AAAA,QACJ,SACE,YAAO,QAAQ,oBAAf,mBAAgC,cAAa,uBAC7C,QAAQ,oBAAoB,EAAE,KAAK;AAAA,QACrC,iBAAiB;AAAA,MACnB;AAAA,IAAA;AAAA,EACF;AAEF,UAAQ,IAAI,cAAc,QAAQ,oBAAoB,CAAC;AACvD,SAAO,CAAC,QAAQ,oBAAoB,EAAE,MAAM,OAAO;AACrD;AAEO,SAAS,MACd,OAIA;AACA,QAAM,QAAQ,oBAAC,YAAY,EAAA,GAAG,MAAO,CAAA;AACrC,MAAI,MAAM,UAAU;AAClB,+BAAQ,MAAM,UAAN,EAAe,UAAU,MAAM,UAAW,UAAM,OAAA;AAAA,EAAA;AAEnD,SAAA;AACT;AAEA,SAAS,WACP,OAImB;AACnB,QAAM,CAAC,IAAI,IAAI,WAAW,KAAK;AACvB,UAAA,IAAI,cAAc,IAAI;AAEvB,SAAA,MAAM,SAAS,IAAI;AAC5B;"}
@@ -1,20 +1,19 @@
1
1
  import { defaultSerializeError } from './router.js';
2
+ export declare const TSR_DEFERRED_PROMISE: unique symbol;
2
3
  export type DeferredPromiseState<T> = {
3
- uid: string;
4
- resolve?: () => void;
5
- reject?: () => void;
6
- } & ({
7
- status: 'pending';
8
- data?: T;
9
- error?: unknown;
10
- } | {
11
- status: 'success';
12
- data: T;
13
- } | {
14
- status: 'error';
15
- data?: T;
16
- error: unknown;
17
- });
4
+ [TSR_DEFERRED_PROMISE]: {
5
+ status: 'pending';
6
+ data?: T;
7
+ error?: unknown;
8
+ } | {
9
+ status: 'success';
10
+ data: T;
11
+ } | {
12
+ status: 'error';
13
+ data?: T;
14
+ error: unknown;
15
+ };
16
+ };
18
17
  export type DeferredPromise<T> = Promise<T> & DeferredPromiseState<T>;
19
18
  export declare function defer<T>(_promise: Promise<T>, options?: {
20
19
  serializeError?: typeof defaultSerializeError;
package/dist/esm/defer.js CHANGED
@@ -1,24 +1,26 @@
1
1
  import { defaultSerializeError } from "./router.js";
2
+ const TSR_DEFERRED_PROMISE = Symbol.for("TSR_DEFERRED_PROMISE");
2
3
  function defer(_promise, options) {
3
4
  const promise = _promise;
4
- if (!promise.status) {
5
- Object.assign(promise, {
6
- status: "pending"
7
- });
8
- promise.then((data) => {
9
- promise.status = "success";
10
- promise.data = data;
11
- }).catch((error) => {
12
- promise.status = "error";
13
- promise.error = {
14
- data: ((options == null ? void 0 : options.serializeError) ?? defaultSerializeError)(error),
15
- __isServerError: true
16
- };
17
- });
5
+ if (promise[TSR_DEFERRED_PROMISE]) {
6
+ return promise;
18
7
  }
8
+ promise[TSR_DEFERRED_PROMISE] = { status: "pending" };
9
+ promise.then((data) => {
10
+ promise[TSR_DEFERRED_PROMISE].status = "success";
11
+ promise[TSR_DEFERRED_PROMISE].data = data;
12
+ console.log("defer then", promise[TSR_DEFERRED_PROMISE]);
13
+ }).catch((error) => {
14
+ promise[TSR_DEFERRED_PROMISE].status = "error";
15
+ promise[TSR_DEFERRED_PROMISE].error = {
16
+ data: ((options == null ? void 0 : options.serializeError) ?? defaultSerializeError)(error),
17
+ __isServerError: true
18
+ };
19
+ });
19
20
  return promise;
20
21
  }
21
22
  export {
23
+ TSR_DEFERRED_PROMISE,
22
24
  defer
23
25
  };
24
26
  //# sourceMappingURL=defer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"defer.js","sources":["../../src/defer.ts"],"sourcesContent":["import { defaultSerializeError } from './router'\n\nexport type DeferredPromiseState<T> = {\n uid: string\n resolve?: () => void\n reject?: () => void\n} & (\n | {\n status: 'pending'\n data?: T\n error?: unknown\n }\n | {\n status: 'success'\n data: T\n }\n | {\n status: 'error'\n data?: T\n error: unknown\n }\n)\n\nexport type DeferredPromise<T> = Promise<T> & DeferredPromiseState<T>\n\nexport function defer<T>(\n _promise: Promise<T>,\n options?: {\n serializeError?: typeof defaultSerializeError\n },\n) {\n const promise = _promise as DeferredPromise<T>\n\n if (!(promise as any).status) {\n Object.assign(promise, {\n status: 'pending',\n })\n\n promise\n .then((data) => {\n promise.status = 'success' as any\n promise.data = data\n })\n .catch((error) => {\n promise.status = 'error' as any\n ;(promise as any).error = {\n data: (options?.serializeError ?? defaultSerializeError)(error),\n __isServerError: true,\n }\n })\n }\n\n return promise\n}\n"],"names":[],"mappings":";AAyBgB,SAAA,MACd,UACA,SAGA;AACA,QAAM,UAAU;AAEZ,MAAA,CAAE,QAAgB,QAAQ;AAC5B,WAAO,OAAO,SAAS;AAAA,MACrB,QAAQ;AAAA,IAAA,CACT;AAGE,YAAA,KAAK,CAAC,SAAS;AACd,cAAQ,SAAS;AACjB,cAAQ,OAAO;AAAA,IAAA,CAChB,EACA,MAAM,CAAC,UAAU;AAChB,cAAQ,SAAS;AACf,cAAgB,QAAQ;AAAA,QACxB,QAAO,mCAAS,mBAAkB,uBAAuB,KAAK;AAAA,QAC9D,iBAAiB;AAAA,MACnB;AAAA,IAAA,CACD;AAAA,EAAA;AAGE,SAAA;AACT;"}
1
+ {"version":3,"file":"defer.js","sources":["../../src/defer.ts"],"sourcesContent":["import { defaultSerializeError } from './router'\n\nexport const TSR_DEFERRED_PROMISE = Symbol.for('TSR_DEFERRED_PROMISE')\n\nexport type DeferredPromiseState<T> = {\n [TSR_DEFERRED_PROMISE]:\n | {\n status: 'pending'\n data?: T\n error?: unknown\n }\n | {\n status: 'success'\n data: T\n }\n | {\n status: 'error'\n data?: T\n error: unknown\n }\n}\n\nexport type DeferredPromise<T> = Promise<T> & DeferredPromiseState<T>\n\nexport function defer<T>(\n _promise: Promise<T>,\n options?: {\n serializeError?: typeof defaultSerializeError\n },\n) {\n const promise = _promise as DeferredPromise<T>\n // this is already deferred promise\n if ((promise as any)[TSR_DEFERRED_PROMISE]) {\n return promise\n }\n promise[TSR_DEFERRED_PROMISE] = { status: 'pending' }\n\n promise\n .then((data) => {\n promise[TSR_DEFERRED_PROMISE].status = 'success'\n promise[TSR_DEFERRED_PROMISE].data = data\n console.log('defer then', promise[TSR_DEFERRED_PROMISE])\n })\n .catch((error) => {\n promise[TSR_DEFERRED_PROMISE].status = 'error'\n ;(promise[TSR_DEFERRED_PROMISE] as any).error = {\n data: (options?.serializeError ?? defaultSerializeError)(error),\n __isServerError: true,\n }\n })\n\n return promise\n}\n"],"names":[],"mappings":";AAEa,MAAA,uBAAuB,OAAO,IAAI,sBAAsB;AAsBrD,SAAA,MACd,UACA,SAGA;AACA,QAAM,UAAU;AAEX,MAAA,QAAgB,oBAAoB,GAAG;AACnC,WAAA;AAAA,EAAA;AAET,UAAQ,oBAAoB,IAAI,EAAE,QAAQ,UAAU;AAGjD,UAAA,KAAK,CAAC,SAAS;AACN,YAAA,oBAAoB,EAAE,SAAS;AAC/B,YAAA,oBAAoB,EAAE,OAAO;AACrC,YAAQ,IAAI,cAAc,QAAQ,oBAAoB,CAAC;AAAA,EAAA,CACxD,EACA,MAAM,CAAC,UAAU;AACR,YAAA,oBAAoB,EAAE,SAAS;AACrC,YAAQ,oBAAoB,EAAU,QAAQ;AAAA,MAC9C,QAAO,mCAAS,mBAAkB,uBAAuB,KAAK;AAAA,MAC9D,iBAAiB;AAAA,IACnB;AAAA,EAAA,CACD;AAEI,SAAA;AACT;"}
@@ -5,7 +5,7 @@ export { default as warning } from 'tiny-warning';
5
5
  export { useAwaited, Await } from './awaited.js';
6
6
  export type { AwaitOptions } from './awaited.js';
7
7
  export { ScriptOnce } from './ScriptOnce.js';
8
- export { defer } from './defer.js';
8
+ export { defer, TSR_DEFERRED_PROMISE } from './defer.js';
9
9
  export type { DeferredPromiseState, DeferredPromise } from './defer.js';
10
10
  export { CatchBoundary, ErrorComponent } from './CatchBoundary.js';
11
11
  export { FileRoute, createFileRoute, FileRouteLoader, LazyRoute, createLazyRoute, createLazyFileRoute, } from './fileRoute.js';
@@ -34,7 +34,7 @@ export { RouteApi, getRouteApi, Route, createRoute, RootRoute, rootRouteWithCont
34
34
  export type { AnyPathParams, ResolveParams, SearchSchemaInput, AnyContext, RouteContext, PreloadableObj, RoutePathOptions, StaticDataRouteOption, RoutePathOptionsIntersection, RouteOptions, FileBaseRouteOptions, BaseRouteOptions, UpdatableRouteOptions, UpdatableStaticRouteOption, MetaDescriptor, RouteLinkEntry, ParseParamsFn, RouteLoaderFn, LoaderFnContext, SearchFilter, ResolveId, InferFullSearchSchema, InferFullSearchSchemaInput, ResolveFullSearchSchema, ResolveFullSearchSchemaInput, AnyRoute, RouteConstraints, AnyRootRoute, ResolveFullPath, RouteMask, ErrorRouteProps, ErrorComponentProps, NotFoundRouteProps, ReactNode, SyncRouteComponent, AsyncRouteComponent, RouteComponent, ErrorRouteComponent, NotFoundRouteComponent, TrimPath, TrimPathLeft, TrimPathRight, RootRouteOptions, AnyRouteWithContext, ParseSplatParams, SplatParams, StringifyParamsFn, ParamsOptions, FullSearchSchemaOption, RouteContextFn, RouteContextOptions, BeforeLoadFn, BeforeLoadContextOptions, ContextOptions, InferAllParams, InferAllContext, LooseReturnType, LooseAsyncReturnType, ContextReturnType, ContextAsyncReturnType, RouteContextParameter, BeforeLoadContextParameter, ResolveAllContext, ResolveLoaderData, ResolveAllParamsFromParent, ResolveRouteContext, } from './route.js';
35
35
  export type { ParseRoute, RoutesById, RouteById, RouteIds, RoutesByPath, RouteByPath, RoutePaths, FullSearchSchema, AllParams, AllLoaderData, FullSearchSchemaInput, AllContext, } from './routeInfo.js';
36
36
  export { componentTypes, createRouter, Router, lazyFn, SearchParamError, PathParamError, getInitialRouterState, defaultSerializeError, } from './router.js';
37
- export type { Register, AnyRouter, RegisteredRouter, HydrationCtx, RouterContextOptions, TrailingSlashOption, RouterOptions, RouterErrorSerializer, RouterState, ListenerFn, BuildNextOptions, DehydratedRouterState, DehydratedRouteMatch, DehydratedRouter, RouterConstructorOptions, RouterEvents, RouterEvent, RouterListener, AnyRouterWithContext, ExtractedEntry, StreamState, } from './router.js';
37
+ export type { Register, AnyRouter, RegisteredRouter, HydrationCtx, RouterContextOptions, TrailingSlashOption, RouterOptions, RouterErrorSerializer, RouterState, ListenerFn, BuildNextOptions, DehydratedRouterState, DehydratedRouteMatch, DehydratedRouter, RouterConstructorOptions, RouterEvents, RouterEvent, RouterListener, AnyRouterWithContext, ExtractedEntry, ExtractedStream, ExtractedPromise, StreamState, } from './router.js';
38
38
  export { RouterProvider, RouterContextProvider } from './RouterProvider.js';
39
39
  export type { RouterProps, CommitLocationOptions, MatchLocation, NavigateFn, BuildLocationFn, InjectedHtmlEntry, } from './RouterProvider.js';
40
40
  export { useScrollRestoration, useElementScrollRestoration, ScrollRestoration, } from './scroll-restoration.js';
package/dist/esm/index.js CHANGED
@@ -3,7 +3,7 @@ import { default as default2 } from "tiny-invariant";
3
3
  import { default as default3 } from "tiny-warning";
4
4
  import { Await, useAwaited } from "./awaited.js";
5
5
  import { ScriptOnce } from "./ScriptOnce.js";
6
- import { defer } from "./defer.js";
6
+ import { TSR_DEFERRED_PROMISE, defer } from "./defer.js";
7
7
  import { CatchBoundary, ErrorComponent } from "./CatchBoundary.js";
8
8
  import { FileRoute, FileRouteLoader, LazyRoute, createFileRoute, createLazyFileRoute, createLazyRoute } from "./fileRoute.js";
9
9
  import { lazyRouteComponent } from "./lazyRouteComponent.js";
@@ -64,6 +64,7 @@ export {
64
64
  ScriptOnce,
65
65
  ScrollRestoration,
66
66
  SearchParamError,
67
+ TSR_DEFERRED_PROMISE,
67
68
  cleanPath,
68
69
  componentTypes,
69
70
  createBrowserHistory,
@@ -1,4 +1,5 @@
1
1
  import { Store, NoInfer } from '@tanstack/react-store';
2
+ import { DeferredPromiseState } from './defer.js';
2
3
  import { HistoryState, RouterHistory } from '@tanstack/history';
3
4
  import { Manifest } from './manifest.js';
4
5
  import { AnyContext, AnyRoute, AnyRouteWithContext, ErrorRouteComponent, NotFoundRouteComponent, RootRoute, RouteComponent, RouteMask } from './route.js';
@@ -44,15 +45,22 @@ export type HydrationCtx = {
44
45
  payload: Record<string, any>;
45
46
  };
46
47
  export type InferRouterContext<TRouteTree extends AnyRoute> = TRouteTree extends RootRoute<any, infer TRouterContext extends AnyContext, any, any, any, any, any, any> ? TRouterContext : AnyContext;
47
- export type ExtractedEntry = {
48
+ export interface ExtractedBaseEntry {
48
49
  dataType: '__beforeLoadContext' | 'loaderData';
49
- type: 'promise' | 'stream';
50
+ type: string;
50
51
  path: Array<string>;
51
- value: any;
52
52
  id: number;
53
- streamState?: StreamState;
54
53
  matchIndex: number;
55
- };
54
+ }
55
+ export interface ExtractedStream extends ExtractedBaseEntry {
56
+ type: 'stream';
57
+ streamState: StreamState;
58
+ }
59
+ export interface ExtractedPromise extends ExtractedBaseEntry {
60
+ type: 'promise';
61
+ promiseState: DeferredPromiseState<any>;
62
+ }
63
+ export type ExtractedEntry = ExtractedStream | ExtractedPromise;
56
64
  export type StreamState = {
57
65
  promises: Array<ControlledPromise<string | null>>;
58
66
  };