@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.35 → 3.5.0-ultramodern.37

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 (76) hide show
  1. package/dist/cjs/cli/tanstackTypes/shared.js +12 -19
  2. package/dist/cjs/cli/tanstackTypes/source.js +24 -19
  3. package/dist/cjs/runtime/blockingSubscribe.js +0 -7
  4. package/dist/cjs/runtime/clientHydration.js +2 -14
  5. package/dist/cjs/runtime/loaderBridge.js +3 -10
  6. package/dist/cjs/runtime/pluginShared.js +0 -3
  7. package/dist/cjs/runtime/register.js +1 -47
  8. package/dist/cjs/runtime/rsc/ReplayableStream.js +0 -4
  9. package/dist/cjs/runtime/rsc/payloadFetch.js +3 -16
  10. package/dist/cjs/runtime/rsc/payloadRoutes.js +2 -14
  11. package/dist/cjs/runtime/rsc/shared.js +2 -5
  12. package/dist/cjs/runtime/shared/isAbsoluteUrl.js +47 -0
  13. package/dist/esm/cli/index.mjs +4 -4
  14. package/dist/esm/cli/tanstackTypes/shared.mjs +12 -19
  15. package/dist/esm/cli/tanstackTypes/source.mjs +23 -18
  16. package/dist/esm/runtime/blockingSubscribe.mjs +1 -1
  17. package/dist/esm/runtime/clientHydration.mjs +1 -1
  18. package/dist/esm/runtime/loaderBridge.mjs +1 -8
  19. package/dist/esm/runtime/pluginShared.mjs +1 -1
  20. package/dist/esm/runtime/register.mjs +0 -14
  21. package/dist/esm/runtime/rsc/ReplayableStream.mjs +1 -1
  22. package/dist/esm/runtime/rsc/payloadFetch.mjs +2 -9
  23. package/dist/esm/runtime/rsc/payloadRoutes.mjs +1 -1
  24. package/dist/esm/runtime/rsc/shared.mjs +1 -1
  25. package/dist/esm/runtime/shared/isAbsoluteUrl.mjs +9 -0
  26. package/dist/esm-node/cli/index.mjs +4 -4
  27. package/dist/esm-node/cli/tanstackTypes/shared.mjs +12 -19
  28. package/dist/esm-node/cli/tanstackTypes/source.mjs +23 -18
  29. package/dist/esm-node/runtime/blockingSubscribe.mjs +1 -1
  30. package/dist/esm-node/runtime/clientHydration.mjs +1 -1
  31. package/dist/esm-node/runtime/loaderBridge.mjs +1 -8
  32. package/dist/esm-node/runtime/pluginShared.mjs +1 -1
  33. package/dist/esm-node/runtime/register.mjs +0 -14
  34. package/dist/esm-node/runtime/rsc/ReplayableStream.mjs +1 -1
  35. package/dist/esm-node/runtime/rsc/payloadFetch.mjs +2 -9
  36. package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +1 -1
  37. package/dist/esm-node/runtime/rsc/shared.mjs +1 -1
  38. package/dist/esm-node/runtime/shared/isAbsoluteUrl.mjs +10 -0
  39. package/dist/types/cli/tanstackTypes/shared.d.ts +1 -1
  40. package/dist/types/cli/tanstackTypes/source.d.ts +3 -1
  41. package/dist/types/runtime/blockingSubscribe.d.ts +0 -2
  42. package/dist/types/runtime/clientHydration.d.ts +0 -9
  43. package/dist/types/runtime/formData.d.ts +2 -1
  44. package/dist/types/runtime/loaderBridge.d.ts +2 -1
  45. package/dist/types/runtime/pluginShared.d.ts +2 -3
  46. package/dist/types/runtime/register.d.ts +1 -9
  47. package/dist/types/runtime/routeTree/types.d.ts +2 -1
  48. package/dist/types/runtime/rsc/ReplayableStream.d.ts +3 -2
  49. package/dist/types/runtime/rsc/SlotContext.d.ts +2 -1
  50. package/dist/types/runtime/rsc/payloadFetch.d.ts +2 -4
  51. package/dist/types/runtime/rsc/payloadRoutes.d.ts +3 -6
  52. package/dist/types/runtime/rsc/shared.d.ts +0 -1
  53. package/dist/types/runtime/shared/isAbsoluteUrl.d.ts +1 -0
  54. package/dist/types/runtime/ssrTypes.d.ts +3 -2
  55. package/dist/types/runtime/types.d.ts +2 -3
  56. package/package.json +15 -16
  57. package/src/cli/tanstackTypes/canonicalRoutes.ts +1 -1
  58. package/src/cli/tanstackTypes/shared.ts +24 -30
  59. package/src/cli/tanstackTypes/source.ts +31 -21
  60. package/src/runtime/blockingSubscribe.ts +2 -2
  61. package/src/runtime/clientHydration.ts +5 -10
  62. package/src/runtime/formData.ts +1 -1
  63. package/src/runtime/loaderBridge.ts +3 -9
  64. package/src/runtime/pluginShared.ts +3 -3
  65. package/src/runtime/register.ts +5 -37
  66. package/src/runtime/routeTree/types.ts +1 -1
  67. package/src/runtime/rsc/ReplayableStream.ts +2 -2
  68. package/src/runtime/rsc/SlotContext.tsx +1 -1
  69. package/src/runtime/rsc/payloadFetch.ts +5 -11
  70. package/src/runtime/rsc/payloadRoutes.ts +6 -6
  71. package/src/runtime/rsc/shared.ts +1 -1
  72. package/src/runtime/shared/isAbsoluteUrl.ts +8 -0
  73. package/src/runtime/ssrTypes.ts +2 -2
  74. package/src/runtime/submitAction.ts +17 -10
  75. package/src/runtime/types.ts +1 -8
  76. package/tests/router/register.test.ts +1 -39
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Registers the TanStack router provider with the @modern-js/runtime router
2
+ * Registers TanStack router provider with the @modern-js/runtime router
3
3
  * provider registry. Importing '@modern-js/plugin-tanstack/runtime' is enough
4
4
  * to make `runtime.router.framework: 'tanstack'` resolvable by the built-in
5
5
  * router runtime plugin.
@@ -12,47 +12,15 @@ import {
12
12
  type RouterProviderPlugin,
13
13
  registerRouterProvider,
14
14
  } from '@modern-js/runtime/context';
15
- import { Form, RouteActionResponseError, useFetcher } from './dataMutation';
16
- import { Outlet } from './outlet';
17
15
  import { tanstackRouterPlugin } from './plugin';
18
- import { Link, NavLink } from './prefetchLink';
19
16
 
20
- // The TanStack runtime plugin types its API against its own hook registry,
17
+ // TanStack runtime plugin types its API against its own hook registry,
21
18
  // while the provider contract is typed against the built-in router hook
22
- // registry of @modern-js/runtime. The two are runtime-compatible (the
19
+ // registry from @modern-js/runtime. The two are runtime-compatible (the
23
20
  // built-in router plugin registers the hooks and forwards its API to the
24
- // resolved provider), but nominally distinct — hence the explicit adapter
25
- // cast at this single boundary.
21
+ // resolved provider), but nominally distinct, so keep an explicit adapter
22
+ // cast as the single boundary.
26
23
  const tanstackRouterProviderFactory: RouterProviderFactory = userConfig =>
27
24
  tanstackRouterPlugin(userConfig) as unknown as RouterProviderPlugin;
28
25
 
29
26
  registerRouterProvider('tanstack', tanstackRouterProviderFactory);
30
-
31
- /**
32
- * Compatibility bindings for the deprecated `@modern-js/runtime/tanstack-router`
33
- * alias. `@modern-js/runtime` cannot depend on this package (the dependency
34
- * direction is plugin-tanstack -> runtime), so the alias resolves the
35
- * Modern.js specific bindings through this `Symbol.for` slot at use time.
36
- *
37
- * `??=` keeps the first copy: when Module Federation evaluates a second
38
- * bundled copy of this module, both copies are functionally identical and the
39
- * established registration wins (mirroring the router-provider registry).
40
- */
41
- const COMPAT_BINDINGS_SLOT: unique symbol = Symbol.for(
42
- '@modern-js/plugin-tanstack:runtime-compat-bindings',
43
- );
44
-
45
- export const tanstackRouterCompatBindings = {
46
- Form,
47
- Link,
48
- NavLink,
49
- Outlet,
50
- RouteActionResponseError,
51
- useFetcher,
52
- };
53
-
54
- (
55
- globalThis as {
56
- [COMPAT_BINDINGS_SLOT]?: typeof tanstackRouterCompatBindings;
57
- }
58
- )[COMPAT_BINDINGS_SLOT] ??= tanstackRouterCompatBindings;
@@ -8,7 +8,7 @@ import type {
8
8
 
9
9
  export type RouteParams = Record<string, string>;
10
10
 
11
- export type ModernLoader = (args: {
11
+ type ModernLoader = (args: {
12
12
  request: Request;
13
13
  params: RouteParams;
14
14
  context?: unknown;
@@ -1,5 +1,5 @@
1
1
  // @effect-diagnostics asyncFunction:off newPromise:off strictBooleanExpressions:off
2
- export interface ReplayableStreamOptions {
2
+ interface ReplayableStreamOptions {
3
3
  signal?: AbortSignal;
4
4
  }
5
5
 
@@ -8,7 +8,7 @@ type Waiter = {
8
8
  resolve: () => void;
9
9
  };
10
10
 
11
- export const REPLAYABLE_STREAM_MARKER = Symbol.for(
11
+ const REPLAYABLE_STREAM_MARKER = Symbol.for(
12
12
  'modern.tanstack.rsc.ReplayableStream',
13
13
  );
14
14
 
@@ -3,7 +3,7 @@
3
3
  import type React from 'react';
4
4
  import { createContext, use } from 'react';
5
5
 
6
- export type SlotImplementations = Record<string, unknown>;
6
+ type SlotImplementations = Record<string, unknown>;
7
7
 
8
8
  const SlotContext = createContext<{
9
9
  implementations: SlotImplementations;
@@ -1,14 +1,17 @@
1
1
  // @effect-diagnostics asyncFunction:off globalFetch:off processEnv:off strictBooleanExpressions:off
2
2
  import type { ServerPayload } from '@modern-js/runtime/context';
3
3
  import { notFound, redirect } from '@tanstack/react-router';
4
+ import { isAbsoluteUrl } from '../shared/isAbsoluteUrl';
4
5
  import { reviveTanstackRscFlightValues } from './flightSerialization';
5
6
 
7
+ export { isAbsoluteUrl };
8
+
6
9
  type PayloadDecoder = (stream: ReadableStream<Uint8Array>) => Promise<unknown>;
7
10
 
8
11
  export const payloadFetchCache = new Map<string, Promise<ServerPayload>>();
9
12
  let payloadDecoder: PayloadDecoder | undefined;
10
13
 
11
- export async function decodePayload(stream: ReadableStream<Uint8Array>) {
14
+ async function decodePayload(stream: ReadableStream<Uint8Array>) {
12
15
  if (payloadDecoder) {
13
16
  return reviveTanstackRscFlightValues(await payloadDecoder(stream));
14
17
  }
@@ -19,7 +22,7 @@ export async function decodePayload(stream: ReadableStream<Uint8Array>) {
19
22
  );
20
23
  }
21
24
 
22
- export function isServerPayload(value: unknown): value is ServerPayload {
25
+ function isServerPayload(value: unknown): value is ServerPayload {
23
26
  return (
24
27
  Boolean(value) &&
25
28
  typeof value === 'object' &&
@@ -38,15 +41,6 @@ export function createPayloadFetchKey(request: Request) {
38
41
  ]);
39
42
  }
40
43
 
41
- export function isAbsoluteUrl(value: string) {
42
- try {
43
- void new URL(value);
44
- return true;
45
- } catch {
46
- return false;
47
- }
48
- }
49
-
50
44
  export async function fetchTanstackRscPayload(request: Request) {
51
45
  const headers = new Headers(request.headers);
52
46
  headers.set('x-rsc-tree', 'true');
@@ -1,7 +1,7 @@
1
1
  // @effect-diagnostics asyncFunction:off globalFetch:off processEnv:off strictBooleanExpressions:off
2
2
  import type { PayloadRoute, ServerPayload } from '@modern-js/runtime/context';
3
3
 
4
- export type RouterStaticData = {
4
+ type RouterStaticData = {
5
5
  modernRouteAction?: unknown;
6
6
  modernRouteHandle?: unknown;
7
7
  modernRouteHasAction?: unknown;
@@ -11,7 +11,7 @@ export type RouterStaticData = {
11
11
  modernRouteIsClientComponent?: unknown;
12
12
  };
13
13
 
14
- export type RouterRouteLike = {
14
+ type RouterRouteLike = {
15
15
  id?: unknown;
16
16
  options?: {
17
17
  index?: unknown;
@@ -40,7 +40,7 @@ export type TanstackPayloadRouterLike = {
40
40
  };
41
41
  };
42
42
 
43
- export function toPlainRecord(value: unknown): Record<string, unknown> {
43
+ function toPlainRecord(value: unknown): Record<string, unknown> {
44
44
  if (!value || typeof value !== 'object') {
45
45
  return {};
46
46
  }
@@ -73,16 +73,16 @@ export function getRouteId(match: RouterMatchLike) {
73
73
  return typeof routeId === 'string' ? routeId : undefined;
74
74
  }
75
75
 
76
- export function getRouteStaticData(match: RouterMatchLike) {
76
+ function getRouteStaticData(match: RouterMatchLike) {
77
77
  return match.route?.options?.staticData || {};
78
78
  }
79
79
 
80
- export function getRouteParentId(match: RouterMatchLike) {
80
+ function getRouteParentId(match: RouterMatchLike) {
81
81
  const parentId = match.route?.parentRoute?.id;
82
82
  return typeof parentId === 'string' ? parentId : undefined;
83
83
  }
84
84
 
85
- export function toRoutePath(match: RouterMatchLike) {
85
+ function toRoutePath(match: RouterMatchLike) {
86
86
  const path = match.route?.options?.path;
87
87
  return typeof path === 'string' ? path : undefined;
88
88
  }
@@ -35,7 +35,7 @@ export function EmptyFallback() {
35
35
  return null;
36
36
  }
37
37
 
38
- export function selectTreePath(tree: unknown, path: string[]) {
38
+ function selectTreePath(tree: unknown, path: string[]) {
39
39
  let current = tree;
40
40
  for (const key of path) {
41
41
  if (current === null || typeof current !== 'object') {
@@ -0,0 +1,8 @@
1
+ export function isAbsoluteUrl(value: string): boolean {
2
+ try {
3
+ void new URL(value);
4
+ return true;
5
+ } catch {
6
+ return false;
7
+ }
8
+ }
@@ -23,14 +23,14 @@ export type RouterMatchWithError = {
23
23
  routeId?: unknown;
24
24
  };
25
25
 
26
- export type RouterRouteOptions = {
26
+ type RouterRouteOptions = {
27
27
  component?: unknown;
28
28
  errorComponent?: unknown;
29
29
  notFoundComponent?: unknown;
30
30
  pendingComponent?: unknown;
31
31
  };
32
32
 
33
- export type RouterRouteWithOptions = {
33
+ type RouterRouteWithOptions = {
34
34
  options?: RouterRouteOptions;
35
35
  };
36
36
 
@@ -31,14 +31,21 @@ type RouteLoader = (args: {
31
31
  context?: unknown;
32
32
  }) => Promise<unknown> | unknown;
33
33
 
34
+ type RouterBuildLocationOptions = Parameters<AnyRouter['buildLocation']>[0];
35
+ type RouterBuiltLocation = ReturnType<AnyRouter['buildLocation']> & {
36
+ pathname: string;
37
+ };
38
+ type RouterParsedLocation = Parameters<AnyRouter['getParsedLocationHref']>[0];
39
+ type RouterNavigateOptions = Parameters<AnyRouter['navigate']>[0];
40
+
34
41
  function resolveRouteHandlers(router: AnyRouter, actionTo: string) {
35
42
  const builtLocation = router.buildLocation({
36
- to: actionTo as any,
37
- } as any);
38
- const href = router.getParsedLocationHref(builtLocation as any);
39
- const matchedRoutes = router.getMatchedRoutes(
40
- (builtLocation as any).pathname,
43
+ to: actionTo,
44
+ } as RouterBuildLocationOptions) as RouterBuiltLocation;
45
+ const href = router.getParsedLocationHref(
46
+ builtLocation as RouterParsedLocation,
41
47
  );
48
+ const matchedRoutes = router.getMatchedRoutes(builtLocation.pathname);
42
49
  const routeStaticData = matchedRoutes.foundRoute?.options?.staticData as
43
50
  | Record<string, unknown>
44
51
  | undefined;
@@ -118,8 +125,8 @@ export async function submitRouteAction({
118
125
  result.headers.get('Location');
119
126
  if (redirectTo || isRedirectResponse(result)) {
120
127
  await router.navigate({
121
- to: (redirectTo || '/') as any,
122
- } as any);
128
+ to: redirectTo || '/',
129
+ } as RouterNavigateOptions);
123
130
  return parseResponseData(result);
124
131
  }
125
132
  return parseResponseResultOrThrow(result);
@@ -130,7 +137,7 @@ export async function submitRouteAction({
130
137
 
131
138
  await router.navigate({
132
139
  href: `${requestUrl.pathname}${requestUrl.search}${requestUrl.hash}`,
133
- } as any);
140
+ } as RouterNavigateOptions);
134
141
  return;
135
142
  }
136
143
 
@@ -175,8 +182,8 @@ export async function submitRouteAction({
175
182
  result.headers.get('Location');
176
183
  if (redirectTo || isRedirectResponse(result)) {
177
184
  await router.navigate({
178
- to: (redirectTo || '/') as any,
179
- } as any);
185
+ to: redirectTo || '/',
186
+ } as RouterNavigateOptions);
180
187
  return parseResponseData(result);
181
188
  }
182
189
 
@@ -1,22 +1,15 @@
1
- import type { ModernRoute, RouterFramework } from '@modern-js/runtime/context';
1
+ import type { ModernRoute } from '@modern-js/runtime/context';
2
2
  import type { RouteObject } from '@modern-js/runtime-utils/router';
3
3
  import type React from 'react';
4
4
 
5
5
  export type {
6
- BuiltInRouterFramework,
7
- InternalRouterRuntimeState,
8
6
  InternalRouterServerSnapshot,
9
- LoaderFunction,
10
- LoaderFunctionArgs,
11
7
  ModernRoute,
12
8
  RouterFramework,
13
- RouterRouteMatchSnapshot,
14
- RouterServerPrepareResult,
15
9
  } from '@modern-js/runtime/context';
16
10
 
17
11
  /** TanStack-specific router config. */
18
12
  export type RouterConfig = {
19
- framework?: RouterFramework;
20
13
  routesConfig: {
21
14
  globalApp?: React.ComponentType<any>;
22
15
  routes?: ModernRoute[];
@@ -1,46 +1,8 @@
1
1
  import { resolveRouterProvider } from '@modern-js/runtime/context';
2
- import {
3
- Form,
4
- Link,
5
- NavLink,
6
- Outlet,
7
- RouteActionResponseError,
8
- useFetcher,
9
- } from '../../src/runtime';
10
- import { tanstackRouterCompatBindings } from '../../src/runtime/register';
11
-
12
- const COMPAT_BINDINGS_SLOT = Symbol.for(
13
- '@modern-js/plugin-tanstack:runtime-compat-bindings',
14
- );
2
+ import '../../src/runtime/register';
15
3
 
16
4
  describe("'@modern-js/plugin-tanstack/runtime' import side effects", () => {
17
5
  it('registers the tanstack router provider', () => {
18
6
  expect(typeof resolveRouterProvider('tanstack')).toBe('function');
19
7
  });
20
-
21
- it("publishes the compat bindings consumed by '@modern-js/runtime/tanstack-router'", () => {
22
- const bindings = (globalThis as Record<symbol, unknown>)[
23
- COMPAT_BINDINGS_SLOT
24
- ] as typeof tanstackRouterCompatBindings;
25
-
26
- expect(bindings).toBeDefined();
27
- expect(bindings).toBe(tanstackRouterCompatBindings);
28
- expect(bindings.Form).toBe(Form);
29
- expect(bindings.Link).toBe(Link);
30
- expect(bindings.NavLink).toBe(NavLink);
31
- expect(bindings.Outlet).toBe(Outlet);
32
- expect(bindings.RouteActionResponseError).toBe(RouteActionResponseError);
33
- expect(bindings.useFetcher).toBe(useFetcher);
34
- });
35
-
36
- it('keeps the first published bindings when a duplicate module copy evaluates', () => {
37
- // Simulates a Module Federation remote evaluating its own copy of
38
- // register.ts: `??=` must keep the established bindings.
39
- const host = globalThis as Record<symbol, unknown>;
40
- const established = host[COMPAT_BINDINGS_SLOT];
41
- expect(established).toBeDefined();
42
-
43
- host[COMPAT_BINDINGS_SLOT] ??= { duplicate: true };
44
- expect(host[COMPAT_BINDINGS_SLOT]).toBe(established);
45
- });
46
8
  });