@parlor/client 0.1.0 → 0.3.0
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 +2 -0
- package/dist/action-client.d.ts +2 -0
- package/dist/action-client.d.ts.map +1 -1
- package/dist/action-client.js +13 -4
- package/dist/action-client.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/plugin-client.js.map +1 -1
- package/dist/query-keys.js.map +1 -1
- package/dist/react/action-query.d.ts +26 -0
- package/dist/react/action-query.d.ts.map +1 -0
- package/dist/react/action-query.js +33 -0
- package/dist/react/action-query.js.map +1 -0
- package/dist/react/agent-ui/activity-state.js.map +1 -1
- package/dist/react/agent-ui/chat-activity.js.map +1 -1
- package/dist/react/agent-ui/chat-confirm.js.map +1 -1
- package/dist/react/agent-ui/chat.js.map +1 -1
- package/dist/react/agent-ui/dev.js.map +1 -1
- package/dist/react/agent-ui/runtime.js.map +1 -1
- package/dist/react/agent-ui/use-agent-activity.js.map +1 -1
- package/dist/react/agent-ui/use-agent-confirmations.js.map +1 -1
- package/dist/react/agent-ui/use-agent-view.js.map +1 -1
- package/dist/react/chat/ask-fields.js.map +1 -1
- package/dist/react/chat/chat-ask.d.ts +3 -2
- package/dist/react/chat/chat-ask.d.ts.map +1 -1
- package/dist/react/chat/chat-ask.js +3 -2
- package/dist/react/chat/chat-ask.js.map +1 -1
- package/dist/react/chat/chat-composer.d.ts.map +1 -1
- package/dist/react/chat/chat-composer.js +1 -1
- package/dist/react/chat/chat-composer.js.map +1 -1
- package/dist/react/chat/chat-root.js.map +1 -1
- package/dist/react/chat/chat-thread.js.map +1 -1
- package/dist/react/chat/context.js.map +1 -1
- package/dist/react/chat/create.js.map +1 -1
- package/dist/react/chat/open-turns.js.map +1 -1
- package/dist/react/chat/runtime.d.ts +29 -4
- package/dist/react/chat/runtime.d.ts.map +1 -1
- package/dist/react/chat/runtime.js +82 -11
- package/dist/react/chat/runtime.js.map +1 -1
- package/dist/react/chat/use-chat.d.ts.map +1 -1
- package/dist/react/chat/use-chat.js +2 -0
- package/dist/react/chat/use-chat.js.map +1 -1
- package/dist/react/chat/use-device-setup.js.map +1 -1
- package/dist/react/hooks.d.ts +7 -1
- package/dist/react/hooks.d.ts.map +1 -1
- package/dist/react/hooks.js +17 -13
- package/dist/react/hooks.js.map +1 -1
- package/dist/react/index.d.ts +3 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +2 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/provider.d.ts +6 -3
- package/dist/react/provider.d.ts.map +1 -1
- package/dist/react/provider.js +61 -11
- package/dist/react/provider.js.map +1 -1
- package/dist/react/retry.js.map +1 -1
- package/dist/react/sync-bridge.d.ts +4 -1
- package/dist/react/sync-bridge.d.ts.map +1 -1
- package/dist/react/sync-bridge.js.map +1 -1
- package/dist/react/sync.d.ts +41 -2
- package/dist/react/sync.d.ts.map +1 -1
- package/dist/react/sync.js +127 -9
- package/dist/react/sync.js.map +1 -1
- package/dist/react/use-capability.js.map +1 -1
- package/dist/react/use-devices.js.map +1 -1
- package/dist/react/use-link-device.js.map +1 -1
- package/dist/register.js.map +1 -1
- package/dist/router/errors.d.ts +13 -0
- package/dist/router/errors.d.ts.map +1 -0
- package/dist/router/errors.js +16 -0
- package/dist/router/errors.js.map +1 -0
- package/dist/router/index.d.ts +4 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +4 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/mount.d.ts +22 -0
- package/dist/router/mount.d.ts.map +1 -0
- package/dist/router/mount.js +27 -0
- package/dist/router/mount.js.map +1 -0
- package/dist/router/router.d.ts +29 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +44 -0
- package/dist/router/router.js.map +1 -0
- package/dist/session.d.ts +7 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/dist/ssr/index.d.ts +2 -0
- package/dist/ssr/index.d.ts.map +1 -0
- package/dist/ssr/index.js +2 -0
- package/dist/ssr/index.js.map +1 -0
- package/dist/ssr/render.d.ts +18 -0
- package/dist/ssr/render.d.ts.map +1 -0
- package/dist/ssr/render.js +96 -0
- package/dist/ssr/render.js.map +1 -0
- package/package.json +15 -7
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { RouterContextProvider, Scripts } from "@tanstack/react-router";
|
|
3
|
+
import { createRequestHandler, getSsrStatus, transformHtmlStringWithRouter, } from "@tanstack/react-router/ssr/server";
|
|
4
|
+
import { createElement } from "react";
|
|
5
|
+
import { renderToReadableStream, renderToString } from "react-dom/server";
|
|
6
|
+
import { createActionClient } from "../action-client.js";
|
|
7
|
+
import { SERVER_RENDERED } from "../router/mount.js";
|
|
8
|
+
const FORWARDED_HEADERS = ["cookie", "authorization"];
|
|
9
|
+
const APP_TAG = "parlor-app";
|
|
10
|
+
const CONTAINER = /<([a-z][\w-]*)(\s[^>]*?\bid=(["']?)root\3(?:\s[^>]*)?)>\s*<\/\1>/i;
|
|
11
|
+
const TITLE = /<title[\s>]/i;
|
|
12
|
+
const TEMPLATE_TITLE = /\s*<title[^>]*>[\s\S]*?<\/title>/i;
|
|
13
|
+
let warnedNoContainer = false;
|
|
14
|
+
function forwarded(headers) {
|
|
15
|
+
const kept = {};
|
|
16
|
+
for (const name of FORWARDED_HEADERS) {
|
|
17
|
+
const value = headers.get(name);
|
|
18
|
+
if (value !== null)
|
|
19
|
+
kept[name] = value;
|
|
20
|
+
}
|
|
21
|
+
return kept;
|
|
22
|
+
}
|
|
23
|
+
/** A route that says it never renders on the server settles it before any loader runs. */
|
|
24
|
+
function declined(router, pathname) {
|
|
25
|
+
const [routes] = router.getMatchedRoutes(pathname);
|
|
26
|
+
return routes.some((route) => {
|
|
27
|
+
const ssr = route.options.ssr ?? router.options.defaultSsr ?? true;
|
|
28
|
+
return ssr === false || ssr === "data-only";
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Every element above the app has one child, so `useId` counts as it does from the browser's
|
|
33
|
+
* root. The router's scripts render after the app, once it has taken what loaders dehydrated.
|
|
34
|
+
*/
|
|
35
|
+
async function renderDocument(router, element, nonce) {
|
|
36
|
+
const stream = await renderToReadableStream(_jsx("html", { children: _jsx("body", { children: createElement(APP_TAG, null, element) }) }), {
|
|
37
|
+
nonce,
|
|
38
|
+
progressiveChunkSize: Number.POSITIVE_INFINITY,
|
|
39
|
+
onError: (error) => console.error("[parlor] Server render:", error),
|
|
40
|
+
});
|
|
41
|
+
await stream.allReady;
|
|
42
|
+
const app = await new Response(stream).text();
|
|
43
|
+
const scripts = renderToString(_jsx(RouterContextProvider, { router: router, children: _jsx(Scripts, {}) }));
|
|
44
|
+
const html = app
|
|
45
|
+
.replace(/^<!DOCTYPE html>/i, "")
|
|
46
|
+
.replace("</body>", () => `${scripts}</body>`);
|
|
47
|
+
return transformHtmlStringWithRouter(router, html);
|
|
48
|
+
}
|
|
49
|
+
/** React renders the app and hoists its head tags; the template keeps everything else. */
|
|
50
|
+
function intoTemplate(template, rendered) {
|
|
51
|
+
const head = rendered.slice(rendered.indexOf("<head>") + "<head>".length, rendered.indexOf("</head>"));
|
|
52
|
+
const appStart = rendered.indexOf(`<${APP_TAG}>`) + `<${APP_TAG}>`.length;
|
|
53
|
+
const appEnd = rendered.lastIndexOf(`</${APP_TAG}>`);
|
|
54
|
+
const scripts = rendered.slice(appEnd + `</${APP_TAG}>`.length, rendered.lastIndexOf("</body>"));
|
|
55
|
+
const headEnd = template.indexOf("</head>");
|
|
56
|
+
const templateHead = template.slice(0, headEnd);
|
|
57
|
+
const shell = `${TITLE.test(head) ? templateHead.replace(TEMPLATE_TITLE, "") : templateHead}${head}${template.slice(headEnd)}`;
|
|
58
|
+
return shell.replace(CONTAINER, (_match, tag, attributes) => `<${tag}${attributes} ${SERVER_RENDERED}>${rendered.slice(appStart, appEnd)}</${tag}>${scripts}`);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Renders one document request with TanStack Router's SSR handler: the loaders run against
|
|
62
|
+
* the app's server with the request's cookie and authorization, then React renders the
|
|
63
|
+
* matched routes and the router's state, query cache included, goes along for hydration.
|
|
64
|
+
*/
|
|
65
|
+
export function createRenderer(createApp) {
|
|
66
|
+
return async (request, { template, fetch, nonce }) => {
|
|
67
|
+
if (!CONTAINER.test(template)) {
|
|
68
|
+
if (!warnedNoContainer) {
|
|
69
|
+
warnedNoContainer = true;
|
|
70
|
+
console.warn('[parlor] index.html has no empty element with id="root", so pages are not rendered on the server.');
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const url = new URL(request.url);
|
|
75
|
+
const { router, element } = createApp(createActionClient({
|
|
76
|
+
baseUrl: url.origin,
|
|
77
|
+
fetch: (input, init) => fetch(new Request(input, init)),
|
|
78
|
+
headers: forwarded(request.headers),
|
|
79
|
+
}));
|
|
80
|
+
if (declined(router, url.pathname))
|
|
81
|
+
return undefined;
|
|
82
|
+
router.update({ ...router.options, ssr: { nonce } });
|
|
83
|
+
const notRendered = new Response();
|
|
84
|
+
const response = await createRequestHandler({ request, createRouter: () => router })(async ({ responseHeaders }) => {
|
|
85
|
+
if (!router.state.matches.every((match) => match.ssr === true))
|
|
86
|
+
return notRendered;
|
|
87
|
+
const page = intoTemplate(template, await renderDocument(router, element, nonce));
|
|
88
|
+
return new Response(page, {
|
|
89
|
+
status: getSsrStatus(router),
|
|
90
|
+
headers: responseHeaders,
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
return response === notRendered ? undefined : response;
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/ssr/render.tsx"],"names":[],"mappings":"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","sourcesContent":["import { type AnyRouter, RouterContextProvider, Scripts } from \"@tanstack/react-router\";\nimport {\n createRequestHandler,\n getSsrStatus,\n transformHtmlStringWithRouter,\n} from \"@tanstack/react-router/ssr/server\";\nimport { createElement, type ReactNode } from \"react\";\nimport { renderToReadableStream, renderToString } from \"react-dom/server\";\n\nimport { createActionClient } from \"../action-client.js\";\nimport { type CreateParlorApp, SERVER_RENDERED } from \"../router/mount.js\";\n\nexport interface RenderOptions {\n /** The app's `index.html` as the browser gets it; the page renders into its `#root`. */\n readonly template: string;\n /** Reaches the app's server: in process, through its Durable Object, or over the network in dev. */\n readonly fetch: (request: Request) => Promise<Response>;\n /** Goes on every inline script; the response's policy allows it. */\n readonly nonce: string;\n}\n\n/** The page, or undefined when a route it matches does not render on the server. */\nexport type RenderPage = (\n request: Request,\n options: RenderOptions,\n) => Promise<Response | undefined>;\n\nconst FORWARDED_HEADERS = [\"cookie\", \"authorization\"] as const;\nconst APP_TAG = \"parlor-app\";\nconst CONTAINER = /<([a-z][\\w-]*)(\\s[^>]*?\\bid=([\"']?)root\\3(?:\\s[^>]*)?)>\\s*<\\/\\1>/i;\nconst TITLE = /<title[\\s>]/i;\nconst TEMPLATE_TITLE = /\\s*<title[^>]*>[\\s\\S]*?<\\/title>/i;\n\nlet warnedNoContainer = false;\n\nfunction forwarded(headers: Headers): Record<string, string> {\n const kept: Record<string, string> = {};\n for (const name of FORWARDED_HEADERS) {\n const value = headers.get(name);\n if (value !== null) kept[name] = value;\n }\n return kept;\n}\n\n/** A route that says it never renders on the server settles it before any loader runs. */\nfunction declined(router: AnyRouter, pathname: string): boolean {\n const [routes] = router.getMatchedRoutes(pathname);\n return routes.some((route) => {\n const ssr = route.options.ssr ?? router.options.defaultSsr ?? true;\n return ssr === false || ssr === \"data-only\";\n });\n}\n\n/**\n * Every element above the app has one child, so `useId` counts as it does from the browser's\n * root. The router's scripts render after the app, once it has taken what loaders dehydrated.\n */\nasync function renderDocument(\n router: AnyRouter,\n element: ReactNode,\n nonce: string,\n): Promise<string> {\n const stream = await renderToReadableStream(\n <html>\n <body>{createElement(APP_TAG, null, element)}</body>\n </html>,\n {\n nonce,\n progressiveChunkSize: Number.POSITIVE_INFINITY,\n onError: (error) => console.error(\"[parlor] Server render:\", error),\n },\n );\n await stream.allReady;\n const app = await new Response(stream).text();\n const scripts = renderToString(\n <RouterContextProvider router={router}>\n <Scripts />\n </RouterContextProvider>,\n );\n const html = app\n .replace(/^<!DOCTYPE html>/i, \"\")\n .replace(\"</body>\", () => `${scripts}</body>`);\n return transformHtmlStringWithRouter(router, html);\n}\n\n/** React renders the app and hoists its head tags; the template keeps everything else. */\nfunction intoTemplate(template: string, rendered: string): string {\n const head = rendered.slice(\n rendered.indexOf(\"<head>\") + \"<head>\".length,\n rendered.indexOf(\"</head>\"),\n );\n const appStart = rendered.indexOf(`<${APP_TAG}>`) + `<${APP_TAG}>`.length;\n const appEnd = rendered.lastIndexOf(`</${APP_TAG}>`);\n const scripts = rendered.slice(\n appEnd + `</${APP_TAG}>`.length,\n rendered.lastIndexOf(\"</body>\"),\n );\n const headEnd = template.indexOf(\"</head>\");\n const templateHead = template.slice(0, headEnd);\n const shell = `${TITLE.test(head) ? templateHead.replace(TEMPLATE_TITLE, \"\") : templateHead}${head}${template.slice(headEnd)}`;\n return shell.replace(\n CONTAINER,\n (_match, tag: string, attributes: string) =>\n `<${tag}${attributes} ${SERVER_RENDERED}>${rendered.slice(appStart, appEnd)}</${tag}>${scripts}`,\n );\n}\n\n/**\n * Renders one document request with TanStack Router's SSR handler: the loaders run against\n * the app's server with the request's cookie and authorization, then React renders the\n * matched routes and the router's state, query cache included, goes along for hydration.\n */\nexport function createRenderer(createApp: CreateParlorApp): RenderPage {\n return async (request, { template, fetch, nonce }) => {\n if (!CONTAINER.test(template)) {\n if (!warnedNoContainer) {\n warnedNoContainer = true;\n console.warn(\n '[parlor] index.html has no empty element with id=\"root\", so pages are not rendered on the server.',\n );\n }\n return undefined;\n }\n const url = new URL(request.url);\n const { router, element } = createApp(\n createActionClient({\n baseUrl: url.origin,\n fetch: (input, init) => fetch(new Request(input, init)),\n headers: forwarded(request.headers),\n }),\n );\n if (declined(router, url.pathname)) return undefined;\n router.update({ ...router.options, ssr: { nonce } });\n\n const notRendered = new Response();\n const response = await createRequestHandler({ request, createRouter: () => router })(\n async ({ responseHeaders }) => {\n if (!router.state.matches.every((match) => match.ssr === true))\n return notRendered;\n const page = intoTemplate(template, await renderDocument(router, element, nonce));\n return new Response(page, {\n status: getSsrStatus(router),\n headers: responseHeaders,\n });\n },\n );\n return response === notRendered ? undefined : response;\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parlor/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"homepage": "https://cychien.github.io/parlor",
|
|
5
5
|
"bugs": "https://github.com/cychien/parlor/issues",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,14 +22,22 @@
|
|
|
22
22
|
"./react": {
|
|
23
23
|
"types": "./dist/react/index.d.ts",
|
|
24
24
|
"import": "./dist/react/index.js"
|
|
25
|
+
},
|
|
26
|
+
"./router": {
|
|
27
|
+
"types": "./dist/router/index.d.ts",
|
|
28
|
+
"import": "./dist/router/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./ssr": {
|
|
31
|
+
"types": "./dist/ssr/index.d.ts",
|
|
32
|
+
"import": "./dist/ssr/index.js"
|
|
25
33
|
}
|
|
26
34
|
},
|
|
27
35
|
"dependencies": {
|
|
28
|
-
"@parlor/
|
|
29
|
-
"@parlor/
|
|
30
|
-
"@parlor/
|
|
31
|
-
"@parlor/
|
|
32
|
-
"@parlor/
|
|
36
|
+
"@parlor/agent-ui": "0.3.0",
|
|
37
|
+
"@parlor/core": "0.3.0",
|
|
38
|
+
"@parlor/chat": "0.3.0",
|
|
39
|
+
"@parlor/sync": "0.3.0",
|
|
40
|
+
"@parlor/capabilities": "0.3.0"
|
|
33
41
|
},
|
|
34
42
|
"devDependencies": {
|
|
35
43
|
"@tanstack/react-query": "^5.104.1",
|
|
@@ -47,7 +55,7 @@
|
|
|
47
55
|
"zod": "^4.6.5"
|
|
48
56
|
},
|
|
49
57
|
"peerDependencies": {
|
|
50
|
-
"@tanstack/react-query": ">=5",
|
|
58
|
+
"@tanstack/react-query": ">=5.102",
|
|
51
59
|
"@tanstack/react-router": ">=1.170",
|
|
52
60
|
"react": ">=19",
|
|
53
61
|
"react-dom": ">=19"
|