@bleedingdev/modern-js-plugin-tanstack 3.5.0-ultramodern.9 → 3.5.0-ultramodern.91
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.
- package/dist/cjs/cli/artifacts.js +157 -0
- package/dist/cjs/cli/index.js +8 -79
- package/dist/cjs/cli/tanstackTypes/canonicalRoutes.js +113 -0
- package/dist/cjs/cli/tanstackTypes/shared.js +123 -0
- package/dist/cjs/cli/tanstackTypes/source.js +255 -0
- package/dist/cjs/cli/tanstackTypes.js +4 -350
- package/dist/cjs/runtime/blockingSubscribe.js +57 -0
- package/dist/cjs/runtime/{pluginCore.js → clientBasepath.js} +12 -19
- package/dist/cjs/runtime/clientHydration.js +118 -0
- package/dist/cjs/runtime/dataMutation.js +11 -176
- package/dist/cjs/runtime/formData.js +116 -0
- package/dist/cjs/runtime/loaderBridge.js +7 -11
- package/dist/cjs/runtime/plugin.js +21 -125
- package/dist/cjs/runtime/plugin.node.js +45 -125
- package/dist/cjs/runtime/pluginShared.js +87 -0
- package/dist/cjs/runtime/prefetchLink.js +15 -2
- package/dist/cjs/runtime/register.js +3 -16
- package/dist/cjs/runtime/routeTree/components.js +102 -0
- package/dist/cjs/runtime/routeTree/construction.js +152 -0
- package/dist/cjs/runtime/routeTree/index.js +47 -0
- package/dist/cjs/runtime/routeTree/loaders.js +158 -0
- package/dist/cjs/runtime/routeTree/paths.js +57 -0
- package/dist/cjs/runtime/routeTree/staticData.js +63 -0
- package/dist/cjs/runtime/routeTree/tanstackRoutes.js +57 -0
- package/dist/cjs/runtime/routeTree/types.js +18 -0
- package/dist/cjs/runtime/routeTree.js +7 -320
- package/dist/cjs/runtime/router.js +15 -2
- package/dist/cjs/runtime/rsc/CompositeComponent.js +18 -13
- package/dist/cjs/runtime/rsc/ReplayableStream.js +0 -4
- package/dist/cjs/runtime/rsc/RscNodeRenderer.js +5 -16
- package/dist/cjs/runtime/rsc/client.js +8 -25
- package/dist/cjs/runtime/rsc/flightSerialization.js +132 -0
- package/dist/cjs/runtime/rsc/payloadErrors.js +99 -0
- package/dist/cjs/runtime/rsc/payloadFetch.js +105 -0
- package/dist/cjs/runtime/rsc/payloadRouter.js +21 -142
- package/dist/cjs/runtime/rsc/payloadRoutes.js +94 -0
- package/dist/cjs/runtime/rsc/payloadStorage.js +58 -0
- package/dist/cjs/runtime/rsc/server.js +14 -18
- package/dist/cjs/runtime/rsc/shared.js +68 -0
- package/dist/cjs/runtime/rsc/slotUsageSanitizer.js +1 -0
- package/dist/cjs/runtime/rsc/treeGetter.js +72 -0
- package/dist/cjs/runtime/shared/isAbsoluteUrl.js +47 -0
- package/dist/cjs/runtime/ssrManagedTags.js +103 -0
- package/dist/cjs/runtime/ssrPreload.js +89 -0
- package/dist/cjs/runtime/ssrTypes.js +18 -0
- package/dist/cjs/runtime/state.js +1 -1
- package/dist/cjs/runtime/submitAction.js +161 -0
- package/dist/cjs/runtime/utils.js +49 -86
- package/dist/esm/cli/artifacts.mjs +103 -0
- package/dist/esm/cli/index.mjs +8 -82
- package/dist/esm/cli/tanstackTypes/canonicalRoutes.mjs +75 -0
- package/dist/esm/cli/tanstackTypes/shared.mjs +61 -0
- package/dist/esm/cli/tanstackTypes/source.mjs +207 -0
- package/dist/esm/cli/tanstackTypes.mjs +2 -339
- package/dist/esm/runtime/blockingSubscribe.mjs +19 -0
- package/dist/esm/runtime/clientBasepath.mjs +10 -0
- package/dist/esm/runtime/clientHydration.mjs +71 -0
- package/dist/esm/runtime/dataMutation.mjs +2 -167
- package/dist/esm/runtime/formData.mjs +63 -0
- package/dist/esm/runtime/loaderBridge.mjs +5 -9
- package/dist/esm/runtime/plugin.mjs +14 -118
- package/dist/esm/runtime/plugin.node.mjs +41 -121
- package/dist/esm/runtime/pluginShared.mjs +40 -0
- package/dist/esm/runtime/prefetchLink.mjs +18 -5
- package/dist/esm/runtime/register.mjs +1 -14
- package/dist/esm/runtime/routeTree/components.mjs +55 -0
- package/dist/esm/runtime/routeTree/construction.mjs +111 -0
- package/dist/esm/runtime/routeTree/index.mjs +2 -0
- package/dist/esm/runtime/routeTree/loaders.mjs +117 -0
- package/dist/esm/runtime/routeTree/paths.mjs +16 -0
- package/dist/esm/runtime/routeTree/staticData.mjs +22 -0
- package/dist/esm/runtime/routeTree/tanstackRoutes.mjs +13 -0
- package/dist/esm/runtime/routeTree/types.mjs +0 -0
- package/dist/esm/runtime/routeTree.mjs +1 -318
- package/dist/esm/runtime/router.mjs +16 -2
- package/dist/esm/runtime/rsc/CompositeComponent.mjs +18 -13
- package/dist/esm/runtime/rsc/ReplayableStream.mjs +1 -1
- package/dist/esm/runtime/rsc/RscNodeRenderer.mjs +4 -15
- package/dist/esm/runtime/rsc/client.mjs +6 -26
- package/dist/esm/runtime/rsc/flightSerialization.mjs +88 -0
- package/dist/esm/runtime/rsc/payloadErrors.mjs +49 -0
- package/dist/esm/runtime/rsc/payloadFetch.mjs +55 -0
- package/dist/esm/runtime/rsc/payloadRouter.mjs +12 -133
- package/dist/esm/runtime/rsc/payloadRoutes.mjs +50 -0
- package/dist/esm/runtime/rsc/payloadStorage.mjs +14 -0
- package/dist/esm/runtime/rsc/server.mjs +17 -21
- package/dist/esm/runtime/rsc/shared.mjs +21 -0
- package/dist/esm/runtime/rsc/slotUsageSanitizer.mjs +1 -0
- package/dist/esm/runtime/rsc/treeGetter.mjs +34 -0
- package/dist/esm/runtime/shared/isAbsoluteUrl.mjs +9 -0
- package/dist/esm/runtime/ssrManagedTags.mjs +53 -0
- package/dist/esm/runtime/ssrPreload.mjs +51 -0
- package/dist/esm/runtime/ssrTypes.mjs +0 -0
- package/dist/esm/runtime/state.mjs +1 -1
- package/dist/esm/runtime/submitAction.mjs +120 -0
- package/dist/esm/runtime/utils.mjs +47 -75
- package/dist/esm-node/cli/artifacts.mjs +104 -0
- package/dist/esm-node/cli/index.mjs +8 -82
- package/dist/esm-node/cli/tanstackTypes/canonicalRoutes.mjs +76 -0
- package/dist/esm-node/cli/tanstackTypes/shared.mjs +62 -0
- package/dist/esm-node/cli/tanstackTypes/source.mjs +208 -0
- package/dist/esm-node/cli/tanstackTypes.mjs +2 -339
- package/dist/esm-node/runtime/blockingSubscribe.mjs +20 -0
- package/dist/esm-node/runtime/clientBasepath.mjs +11 -0
- package/dist/esm-node/runtime/clientHydration.mjs +72 -0
- package/dist/esm-node/runtime/dataMutation.mjs +2 -167
- package/dist/esm-node/runtime/formData.mjs +64 -0
- package/dist/esm-node/runtime/loaderBridge.mjs +5 -9
- package/dist/esm-node/runtime/plugin.mjs +14 -118
- package/dist/esm-node/runtime/plugin.node.mjs +41 -121
- package/dist/esm-node/runtime/pluginShared.mjs +41 -0
- package/dist/esm-node/runtime/prefetchLink.mjs +18 -5
- package/dist/esm-node/runtime/register.mjs +1 -14
- package/dist/esm-node/runtime/routeTree/components.mjs +56 -0
- package/dist/esm-node/runtime/routeTree/construction.mjs +112 -0
- package/dist/esm-node/runtime/routeTree/index.mjs +3 -0
- package/dist/esm-node/runtime/routeTree/loaders.mjs +118 -0
- package/dist/esm-node/runtime/routeTree/paths.mjs +17 -0
- package/dist/esm-node/runtime/routeTree/staticData.mjs +23 -0
- package/dist/esm-node/runtime/routeTree/tanstackRoutes.mjs +14 -0
- package/dist/esm-node/runtime/routeTree/types.mjs +1 -0
- package/dist/esm-node/runtime/routeTree.mjs +1 -318
- package/dist/esm-node/runtime/router.mjs +16 -2
- package/dist/esm-node/runtime/rsc/CompositeComponent.mjs +18 -13
- package/dist/esm-node/runtime/rsc/ReplayableStream.mjs +1 -1
- package/dist/esm-node/runtime/rsc/RscNodeRenderer.mjs +4 -15
- package/dist/esm-node/runtime/rsc/client.mjs +6 -26
- package/dist/esm-node/runtime/rsc/flightSerialization.mjs +89 -0
- package/dist/esm-node/runtime/rsc/payloadErrors.mjs +50 -0
- package/dist/esm-node/runtime/rsc/payloadFetch.mjs +56 -0
- package/dist/esm-node/runtime/rsc/payloadRouter.mjs +12 -133
- package/dist/esm-node/runtime/rsc/payloadRoutes.mjs +51 -0
- package/dist/esm-node/runtime/rsc/payloadStorage.mjs +15 -0
- package/dist/esm-node/runtime/rsc/server.mjs +17 -21
- package/dist/esm-node/runtime/rsc/shared.mjs +22 -0
- package/dist/esm-node/runtime/rsc/slotUsageSanitizer.mjs +1 -0
- package/dist/esm-node/runtime/rsc/treeGetter.mjs +35 -0
- package/dist/esm-node/runtime/shared/isAbsoluteUrl.mjs +10 -0
- package/dist/esm-node/runtime/ssrManagedTags.mjs +54 -0
- package/dist/esm-node/runtime/ssrPreload.mjs +52 -0
- package/dist/esm-node/runtime/ssrTypes.mjs +1 -0
- package/dist/esm-node/runtime/state.mjs +1 -1
- package/dist/esm-node/runtime/submitAction.mjs +121 -0
- package/dist/esm-node/runtime/utils.mjs +47 -75
- package/dist/types/cli/artifacts.d.ts +33 -0
- package/dist/types/cli/index.d.ts +2 -22
- package/dist/types/cli/tanstackTypes/canonicalRoutes.d.ts +22 -0
- package/dist/types/cli/tanstackTypes/shared.d.ts +20 -0
- package/dist/types/cli/tanstackTypes/source.d.ts +12 -0
- package/dist/types/cli/tanstackTypes.d.ts +3 -31
- package/dist/types/runtime/blockingSubscribe.d.ts +1 -0
- package/dist/types/runtime/clientBasepath.d.ts +1 -0
- package/dist/types/runtime/clientHydration.d.ts +10 -0
- package/dist/types/runtime/dataMutation.d.ts +3 -12
- package/dist/types/runtime/formData.d.ts +24 -0
- package/dist/types/runtime/loaderBridge.d.ts +2 -1
- package/dist/types/runtime/plugin.d.ts +1 -1
- package/dist/types/runtime/plugin.node.d.ts +1 -1
- package/dist/types/runtime/pluginShared.d.ts +38 -0
- package/dist/types/runtime/register.d.ts +10 -9
- package/dist/types/runtime/routeTree/components.d.ts +7 -0
- package/dist/types/runtime/routeTree/construction.d.ts +5 -0
- package/dist/types/runtime/routeTree/index.d.ts +2 -0
- package/dist/types/runtime/routeTree/loaders.d.ts +4 -0
- package/dist/types/runtime/routeTree/paths.d.ts +3 -0
- package/dist/types/runtime/routeTree/staticData.d.ts +19 -0
- package/dist/types/runtime/routeTree/tanstackRoutes.d.ts +4 -0
- package/dist/types/runtime/routeTree/types.d.ts +76 -0
- package/dist/types/runtime/routeTree.d.ts +1 -9
- package/dist/types/runtime/router.d.ts +6 -7
- package/dist/types/runtime/rsc/CompositeComponent.d.ts +1 -2
- package/dist/types/runtime/rsc/ReplayableStream.d.ts +3 -2
- package/dist/types/runtime/rsc/RscNodeRenderer.d.ts +2 -3
- package/dist/types/runtime/rsc/SlotContext.d.ts +2 -1
- package/dist/types/runtime/rsc/client.d.ts +2 -0
- package/dist/types/runtime/rsc/flightSerialization.d.ts +3 -0
- package/dist/types/runtime/rsc/payloadErrors.d.ts +6 -0
- package/dist/types/runtime/rsc/payloadFetch.d.ts +8 -0
- package/dist/types/runtime/rsc/payloadRouter.d.ts +2 -10
- package/dist/types/runtime/rsc/payloadRoutes.d.ts +40 -0
- package/dist/types/runtime/rsc/payloadStorage.d.ts +5 -0
- package/dist/types/runtime/rsc/shared.d.ts +18 -0
- package/dist/types/runtime/rsc/treeGetter.d.ts +1 -0
- package/dist/types/runtime/shared/isAbsoluteUrl.d.ts +1 -0
- package/dist/types/runtime/ssrManagedTags.d.ts +7 -0
- package/dist/types/runtime/ssrPreload.d.ts +2 -0
- package/dist/types/runtime/ssrTypes.d.ts +44 -0
- package/dist/types/runtime/state.d.ts +1 -1
- package/dist/types/runtime/submitAction.d.ts +14 -0
- package/dist/types/runtime/types.d.ts +4 -10
- package/dist/types/runtime/utils.d.ts +4 -24
- package/package.json +37 -17
- package/rstest.config.mts +23 -0
- package/src/cli/artifacts.ts +255 -0
- package/src/cli/index.ts +7 -185
- package/src/cli/tanstackTypes/canonicalRoutes.ts +157 -0
- package/src/cli/tanstackTypes/shared.ts +113 -0
- package/src/cli/tanstackTypes/source.ts +414 -0
- package/src/cli/tanstackTypes.ts +4 -647
- package/src/runtime/blockingSubscribe.ts +48 -0
- package/src/runtime/clientBasepath.ts +12 -0
- package/src/runtime/clientHydration.ts +149 -0
- package/src/runtime/dataMutation.tsx +9 -306
- package/src/runtime/formData.ts +153 -0
- package/src/runtime/loaderBridge.ts +11 -12
- package/src/runtime/plugin.node.tsx +76 -291
- package/src/runtime/plugin.tsx +21 -257
- package/src/runtime/pluginShared.ts +112 -0
- package/src/runtime/prefetchLink.tsx +78 -15
- package/src/runtime/register.ts +10 -42
- package/src/runtime/routeTree/components.ts +130 -0
- package/src/runtime/routeTree/construction.ts +238 -0
- package/src/runtime/routeTree/index.ts +7 -0
- package/src/runtime/routeTree/loaders.ts +232 -0
- package/src/runtime/routeTree/paths.ts +36 -0
- package/src/runtime/routeTree/staticData.ts +66 -0
- package/src/runtime/routeTree/tanstackRoutes.ts +36 -0
- package/src/runtime/routeTree/types.ts +87 -0
- package/src/runtime/routeTree.ts +5 -750
- package/src/runtime/router.ts +35 -7
- package/src/runtime/rsc/CompositeComponent.tsx +29 -20
- package/src/runtime/rsc/ReplayableStream.ts +2 -2
- package/src/runtime/rsc/RscNodeRenderer.tsx +9 -27
- package/src/runtime/rsc/SlotContext.tsx +1 -1
- package/src/runtime/rsc/client.tsx +12 -40
- package/src/runtime/rsc/flightSerialization.ts +158 -0
- package/src/runtime/rsc/payloadErrors.ts +73 -0
- package/src/runtime/rsc/payloadFetch.ts +92 -0
- package/src/runtime/rsc/payloadRouter.ts +29 -234
- package/src/runtime/rsc/payloadRoutes.ts +122 -0
- package/src/runtime/rsc/payloadStorage.ts +35 -0
- package/src/runtime/rsc/server.tsx +20 -29
- package/src/runtime/rsc/shared.ts +70 -0
- package/src/runtime/rsc/slotUsageSanitizer.ts +4 -0
- package/src/runtime/rsc/treeGetter.tsx +52 -0
- package/src/runtime/shared/isAbsoluteUrl.ts +8 -0
- package/src/runtime/ssrManagedTags.ts +107 -0
- package/src/runtime/ssrPreload.ts +125 -0
- package/src/runtime/ssrTypes.ts +51 -0
- package/src/runtime/state.ts +9 -3
- package/src/runtime/submitAction.ts +201 -0
- package/src/runtime/types.ts +4 -18
- package/src/runtime/utils.tsx +76 -110
- package/src/types/react-server-dom-rspack.d.ts +56 -0
- package/tests/castRatchet.test.ts +85 -0
- package/tests/realm-isolation.test.ts +114 -0
- package/tests/router/cli.test.ts +7 -0
- package/tests/router/clientHydration.test.tsx +61 -0
- package/tests/router/dataMutation.test.tsx +59 -0
- package/tests/router/fixtures/legacyRuntimeRouter.ts +10 -0
- package/tests/router/fixtures/router-gen.golden.txt +71 -0
- package/tests/router/fixtures/router-gen.oxlint.json +5 -0
- package/tests/router/flightSerialization.roundtrip.test.tsx +137 -0
- package/tests/router/generateRouteArtifacts.test.ts +106 -0
- package/tests/router/hooks.test.ts +14 -0
- package/tests/router/loaderBridge.test.ts +21 -0
- package/tests/router/prefetchLink.test.tsx +106 -59
- package/tests/router/prefetchLinkPreload.test.tsx +85 -0
- package/tests/router/register.test.ts +1 -39
- package/tests/router/routeTree.test.ts +51 -11
- package/tests/router/routerCompatibility.test.ts +245 -0
- package/tests/router/rsc.test.tsx +189 -0
- package/tests/router/rscPayloadRouterMatrix.test.ts +197 -0
- package/tests/router/slotUsageSanitizer.test.ts +23 -0
- package/tests/router/ssrPreload.test.ts +30 -0
- package/tests/router/tanstackTypes.test.ts +298 -1
- package/dist/esm/runtime/pluginCore.mjs +0 -14
- package/dist/esm-node/runtime/pluginCore.mjs +0 -15
- package/dist/types/runtime/pluginCore.d.ts +0 -21
- package/src/runtime/pluginCore.ts +0 -48
package/src/runtime/router.ts
CHANGED
|
@@ -4,12 +4,40 @@
|
|
|
4
4
|
* `router: { framework: 'tanstack', createRoutes }` in modern.runtime.ts).
|
|
5
5
|
*
|
|
6
6
|
* The CLI plugin injects `{ name: 'router', path: '<pkg>/runtime/router' }`
|
|
7
|
-
* for those entries
|
|
8
|
-
*
|
|
9
|
-
* plugin of @modern-js/runtime AND registers the TanStack router provider
|
|
10
|
-
* (the './register' side effect) — the registration can therefore never be
|
|
11
|
-
* tree-shaken away from the entry that needs it.
|
|
7
|
+
* for those entries. This module creates a framework-resolving wrapper whose
|
|
8
|
+
* app-owned provider realm contains this module graph's TanStack factory.
|
|
12
9
|
*/
|
|
13
|
-
import '
|
|
10
|
+
import * as runtimeRouter from '@modern-js/runtime/router/internal';
|
|
11
|
+
import { tanstackRouterProviderFactory } from './register';
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
type LegacyRouterPlugin = (typeof runtimeRouter)['routerPlugin'];
|
|
14
|
+
type CurrentRouterPluginCreator = (
|
|
15
|
+
localProviders: readonly {
|
|
16
|
+
name: string;
|
|
17
|
+
factory: typeof tanstackRouterProviderFactory;
|
|
18
|
+
}[],
|
|
19
|
+
) => LegacyRouterPlugin;
|
|
20
|
+
|
|
21
|
+
function getRouterPlugin(): LegacyRouterPlugin {
|
|
22
|
+
const createRouterPlugin = Reflect.get(runtimeRouter, 'createRouterPlugin') as
|
|
23
|
+
| CurrentRouterPluginCreator
|
|
24
|
+
| undefined;
|
|
25
|
+
|
|
26
|
+
if (typeof createRouterPlugin === 'function') {
|
|
27
|
+
return createRouterPlugin([
|
|
28
|
+
{ name: 'tanstack', factory: tanstackRouterProviderFactory },
|
|
29
|
+
]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const legacyRouterPlugin = Reflect.get(runtimeRouter, 'routerPlugin');
|
|
33
|
+
|
|
34
|
+
if (typeof legacyRouterPlugin === 'function') {
|
|
35
|
+
return tanstackRouterProviderFactory as unknown as LegacyRouterPlugin;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
throw new Error(
|
|
39
|
+
'[@modern-js/plugin-tanstack] The installed @modern-js/runtime/router/internal exports neither createRouterPlugin nor routerPlugin. Install a compatible @modern-js/runtime version.',
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const routerPlugin: LegacyRouterPlugin = getRouterPlugin();
|
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
// @effect-diagnostics strictBooleanExpressions:off
|
|
2
2
|
'use client';
|
|
3
3
|
|
|
4
|
-
import type React from 'react';
|
|
5
4
|
import { Suspense } from 'react';
|
|
6
5
|
import { SlotProvider } from './SlotContext';
|
|
6
|
+
import { EmptyFallback, renderSelectedTree } from './shared';
|
|
7
7
|
import {
|
|
8
8
|
type AnyCompositeComponent,
|
|
9
9
|
type CompositeComponentProps,
|
|
10
10
|
RSC_PROXY_GET_TREE,
|
|
11
|
-
|
|
11
|
+
SERVER_COMPONENT_STREAM,
|
|
12
12
|
} from './symbols';
|
|
13
|
+
import { createTreeGetterFromFlightStream } from './treeGetter';
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
const rawServerValueGetters = new WeakMap<object, () => unknown>();
|
|
16
|
+
|
|
17
|
+
function getRawServerTreeGetter(src: unknown) {
|
|
18
|
+
if (!src || (typeof src !== 'object' && typeof src !== 'function')) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const source = src as {
|
|
23
|
+
[SERVER_COMPONENT_STREAM]?: {
|
|
24
|
+
createReplayStream?: () => ReadableStream<Uint8Array>;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
const stream = source[SERVER_COMPONENT_STREAM];
|
|
28
|
+
if (typeof stream?.createReplayStream !== 'function') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
17
31
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
current = (current as Record<string, unknown>)[key];
|
|
32
|
+
let getTree = rawServerValueGetters.get(src);
|
|
33
|
+
if (!getTree) {
|
|
34
|
+
getTree = createTreeGetterFromFlightStream(stream.createReplayStream());
|
|
35
|
+
rawServerValueGetters.set(src, getTree);
|
|
25
36
|
}
|
|
26
|
-
|
|
37
|
+
|
|
38
|
+
return getTree;
|
|
27
39
|
}
|
|
28
40
|
|
|
29
41
|
function CompositeInner<TComp extends AnyCompositeComponent>({
|
|
@@ -35,14 +47,11 @@ function CompositeInner<TComp extends AnyCompositeComponent>({
|
|
|
35
47
|
src: TComp;
|
|
36
48
|
strict?: boolean;
|
|
37
49
|
}) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
const tree = renderSelectedTree(src, {
|
|
51
|
+
getTree: src[RSC_PROXY_GET_TREE] || getRawServerTreeGetter(src),
|
|
52
|
+
missingTreeError:
|
|
41
53
|
'CompositeComponent src must come from createCompositeComponent().',
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const tree = selectTreePath(getTree(), src[RSC_PROXY_PATH] || []);
|
|
54
|
+
});
|
|
46
55
|
return (
|
|
47
56
|
<SlotProvider implementations={slotProps} strict={strict}>
|
|
48
57
|
{tree}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @effect-diagnostics asyncFunction:off newPromise:off strictBooleanExpressions:off
|
|
2
|
-
|
|
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
|
-
|
|
11
|
+
const REPLAYABLE_STREAM_MARKER = Symbol.for(
|
|
12
12
|
'modern.tanstack.rsc.ReplayableStream',
|
|
13
13
|
);
|
|
14
14
|
|
|
@@ -1,36 +1,18 @@
|
|
|
1
1
|
// @effect-diagnostics strictBooleanExpressions:off
|
|
2
2
|
'use client';
|
|
3
3
|
|
|
4
|
-
import type React from 'react';
|
|
5
4
|
import { Suspense } from 'react';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
RSC_PROXY_GET_TREE,
|
|
9
|
-
RSC_PROXY_PATH,
|
|
10
|
-
} from './symbols';
|
|
11
|
-
|
|
12
|
-
function EmptyFallback() {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function selectTreePath(tree: unknown, path: string[]) {
|
|
17
|
-
let current = tree;
|
|
18
|
-
for (const key of path) {
|
|
19
|
-
if (current === null || typeof current !== 'object') {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
current = (current as Record<string, unknown>)[key];
|
|
23
|
-
}
|
|
24
|
-
return current as React.ReactNode;
|
|
25
|
-
}
|
|
5
|
+
import { EmptyFallback, renderSelectedTree } from './shared';
|
|
6
|
+
import type { AnyRenderableServerComponent } from './symbols';
|
|
26
7
|
|
|
27
8
|
function RscNodeRenderInner({ data }: { data: AnyRenderableServerComponent }) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
9
|
+
return (
|
|
10
|
+
<>
|
|
11
|
+
{renderSelectedTree(data, {
|
|
12
|
+
missingTreeError: 'Renderable RSC is missing its decoded tree getter.',
|
|
13
|
+
})}
|
|
14
|
+
</>
|
|
15
|
+
);
|
|
34
16
|
}
|
|
35
17
|
|
|
36
18
|
export function RscNodeRenderer({
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import type React from 'react';
|
|
4
4
|
import { createContext, use } from 'react';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
type SlotImplementations = Record<string, unknown>;
|
|
7
7
|
|
|
8
8
|
const SlotContext = createContext<{
|
|
9
9
|
implementations: SlotImplementations;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { createSerializationAdapter } from '@tanstack/react-router';
|
|
4
|
-
import { use } from 'react';
|
|
5
4
|
import { CompositeComponent } from './CompositeComponent';
|
|
6
5
|
import { createRscProxy } from './createRscProxy';
|
|
6
|
+
import type { SerializedTanstackRscFlightValue } from './shared';
|
|
7
7
|
import type {
|
|
8
8
|
AnyCompositeComponent,
|
|
9
9
|
RscSlotUsageEvent,
|
|
10
10
|
ServerComponentStream,
|
|
11
11
|
} from './symbols';
|
|
12
|
+
import { createTreeGetterFromFlightStream } from './treeGetter';
|
|
12
13
|
|
|
13
14
|
export type {
|
|
14
15
|
AnyCompositeComponent,
|
|
@@ -23,55 +24,26 @@ type SerializedRsc = {
|
|
|
23
24
|
slotUsagesStream?: ReadableStream<RscSlotUsageEvent>;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
function loadModernRscClientRuntime() {
|
|
31
|
-
modernRscClientRuntimePromise ??= import(
|
|
32
|
-
'@modern-js/runtime/rsc/client'
|
|
33
|
-
).then(runtime => {
|
|
34
|
-
runtime.setServerCallback(runtime.callServer);
|
|
35
|
-
return runtime;
|
|
36
|
-
});
|
|
37
|
-
return modernRscClientRuntimePromise;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function createTreeGetter(stream: ReadableStream<Uint8Array>) {
|
|
41
|
-
let ready = false;
|
|
42
|
-
let tree: unknown;
|
|
43
|
-
const treePromise = loadModernRscClientRuntime()
|
|
44
|
-
.then(runtime =>
|
|
45
|
-
runtime.createFromReadableStream(stream, {
|
|
46
|
-
callServer: runtime.callServer,
|
|
47
|
-
}),
|
|
48
|
-
)
|
|
49
|
-
.then(value => {
|
|
50
|
-
tree = value;
|
|
51
|
-
ready = true;
|
|
52
|
-
return value;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
return () => {
|
|
56
|
-
if (ready) {
|
|
57
|
-
return tree;
|
|
58
|
-
}
|
|
59
|
-
return use(treePromise);
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function createFromFlightStream(serialized: SerializedRsc) {
|
|
27
|
+
function createFromFlightStream(
|
|
28
|
+
serialized: SerializedRsc | SerializedTanstackRscFlightValue,
|
|
29
|
+
) {
|
|
64
30
|
const streamWrapper: ServerComponentStream = {
|
|
65
31
|
createReplayStream: () => serialized.stream,
|
|
66
32
|
};
|
|
67
33
|
|
|
68
|
-
return createRscProxy(
|
|
34
|
+
return createRscProxy(createTreeGetterFromFlightStream(serialized.stream), {
|
|
69
35
|
renderable: serialized.kind === 'renderable',
|
|
70
36
|
slotUsagesStream: serialized.slotUsagesStream,
|
|
71
37
|
stream: streamWrapper,
|
|
72
38
|
});
|
|
73
39
|
}
|
|
74
40
|
|
|
41
|
+
export function createTanstackRscValueFromFlight(
|
|
42
|
+
serialized: SerializedTanstackRscFlightValue,
|
|
43
|
+
): AnyCompositeComponent {
|
|
44
|
+
return createFromFlightStream(serialized) as AnyCompositeComponent;
|
|
45
|
+
}
|
|
46
|
+
|
|
75
47
|
const adapter = createSerializationAdapter({
|
|
76
48
|
key: '$MODERN_TANSTACK_RSC',
|
|
77
49
|
test: (_value: unknown): _value is never => false,
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// @effect-diagnostics asyncFunction:off globalFetch:off processEnv:off strictBooleanExpressions:off
|
|
2
|
+
import {
|
|
3
|
+
isSerializedTanstackRscFlightValue,
|
|
4
|
+
type SerializedTanstackRscFlightValue,
|
|
5
|
+
TANSTACK_RSC_FLIGHT_VALUE,
|
|
6
|
+
} from './shared';
|
|
7
|
+
import {
|
|
8
|
+
isRenderableServerComponent,
|
|
9
|
+
isServerComponent,
|
|
10
|
+
RSC_SLOT_USAGES_STREAM,
|
|
11
|
+
SERVER_COMPONENT_STREAM,
|
|
12
|
+
} from './symbols';
|
|
13
|
+
|
|
14
|
+
export function isPlainObject(
|
|
15
|
+
value: unknown,
|
|
16
|
+
): value is Record<string, unknown> {
|
|
17
|
+
if (!value || typeof value !== 'object') {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const prototype = Object.getPrototypeOf(value);
|
|
21
|
+
return prototype === Object.prototype || prototype === null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function serializeTanstackRscFlightValues(
|
|
25
|
+
value: unknown,
|
|
26
|
+
seen = new WeakMap<object, unknown>(),
|
|
27
|
+
): unknown {
|
|
28
|
+
if (isServerComponent(value)) {
|
|
29
|
+
const streamWrapper = value[SERVER_COMPONENT_STREAM];
|
|
30
|
+
if (!streamWrapper) {
|
|
31
|
+
throw new Error('Cannot serialize TanStack RSC without a Flight stream.');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const kind = isRenderableServerComponent(value)
|
|
35
|
+
? 'renderable'
|
|
36
|
+
: 'composite';
|
|
37
|
+
const slotUsagesStream =
|
|
38
|
+
process.env.NODE_ENV === 'development' && kind === 'composite'
|
|
39
|
+
? value[RSC_SLOT_USAGES_STREAM]
|
|
40
|
+
: undefined;
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
[TANSTACK_RSC_FLIGHT_VALUE]: true,
|
|
44
|
+
kind,
|
|
45
|
+
stream: streamWrapper.createReplayStream(),
|
|
46
|
+
...(slotUsagesStream ? { slotUsagesStream } : {}),
|
|
47
|
+
} satisfies SerializedTanstackRscFlightValue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!value || typeof value !== 'object') {
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
if (seen.has(value)) {
|
|
54
|
+
return seen.get(value);
|
|
55
|
+
}
|
|
56
|
+
if (value instanceof Map) {
|
|
57
|
+
const result = new Map<unknown, unknown>();
|
|
58
|
+
seen.set(value, result);
|
|
59
|
+
for (const [key, item] of value) {
|
|
60
|
+
result.set(
|
|
61
|
+
serializeTanstackRscFlightValues(key, seen),
|
|
62
|
+
serializeTanstackRscFlightValues(item, seen),
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
67
|
+
if (value instanceof Set) {
|
|
68
|
+
const result = new Set<unknown>();
|
|
69
|
+
seen.set(value, result);
|
|
70
|
+
for (const item of value) {
|
|
71
|
+
result.add(serializeTanstackRscFlightValues(item, seen));
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
if (Array.isArray(value)) {
|
|
76
|
+
const result: unknown[] = [];
|
|
77
|
+
seen.set(value, result);
|
|
78
|
+
for (const item of value) {
|
|
79
|
+
result.push(serializeTanstackRscFlightValues(item, seen));
|
|
80
|
+
}
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
if (!isPlainObject(value)) {
|
|
84
|
+
return value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const result: Record<string, unknown> = {};
|
|
88
|
+
seen.set(value, result);
|
|
89
|
+
for (const [key, item] of Object.entries(value)) {
|
|
90
|
+
result[key] = serializeTanstackRscFlightValues(item, seen);
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export async function reviveTanstackRscFlightValues(
|
|
96
|
+
value: unknown,
|
|
97
|
+
seen = new WeakMap<object, unknown>(),
|
|
98
|
+
): Promise<unknown> {
|
|
99
|
+
let reviver:
|
|
100
|
+
| ((serialized: SerializedTanstackRscFlightValue) => unknown)
|
|
101
|
+
| undefined;
|
|
102
|
+
|
|
103
|
+
const getReviver = async () => {
|
|
104
|
+
if (!reviver) {
|
|
105
|
+
const client = await import('./client');
|
|
106
|
+
reviver = client.createTanstackRscValueFromFlight;
|
|
107
|
+
}
|
|
108
|
+
return reviver;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const visit = async (current: unknown): Promise<unknown> => {
|
|
112
|
+
if (isSerializedTanstackRscFlightValue(current)) {
|
|
113
|
+
return (await getReviver())(current);
|
|
114
|
+
}
|
|
115
|
+
if (!current || typeof current !== 'object') {
|
|
116
|
+
return current;
|
|
117
|
+
}
|
|
118
|
+
if (seen.has(current)) {
|
|
119
|
+
return seen.get(current);
|
|
120
|
+
}
|
|
121
|
+
if (current instanceof Map) {
|
|
122
|
+
const result = new Map<unknown, unknown>();
|
|
123
|
+
seen.set(current, result);
|
|
124
|
+
for (const [key, item] of current) {
|
|
125
|
+
result.set(await visit(key), await visit(item));
|
|
126
|
+
}
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
if (current instanceof Set) {
|
|
130
|
+
const result = new Set<unknown>();
|
|
131
|
+
seen.set(current, result);
|
|
132
|
+
for (const item of current) {
|
|
133
|
+
result.add(await visit(item));
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
if (Array.isArray(current)) {
|
|
138
|
+
const result: unknown[] = [];
|
|
139
|
+
seen.set(current, result);
|
|
140
|
+
for (const item of current) {
|
|
141
|
+
result.push(await visit(item));
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
if (!isPlainObject(current)) {
|
|
146
|
+
return current;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const result: Record<string, unknown> = {};
|
|
150
|
+
seen.set(current, result);
|
|
151
|
+
for (const [key, item] of Object.entries(current)) {
|
|
152
|
+
result[key] = await visit(item);
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
return visit(value);
|
|
158
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// @effect-diagnostics asyncFunction:off globalFetch:off processEnv:off strictBooleanExpressions:off
|
|
2
|
+
import type { ServerPayload } from '@modern-js/runtime/context';
|
|
3
|
+
import { isRouteErrorResponse } from '@modern-js/runtime-utils/router';
|
|
4
|
+
|
|
5
|
+
export function shouldRedactServerError(status = 500) {
|
|
6
|
+
return (
|
|
7
|
+
status >= 500 &&
|
|
8
|
+
process.env.NODE_ENV !== 'development' &&
|
|
9
|
+
process.env.NODE_ENV !== 'test'
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function serializePayloadError(error: unknown): unknown {
|
|
14
|
+
if (isRouteErrorResponse(error)) {
|
|
15
|
+
if (shouldRedactServerError(error.status)) {
|
|
16
|
+
return {
|
|
17
|
+
status: error.status,
|
|
18
|
+
statusText: 'Internal Server Error',
|
|
19
|
+
data: 'Unexpected Server Error',
|
|
20
|
+
__type: 'RouteErrorResponse',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return { ...error, __type: 'RouteErrorResponse' };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (error instanceof Error) {
|
|
28
|
+
if (shouldRedactServerError()) {
|
|
29
|
+
return {
|
|
30
|
+
message: 'Unexpected Server Error',
|
|
31
|
+
stack: undefined,
|
|
32
|
+
__type: 'Error',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
message: error.message,
|
|
38
|
+
stack: error.stack,
|
|
39
|
+
__type: 'Error',
|
|
40
|
+
...(error.name !== 'Error' ? { __subType: error.name } : {}),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (shouldRedactServerError()) {
|
|
45
|
+
return {
|
|
46
|
+
message: 'Unexpected Server Error',
|
|
47
|
+
stack: undefined,
|
|
48
|
+
__type: 'Error',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return error;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function isSerializedNotFound(value: unknown) {
|
|
56
|
+
return (
|
|
57
|
+
Boolean(value) &&
|
|
58
|
+
typeof value === 'object' &&
|
|
59
|
+
(value as { isNotFound?: unknown }).isNotFound === true
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function toRouteErrors(payload: ServerPayload) {
|
|
64
|
+
return payload.errors && typeof payload.errors === 'object'
|
|
65
|
+
? (payload.errors as Record<string, unknown>)
|
|
66
|
+
: {};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function toRouteLoaderData(payload: ServerPayload) {
|
|
70
|
+
return payload.loaderData && typeof payload.loaderData === 'object'
|
|
71
|
+
? (payload.loaderData as Record<string, unknown>)
|
|
72
|
+
: {};
|
|
73
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// @effect-diagnostics asyncFunction:off globalFetch:off processEnv:off strictBooleanExpressions:off
|
|
2
|
+
import type { ServerPayload } from '@modern-js/runtime/context';
|
|
3
|
+
import { notFound, redirect } from '@tanstack/react-router';
|
|
4
|
+
import { isAbsoluteUrl } from '../shared/isAbsoluteUrl';
|
|
5
|
+
import { reviveTanstackRscFlightValues } from './flightSerialization';
|
|
6
|
+
|
|
7
|
+
export { isAbsoluteUrl };
|
|
8
|
+
|
|
9
|
+
type PayloadDecoder = (stream: ReadableStream<Uint8Array>) => Promise<unknown>;
|
|
10
|
+
|
|
11
|
+
export const payloadFetchCache = new Map<string, Promise<ServerPayload>>();
|
|
12
|
+
let payloadDecoder: PayloadDecoder | undefined;
|
|
13
|
+
|
|
14
|
+
async function decodePayload(stream: ReadableStream<Uint8Array>) {
|
|
15
|
+
if (payloadDecoder) {
|
|
16
|
+
return reviveTanstackRscFlightValues(await payloadDecoder(stream));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const runtime = await import('@modern-js/runtime/rsc/client');
|
|
20
|
+
return reviveTanstackRscFlightValues(
|
|
21
|
+
await runtime.createFromReadableStream(stream),
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function isServerPayload(value: unknown): value is ServerPayload {
|
|
26
|
+
return (
|
|
27
|
+
Boolean(value) &&
|
|
28
|
+
typeof value === 'object' &&
|
|
29
|
+
(value as ServerPayload).type === 'render' &&
|
|
30
|
+
Array.isArray((value as ServerPayload).routes)
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createPayloadFetchKey(request: Request) {
|
|
35
|
+
return JSON.stringify([
|
|
36
|
+
request.url,
|
|
37
|
+
request.method,
|
|
38
|
+
[...request.headers.entries()].sort(([left], [right]) =>
|
|
39
|
+
left.localeCompare(right),
|
|
40
|
+
),
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function fetchTanstackRscPayload(request: Request) {
|
|
45
|
+
const headers = new Headers(request.headers);
|
|
46
|
+
headers.set('x-rsc-tree', 'true');
|
|
47
|
+
|
|
48
|
+
const response = await fetch(request.url, {
|
|
49
|
+
credentials: 'same-origin',
|
|
50
|
+
headers,
|
|
51
|
+
method: 'GET',
|
|
52
|
+
signal: request.signal,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const redirectLocation = response.headers.get('X-Modernjs-Redirect');
|
|
56
|
+
if (redirectLocation) {
|
|
57
|
+
if (isAbsoluteUrl(redirectLocation)) {
|
|
58
|
+
throw redirect({
|
|
59
|
+
headers: response.headers,
|
|
60
|
+
href: redirectLocation,
|
|
61
|
+
statusCode: response.status,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
throw redirect({
|
|
65
|
+
headers: response.headers,
|
|
66
|
+
statusCode: response.status,
|
|
67
|
+
to: redirectLocation || '/',
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (response.status === 404 && !response.body) {
|
|
72
|
+
throw notFound();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!response.body) {
|
|
76
|
+
throw new Error('TanStack RSC payload response body is null.');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const payload = await decodePayload(response.body);
|
|
80
|
+
if (!isServerPayload(payload)) {
|
|
81
|
+
throw new Error('Unexpected TanStack RSC payload type.');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return payload;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function __setTanstackRscPayloadDecoderForTests(
|
|
88
|
+
decoder?: PayloadDecoder,
|
|
89
|
+
) {
|
|
90
|
+
payloadDecoder = decoder;
|
|
91
|
+
payloadFetchCache.clear();
|
|
92
|
+
}
|