@octanejs/tanstack-router 0.1.10 → 0.1.12
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/README.md +24 -11
- package/package.json +26 -11
- package/src/Asset.tsrx +122 -0
- package/src/Asset.tsrx.d.ts +9 -0
- package/src/Await.tsrx +2 -1
- package/src/Await.tsrx.d.ts +8 -6
- package/src/Body.ts +31 -0
- package/src/CatchBoundary.tsrx +1 -3
- package/src/ClientOnly.tsrx +4 -2
- package/src/Head.ts +22 -0
- package/src/HeadContent.tsrx +41 -0
- package/src/HeadContent.tsrx.d.ts +8 -0
- package/src/Html.ts +19 -0
- package/src/Link.tsrx +25 -7
- package/src/Link.tsrx.d.ts +3 -4
- package/src/Match.tsrx +40 -13
- package/src/Matches.tsrx +7 -7
- package/src/Outlet.tsrx +3 -3
- package/src/RouteNotFound.tsrx +1 -1
- package/src/RouterProvider.tsrx +2 -1
- package/src/ScriptOnce.tsrx +23 -0
- package/src/ScriptOnce.tsrx.d.ts +3 -0
- package/src/Scripts.tsrx +42 -0
- package/src/Scripts.tsrx.d.ts +3 -0
- package/src/Transitioner.tsrx +15 -13
- package/src/assetKeys.ts +11 -0
- package/src/context.ts +6 -3
- package/src/externalHydration.ts +77 -0
- package/src/fileRoute.ts +277 -0
- package/src/frameworkTypes.ts +42 -0
- package/src/generator-plugin.d.ts +20 -0
- package/src/generator-plugin.js +108 -0
- package/src/headContentUtils.ts +172 -0
- package/src/hooks.ts +151 -0
- package/src/index.ts +84 -4
- package/src/lazyRouteComponent.ts +2 -1
- package/src/link.ts +25 -4
- package/src/linkTypes.ts +95 -0
- package/src/not-found.tsrx +2 -2
- package/src/octane-compiler.d.ts +12 -0
- package/src/route.ts +438 -42
- package/src/routeHookTypes.ts +228 -0
- package/src/router.ts +31 -6
- package/src/scriptContentUtils.ts +64 -0
- package/src/scroll-restoration.tsrx +16 -0
- package/src/scroll-restoration.tsrx.d.ts +3 -0
- package/src/ssr/RouterClient.tsrx +36 -0
- package/src/ssr/RouterClient.tsrx.d.ts +4 -0
- package/src/ssr/RouterServer.tsrx +6 -0
- package/src/ssr/RouterServer.tsrx.d.ts +4 -0
- package/src/ssr/client.ts +4 -0
- package/src/ssr/defaultRenderHandler.ts +11 -0
- package/src/ssr/defaultStreamHandler.ts +12 -0
- package/src/ssr/renderRouterToStream.ts +195 -0
- package/src/ssr/renderRouterToString.ts +58 -0
- package/src/ssr/server.ts +8 -0
- package/src/structuralSharing.ts +41 -0
- package/src/typePrimitives.ts +77 -0
- package/src/useAwaited.ts +7 -2
- package/src/useBlocker.tsrx +2 -1
- package/src/useRouterState.ts +20 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { renderToString as octaneRenderToString } from 'octane/server';
|
|
2
|
+
import type { ComponentBody } from 'octane';
|
|
3
|
+
import type { AnyRouter } from '@tanstack/router-core';
|
|
4
|
+
|
|
5
|
+
type RouterApp = ComponentBody<{ router: AnyRouter }>;
|
|
6
|
+
type ServerComponent = Parameters<typeof octaneRenderToString>[0];
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- framework render handlers share an async contract
|
|
9
|
+
export async function renderRouterToString({
|
|
10
|
+
router,
|
|
11
|
+
responseHeaders,
|
|
12
|
+
App,
|
|
13
|
+
}: {
|
|
14
|
+
router: AnyRouter;
|
|
15
|
+
responseHeaders: Headers;
|
|
16
|
+
App: RouterApp;
|
|
17
|
+
}) {
|
|
18
|
+
try {
|
|
19
|
+
const result = octaneRenderToString(
|
|
20
|
+
App as unknown as ServerComponent,
|
|
21
|
+
{ router },
|
|
22
|
+
{ nonce: router.options.ssr?.nonce },
|
|
23
|
+
);
|
|
24
|
+
router.serverSsr!.setRenderFinished();
|
|
25
|
+
|
|
26
|
+
return new Response(
|
|
27
|
+
finalizeBufferedHtml(result.html, result.css, router.serverSsr!.takeBufferedHtml()),
|
|
28
|
+
{
|
|
29
|
+
status: router.stores.statusCode.get(),
|
|
30
|
+
headers: responseHeaders,
|
|
31
|
+
},
|
|
32
|
+
);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
console.error('Render to string error:', error);
|
|
35
|
+
return new Response('Internal Server Error', {
|
|
36
|
+
status: 500,
|
|
37
|
+
headers: responseHeaders,
|
|
38
|
+
});
|
|
39
|
+
} finally {
|
|
40
|
+
router.serverSsr?.cleanup();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function finalizeBufferedHtml(renderedHtml: string, css: string, injectedHtml?: string) {
|
|
45
|
+
let html = renderedHtml;
|
|
46
|
+
|
|
47
|
+
if (css) {
|
|
48
|
+
html = html.includes('</head>') ? html.replace('</head>', `${css}</head>`) : `${css}${html}`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (injectedHtml) {
|
|
52
|
+
html = html.includes('</body>')
|
|
53
|
+
? html.replace('</body>', `${injectedHtml}</body>`)
|
|
54
|
+
: `${html}${injectedHtml}`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return `<!DOCTYPE html>${html}`;
|
|
58
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import '../frameworkTypes';
|
|
2
|
+
|
|
3
|
+
export { RouterServer } from './RouterServer.tsrx';
|
|
4
|
+
export { defaultRenderHandler } from './defaultRenderHandler';
|
|
5
|
+
export { defaultStreamHandler } from './defaultStreamHandler';
|
|
6
|
+
export { renderRouterToStream } from './renderRouterToStream';
|
|
7
|
+
export { renderRouterToString } from './renderRouterToString';
|
|
8
|
+
export * from '@tanstack/router-core/ssr/server';
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AnyRouter,
|
|
3
|
+
Constrain,
|
|
4
|
+
OptionalStructuralSharing,
|
|
5
|
+
ValidateJSON,
|
|
6
|
+
} from '@tanstack/router-core';
|
|
7
|
+
|
|
8
|
+
export type DefaultStructuralSharingEnabled<TRouter extends AnyRouter> =
|
|
9
|
+
boolean extends TRouter['options']['defaultStructuralSharing']
|
|
10
|
+
? false
|
|
11
|
+
: NonNullable<TRouter['options']['defaultStructuralSharing']>;
|
|
12
|
+
|
|
13
|
+
export interface RequiredStructuralSharing<TStructuralSharing, TConstraint> {
|
|
14
|
+
readonly structuralSharing: Constrain<TStructuralSharing, TConstraint>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type StructuralSharingOption<
|
|
18
|
+
TRouter extends AnyRouter,
|
|
19
|
+
TSelected,
|
|
20
|
+
TStructuralSharing,
|
|
21
|
+
> = unknown extends TSelected
|
|
22
|
+
? OptionalStructuralSharing<TStructuralSharing, boolean>
|
|
23
|
+
: unknown extends TRouter['routeTree']
|
|
24
|
+
? OptionalStructuralSharing<TStructuralSharing, boolean>
|
|
25
|
+
: TSelected extends ValidateJSON<TSelected>
|
|
26
|
+
? OptionalStructuralSharing<TStructuralSharing, boolean>
|
|
27
|
+
: DefaultStructuralSharingEnabled<TRouter> extends true
|
|
28
|
+
? RequiredStructuralSharing<TStructuralSharing, false>
|
|
29
|
+
: OptionalStructuralSharing<TStructuralSharing, false>;
|
|
30
|
+
|
|
31
|
+
export type StructuralSharingEnabled<
|
|
32
|
+
TRouter extends AnyRouter,
|
|
33
|
+
TStructuralSharing,
|
|
34
|
+
> = boolean extends TStructuralSharing
|
|
35
|
+
? DefaultStructuralSharingEnabled<TRouter>
|
|
36
|
+
: TStructuralSharing;
|
|
37
|
+
|
|
38
|
+
export type ValidateSelected<TRouter extends AnyRouter, TSelected, TStructuralSharing> =
|
|
39
|
+
StructuralSharingEnabled<TRouter, TStructuralSharing> extends true
|
|
40
|
+
? ValidateJSON<TSelected>
|
|
41
|
+
: TSelected;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AnyRouter,
|
|
3
|
+
Constrain,
|
|
4
|
+
InferFrom,
|
|
5
|
+
InferMaskFrom,
|
|
6
|
+
InferMaskTo,
|
|
7
|
+
InferSelected,
|
|
8
|
+
InferShouldThrow,
|
|
9
|
+
InferStrict,
|
|
10
|
+
InferTo,
|
|
11
|
+
RegisteredRouter,
|
|
12
|
+
} from '@tanstack/router-core';
|
|
13
|
+
import type { LinkComponentProps } from './linkTypes';
|
|
14
|
+
import type { UseParamsOptions, UseSearchOptions } from './routeHookTypes';
|
|
15
|
+
|
|
16
|
+
export type ValidateLinkOptions<
|
|
17
|
+
TRouter extends AnyRouter = RegisteredRouter,
|
|
18
|
+
TOptions = unknown,
|
|
19
|
+
TDefaultFrom extends string = string,
|
|
20
|
+
TComp = 'a',
|
|
21
|
+
> = Constrain<
|
|
22
|
+
TOptions,
|
|
23
|
+
LinkComponentProps<
|
|
24
|
+
TComp,
|
|
25
|
+
TRouter,
|
|
26
|
+
InferFrom<TOptions, TDefaultFrom>,
|
|
27
|
+
InferTo<TOptions>,
|
|
28
|
+
InferMaskFrom<TOptions>,
|
|
29
|
+
InferMaskTo<TOptions>
|
|
30
|
+
>
|
|
31
|
+
>;
|
|
32
|
+
|
|
33
|
+
/** @private */
|
|
34
|
+
export type InferStructuralSharing<TOptions> = TOptions extends {
|
|
35
|
+
structuralSharing: infer TStructuralSharing;
|
|
36
|
+
}
|
|
37
|
+
? TStructuralSharing
|
|
38
|
+
: unknown;
|
|
39
|
+
|
|
40
|
+
export type ValidateUseSearchOptions<
|
|
41
|
+
TOptions,
|
|
42
|
+
TRouter extends AnyRouter = RegisteredRouter,
|
|
43
|
+
> = Constrain<
|
|
44
|
+
TOptions,
|
|
45
|
+
UseSearchOptions<
|
|
46
|
+
TRouter,
|
|
47
|
+
InferFrom<TOptions>,
|
|
48
|
+
InferStrict<TOptions>,
|
|
49
|
+
InferShouldThrow<TOptions>,
|
|
50
|
+
InferSelected<TOptions>,
|
|
51
|
+
InferStructuralSharing<TOptions>
|
|
52
|
+
>
|
|
53
|
+
>;
|
|
54
|
+
|
|
55
|
+
export type ValidateUseParamsOptions<
|
|
56
|
+
TOptions,
|
|
57
|
+
TRouter extends AnyRouter = RegisteredRouter,
|
|
58
|
+
> = Constrain<
|
|
59
|
+
TOptions,
|
|
60
|
+
UseParamsOptions<
|
|
61
|
+
TRouter,
|
|
62
|
+
InferFrom<TOptions>,
|
|
63
|
+
InferStrict<TOptions>,
|
|
64
|
+
InferShouldThrow<TOptions>,
|
|
65
|
+
InferSelected<TOptions>,
|
|
66
|
+
InferStructuralSharing<TOptions>
|
|
67
|
+
>
|
|
68
|
+
>;
|
|
69
|
+
|
|
70
|
+
export type ValidateLinkOptionsArray<
|
|
71
|
+
TRouter extends AnyRouter = RegisteredRouter,
|
|
72
|
+
TOptions extends ReadonlyArray<unknown> = ReadonlyArray<unknown>,
|
|
73
|
+
TDefaultFrom extends string = string,
|
|
74
|
+
TComp = 'a',
|
|
75
|
+
> = {
|
|
76
|
+
[K in keyof TOptions]: ValidateLinkOptions<TRouter, TOptions[K], TDefaultFrom, TComp>;
|
|
77
|
+
};
|
package/src/useAwaited.ts
CHANGED
|
@@ -3,7 +3,12 @@
|
|
|
3
3
|
// this is a one-liner. The promise is typically produced by router-core's `defer()`
|
|
4
4
|
// in a loader and streamed to the client.
|
|
5
5
|
import { use } from 'octane';
|
|
6
|
+
import { toExternalHydrationThenable } from './externalHydration';
|
|
6
7
|
|
|
7
|
-
export
|
|
8
|
-
|
|
8
|
+
export type AwaitOptions<T> = {
|
|
9
|
+
promise: Promise<T>;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function useAwaited<T>(opts: AwaitOptions<T>): T {
|
|
13
|
+
return use(toExternalHydrationThenable(opts.promise));
|
|
9
14
|
}
|
package/src/useBlocker.tsrx
CHANGED
|
@@ -180,7 +180,8 @@ export function useBlocker(
|
|
|
180
180
|
|
|
181
181
|
// Upstream's PromptProps: the blocker options plus optional children (a render
|
|
182
182
|
// prop receiving the resolver, or plain renderables).
|
|
183
|
-
export type PromptProps =
|
|
183
|
+
export type PromptProps =
|
|
184
|
+
(UseBlockerOpts | LegacyBlockerOpts) & {
|
|
184
185
|
children?: OctaneNode | ((params: BlockerResolver) => OctaneNode);
|
|
185
186
|
};
|
|
186
187
|
|
package/src/useRouterState.ts
CHANGED
|
@@ -3,7 +3,27 @@
|
|
|
3
3
|
import { useStore } from './useStore';
|
|
4
4
|
import { useRouter } from './context';
|
|
5
5
|
import { splitSlot, subSlot } from './internal';
|
|
6
|
+
import type { AnyRouter, RegisteredRouter, RouterState } from '@tanstack/router-core';
|
|
7
|
+
import type { StructuralSharingOption, ValidateSelected } from './structuralSharing';
|
|
6
8
|
|
|
9
|
+
export type UseRouterStateOptions<TRouter extends AnyRouter, TSelected, TStructuralSharing> = {
|
|
10
|
+
router?: TRouter;
|
|
11
|
+
select?: (
|
|
12
|
+
state: RouterState<TRouter['routeTree']>,
|
|
13
|
+
) => ValidateSelected<TRouter, TSelected, TStructuralSharing>;
|
|
14
|
+
} & StructuralSharingOption<TRouter, TSelected, TStructuralSharing>;
|
|
15
|
+
|
|
16
|
+
export type UseRouterStateResult<TRouter extends AnyRouter, TSelected> = unknown extends TSelected
|
|
17
|
+
? RouterState<TRouter['routeTree']>
|
|
18
|
+
: TSelected;
|
|
19
|
+
|
|
20
|
+
export function useRouterState<
|
|
21
|
+
TRouter extends AnyRouter = RegisteredRouter,
|
|
22
|
+
TSelected = unknown,
|
|
23
|
+
TStructuralSharing extends boolean = boolean,
|
|
24
|
+
>(
|
|
25
|
+
opts?: UseRouterStateOptions<TRouter, TSelected, TStructuralSharing>,
|
|
26
|
+
): UseRouterStateResult<TRouter, TSelected>;
|
|
7
27
|
export function useRouterState(...args: any[]): any {
|
|
8
28
|
const [user, slot] = splitSlot(args);
|
|
9
29
|
const opts = (user[0] ?? {}) as { select?: (s: any) => any; router?: any };
|