react-server-frame 0.0.4 → 0.0.6

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.
@@ -18,4 +18,5 @@ declare function hydrate({
18
18
  createFromReadableStream: (stream: ReadableStream<Uint8Array>, options?: object) => Promise<Payload>;
19
19
  }): void;
20
20
  //#endregion
21
- export { createServerCallback, hydrate };
21
+ export { createServerCallback, hydrate };
22
+ //# sourceMappingURL=browser.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.mts","names":[],"sources":["../src/browser.tsx"],"mappings":";;;iBAQgB,oBAAA,CAAA;EACd,eAAA;EACA,2BAAA;EACA;AAAA;EAEA,eAAA,GAAkB,QAAA,EAAU,OAAA,CAAQ,QAAA,GAAW,OAAA,cAAqB,OAAA,CAAQ,OAAA;EAC5E,2BAAA;EACA,WAAA,GAAc,CAAA,aAAc,OAAA,cAAqB,OAAA,UAAiB,QAAA;AAAA,KACnE,EAAA,UACyB,IAAA,gBAAiB,OAAA;AAAA,iBAgE3B,OAAA,CAAA;EACd,eAAA;EACA;AAAA;EAEA,eAAA,GAAkB,QAAA,EAAU,OAAA,CAAQ,QAAA,GAAW,OAAA,cAAqB,OAAA,CAAQ,OAAA;EAC5E,wBAAA,GACE,MAAA,EAAQ,cAAA,CAAe,UAAA,GACvB,OAAA,cACG,OAAA,CAAQ,OAAA;AAAA"}
package/dist/browser.mjs CHANGED
@@ -86,3 +86,5 @@ function hydrate({ createFromFetch, createFromReadableStream }) {
86
86
  }
87
87
  //#endregion
88
88
  export { createServerCallback, hydrate };
89
+
90
+ //# sourceMappingURL=browser.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.mjs","names":[],"sources":["../src/browser.tsx"],"sourcesContent":["import { startTransition, StrictMode, use, useState } from \"react\";\nimport { hydrateRoot } from \"react-dom/client\";\nimport { rscStream } from \"rsc-html-stream/client\";\n\nimport type { Payload } from \"./generic-payload.ts\";\n\nlet setPayload: (payload: Promise<Payload>) => void;\n\nexport function createServerCallback({\n createFromFetch,\n createTemporaryReferenceSet,\n encodeReply,\n}: {\n createFromFetch: (response: Promise<Response>, options?: object) => Promise<Payload>;\n createTemporaryReferenceSet: () => unknown;\n encodeReply: (v: unknown[], options?: object) => Promise<string | FormData>;\n}) {\n return async (id: string, args: unknown[]) => {\n const url = new URL(window.location.href);\n url.pathname += \".rsc\";\n const temporaryReferences = createTemporaryReferenceSet();\n const payload = await createFromFetch(\n fetch(url, {\n method: \"POST\",\n body: await encodeReply(args, { temporaryReferences }),\n headers: {\n \"x-rsc-action\": id,\n },\n }),\n { temporaryReferences },\n );\n requestAnimationFrame(() => {\n if (payload.type === \"render\") {\n startTransition(() => {\n setPayload(Promise.resolve(payload));\n });\n }\n if (payload.type === \"redirect\") {\n if (window.navigation) {\n requestAnimationFrame(() => {\n window.navigation.navigate(payload.redirect, {\n history: \"replace\",\n });\n });\n } else {\n window.location.href = payload.redirect;\n }\n }\n });\n return payload.returnValue;\n };\n}\n\nlet seenPayloads = new WeakMap<Payload, Promise<void>>();\nfunction Content({ initialPayload }: { initialPayload: Promise<Payload> }) {\n const [promise, _setPayload] = useState(initialPayload);\n setPayload = _setPayload;\n\n const payload = use(promise);\n\n if (payload.type === \"redirect\") {\n if (window.navigation) {\n if (!seenPayloads.has(payload)) {\n const promise = Promise.resolve(\n window.navigation.navigate(payload.redirect, {\n history: \"replace\",\n }).finished,\n ).then(() => {});\n seenPayloads.set(payload, Promise.resolve(promise));\n }\n use(seenPayloads.get(payload)!);\n return null;\n } else {\n window.location.href = payload.redirect;\n return null;\n }\n }\n\n return payload.root;\n}\n\nexport function hydrate({\n createFromFetch,\n createFromReadableStream,\n}: {\n createFromFetch: (response: Promise<Response>, options?: object) => Promise<Payload>;\n createFromReadableStream: (\n stream: ReadableStream<Uint8Array>,\n options?: object,\n ) => Promise<Payload>;\n}) {\n createFromReadableStream(rscStream).then(\n (payload) =>\n startTransition(() => {\n hydrateRoot(\n document,\n <StrictMode>\n <Content initialPayload={Promise.resolve(payload)} />\n </StrictMode>,\n {\n formState: payload.formState,\n },\n );\n }),\n (reason) => console.error(\"Failed to hydrate root\", reason),\n );\n\n let navigationController = new AbortController();\n async function navigate(to: string) {\n const url = new URL(to, window.location.href);\n url.pathname += \".rsc\";\n\n const thisController = new AbortController();\n const responses = fetch(url, { signal: thisController.signal }).then((response) => [\n response,\n response.clone(),\n ]);\n\n startTransition(() => setPayload(createFromFetch(responses.then(([r]) => r))));\n navigationController.abort();\n navigationController = thisController;\n\n const [, response] = await responses;\n if (!response.body) return;\n const reader = response.body.getReader();\n try {\n let chunk = await reader.read();\n while (!chunk.done) {\n chunk = await reader.read();\n }\n } finally {\n reader.releaseLock();\n }\n }\n\n window.navigation?.addEventListener(\"navigate\", (event) => {\n if (!event.canIntercept) {\n return;\n }\n\n if (event.hashChange || event.downloadRequest !== null) {\n return;\n }\n\n const url = new URL(event.destination.url);\n\n if (window.location.origin !== url.origin) {\n window.location.href = url.href;\n return;\n }\n\n event.intercept({\n async handler() {\n await navigate(event.destination.url);\n },\n });\n });\n\n if (import.meta.hot) {\n import.meta.hot.on(\"rsc:update\", (e) => {\n console.log(\"[vite-rsc:update]\", e.file);\n void navigate(location.href);\n });\n }\n}\n"],"mappings":"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"}
package/dist/client.d.mts CHANGED
@@ -24,4 +24,5 @@ declare function ClientFrame({
24
24
  }): _$react_jsx_runtime0.JSX.Element;
25
25
  declare function fetchFrame(url: URL, signal: AbortSignal, createFromFetch: (response: Promise<Response>, options?: object) => Promise<Payload>): Promise<string | number | bigint | boolean | Iterable<_$react.ReactNode> | _$react.ReactElement<unknown, string | _$react.JSXElementConstructor<any>> | _$react.ReactPortal | null | undefined>;
26
26
  //#endregion
27
- export { ClientFrame, FetchFrameProvider, fetchFrame, useFrame };
27
+ export { ClientFrame, FetchFrameProvider, fetchFrame, useFrame };
28
+ //# sourceMappingURL=client.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.mts","names":[],"sources":["../src/frames.client.tsx"],"mappings":";;;;;KAKK,KAAA;EACH,OAAA;EACA,MAAA;AAAA;AAAA,iBAUc,kBAAA,CAAA;EACd,QAAA;EACA;AAAA;EAEA,QAAA,EAAU,KAAA,CAAM,SAAA;EAChB,UAAA,IAAc,GAAA,EAAK,GAAA,EAAK,MAAA,EAAQ,WAAA,KAAgB,OAAA,CAAQ,KAAA,CAAM,SAAA;AAAA,IAC/D,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAIe,QAAA,CAAA,GAAQ,KAAA;AAAA,iBAmBR,WAAA,CAAA;EAAc,QAAA;EAAU;AAAA;EAAS,QAAA,GAAW,KAAA,CAAM,SAAA;EAAW,GAAA;AAAA,IAAa,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,iBAuCpE,UAAA,CACpB,GAAA,EAAK,GAAA,EACL,MAAA,EAAQ,WAAA,EACR,eAAA,GAAkB,QAAA,EAAU,OAAA,CAAQ,QAAA,GAAW,OAAA,cAAqB,OAAA,CAAQ,OAAA,IAAQ,OAAA,sCAAA,QAAA,CAAT,OAAA,CAAS,SAAA,IAAA,OAAA,CAAA,YAAA,mBAAA,OAAA,CAAA,qBAAA,SAAA,OAAA,CAAA,WAAA"}
package/dist/client.mjs CHANGED
@@ -62,3 +62,5 @@ async function fetchFrame(url, signal, createFromFetch) {
62
62
  }
63
63
  //#endregion
64
64
  export { ClientFrame, FetchFrameProvider, fetchFrame, useFrame };
65
+
66
+ //# sourceMappingURL=client.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.mjs","names":[],"sources":["../src/frames.client.tsx"],"sourcesContent":["\"use client\";\n\nimport { createContext, use, useCallback, useMemo, useRef, useState, useTransition } from \"react\";\nimport type { Payload } from \"./generic-payload.ts\";\n\ntype Frame = {\n pending: boolean;\n reload: () => void;\n};\n\nconst FrameContext = createContext<undefined | Frame>(undefined);\nFrameContext.displayName = \"FrameContext\";\n\nconst FetchFrameContext = createContext<\n undefined | ((url: URL, signal: AbortSignal) => Promise<React.ReactNode>)\n>(undefined);\n\nexport function FetchFrameProvider({\n children,\n fetchFrame,\n}: {\n children: React.ReactNode;\n fetchFrame?: (url: URL, signal: AbortSignal) => Promise<React.ReactNode>;\n}) {\n return <FetchFrameContext.Provider value={fetchFrame}>{children}</FetchFrameContext.Provider>;\n}\n\nexport function useFrame() {\n let frame = use(FrameContext);\n\n if (!frame) {\n throw new Error(\"useFrame must be used within a Frame / ClientFrame\");\n }\n\n return frame;\n}\n\nfunction isPromise<T>(value: T | Promise<T>): value is Promise<T> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"then\" in value &&\n typeof value.then === \"function\"\n );\n}\n\nexport function ClientFrame({ children, src }: { children?: React.ReactNode; src: string }) {\n const [_content, setContent] = useState<React.ReactNode | Promise<React.ReactNode>>(children);\n const content = isPromise(_content) ? use(_content) : _content;\n\n const [pending, startTransition] = useTransition();\n\n const [lastChildren, setLastChildren] = useState(children);\n if (lastChildren !== children) {\n setLastChildren(children);\n setContent(children);\n }\n\n const controllerRef = useRef<AbortController>(undefined);\n\n const fetchFrame = use(FetchFrameContext);\n\n const reload = useCallback(() => {\n if (!fetchFrame) throw new Error(\"FetchFrameContext is not provided\");\n\n const thisController = new AbortController();\n startTransition(() =>\n setContent(fetchFrame(new URL(src, window.location.href), thisController.signal)),\n );\n controllerRef.current?.abort();\n controllerRef.current = thisController;\n }, [fetchFrame, src]);\n\n const frame = useMemo(() => {\n const result = {\n pending,\n reload,\n };\n\n return result;\n }, [pending, reload]);\n\n return <FrameContext.Provider value={frame}>{content}</FrameContext.Provider>;\n}\n\nexport async function fetchFrame(\n url: URL,\n signal: AbortSignal,\n createFromFetch: (response: Promise<Response>, options?: object) => Promise<Payload>,\n) {\n url.pathname += \".rsc\";\n const payload = await createFromFetch(fetch(url, { signal }));\n if (payload.type === \"redirect\") {\n if (window.navigation) {\n return Promise.resolve(\n window.navigation.navigate(payload.redirect, {\n history: \"replace\",\n }).finished,\n ).then(() => {\n return null as React.ReactNode;\n });\n } else {\n window.location.href = payload.redirect;\n return;\n }\n }\n return payload.root;\n}\n"],"mappings":";;;;AAUA,MAAM,eAAe,cAAiC,KAAA,EAAU;AAChE,aAAa,cAAc;AAE3B,MAAM,oBAAoB,cAExB,KAAA,EAAU;AAEZ,SAAgB,mBAAmB,EACjC,UACA,cAIC;AACD,QAAO,oBAAC,kBAAkB,UAAnB;EAA4B,OAAO;EAAa;EAAsC,CAAA;;AAG/F,SAAgB,WAAW;CACzB,IAAI,QAAQ,IAAI,aAAa;AAE7B,KAAI,CAAC,MACH,OAAM,IAAI,MAAM,qDAAqD;AAGvE,QAAO;;AAGT,SAAS,UAAa,OAA4C;AAChE,QACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,OAAO,MAAM,SAAS;;AAI1B,SAAgB,YAAY,EAAE,UAAU,OAAoD;CAC1F,MAAM,CAAC,UAAU,cAAc,SAAqD,SAAS;CAC7F,MAAM,UAAU,UAAU,SAAS,GAAG,IAAI,SAAS,GAAG;CAEtD,MAAM,CAAC,SAAS,mBAAmB,eAAe;CAElD,MAAM,CAAC,cAAc,mBAAmB,SAAS,SAAS;AAC1D,KAAI,iBAAiB,UAAU;AAC7B,kBAAgB,SAAS;AACzB,aAAW,SAAS;;CAGtB,MAAM,gBAAgB,OAAwB,KAAA,EAAU;CAExD,MAAM,aAAa,IAAI,kBAAkB;CAEzC,MAAM,SAAS,kBAAkB;AAC/B,MAAI,CAAC,WAAY,OAAM,IAAI,MAAM,oCAAoC;EAErE,MAAM,iBAAiB,IAAI,iBAAiB;AAC5C,wBACE,WAAW,WAAW,IAAI,IAAI,KAAK,OAAO,SAAS,KAAK,EAAE,eAAe,OAAO,CAAC,CAClF;AACD,gBAAc,SAAS,OAAO;AAC9B,gBAAc,UAAU;IACvB,CAAC,YAAY,IAAI,CAAC;CAErB,MAAM,QAAQ,cAAc;AAM1B,SALe;GACb;GACA;GACD;IAGA,CAAC,SAAS,OAAO,CAAC;AAErB,QAAO,oBAAC,aAAa,UAAd;EAAuB,OAAO;YAAQ;EAAgC,CAAA;;AAG/E,eAAsB,WACpB,KACA,QACA,iBACA;AACA,KAAI,YAAY;CAChB,MAAM,UAAU,MAAM,gBAAgB,MAAM,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC7D,KAAI,QAAQ,SAAS,WACnB,KAAI,OAAO,WACT,QAAO,QAAQ,QACb,OAAO,WAAW,SAAS,QAAQ,UAAU,EAC3C,SAAS,WACV,CAAC,CAAC,SACJ,CAAC,WAAW;AACX,SAAO;GACP;MACG;AACL,SAAO,SAAS,OAAO,QAAQ;AAC/B;;AAGJ,QAAO,QAAQ"}
@@ -13,4 +13,5 @@ type Payload = {
13
13
  formState?: undefined;
14
14
  };
15
15
  //#endregion
16
- export { Payload as t };
16
+ export { Payload as t };
17
+ //# sourceMappingURL=generic-payload-Bio3B-X_.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generic-payload-Bio3B-X_.d.mts","names":[],"sources":["../src/generic-payload.ts"],"mappings":";;;KAEY,OAAA;EAEN,IAAA;EACA,IAAA,EAAM,KAAA,CAAM,SAAA;EACZ,WAAA,GAAc,OAAA;EACd,SAAA,GAAY,cAAA;AAAA;EAGZ,IAAA;EACA,QAAA;EACA,WAAA,GAAc,OAAA;EACd,SAAA;AAAA"}
package/dist/index.d.mts CHANGED
@@ -15,8 +15,8 @@ declare function mapFrames<Frames extends Routes>(router: Router<any>, frames: F
15
15
  fetchFrame: (url: URL, signal: AbortSignal) => Promise<React.ReactNode>;
16
16
  prerender: (body: ReadableStream<Uint8Array>) => Promise<Response>;
17
17
  renderToReadableStream: (payload: any, options?: {
18
- temporaryReferences: unknown;
19
- onError: (error: unknown) => string | undefined;
18
+ temporaryReferences?: unknown;
19
+ onError?: (error: unknown) => string | undefined;
20
20
  }) => ReadableStream<Uint8Array>;
21
21
  }): void;
22
22
  declare class UseServerState {
@@ -30,6 +30,10 @@ declare class RedirectState {
30
30
  location: string;
31
31
  constructor(location: string);
32
32
  }
33
+ declare function reactRedirectsMiddleware(renderToReadableStream: (payload: any, options?: {
34
+ temporaryReferences?: unknown;
35
+ onError?: (error: unknown) => string | undefined;
36
+ }) => ReadableStream<Uint8Array>): Middleware;
33
37
  declare function useServerMiddleware({
34
38
  createTemporaryReferenceSet,
35
39
  decodeAction,
@@ -43,7 +47,7 @@ declare function useServerMiddleware({
43
47
  decodeReply: (body: string | FormData, options?: object) => Promise<unknown[]>;
44
48
  loadServerAction: (id: string) => Promise<Function>;
45
49
  }): Middleware;
46
- declare function redirect(location: string): void;
50
+ declare function redirect(locationOrRedirect: string | Response): void;
47
51
  declare function render({
48
52
  createTemporaryReferenceSet,
49
53
  prerender,
@@ -64,7 +68,10 @@ declare class NotFoundError extends Error {
64
68
  constructor(message: string);
65
69
  }
66
70
  interface Routes extends Record<string, Route | Routes> {}
67
- type Components<R extends Routes> = { [K in keyof R]: R[K] extends Routes ? Components<R[K]> : React.ComponentType };
71
+ type Components<R extends Routes> = { [K in keyof R]: R[K] extends Routes ? Components<R[K]> : React.ComponentType | {
72
+ middleware?: Middleware[];
73
+ component: React.ComponentType;
74
+ } };
68
75
  type ProvideFramesProps<Frames extends Routes> = {
69
76
  children?: React.ReactNode;
70
77
  components: Components<Frames>;
@@ -83,4 +90,5 @@ declare function Frame({
83
90
  src: string;
84
91
  }): _$react_jsx_runtime0.JSX.Element;
85
92
  //#endregion
86
- export { Frame, NotFoundError, ProvideFrames, ProvideFramesProps, RedirectState, UseServerState, mapFrames, redirect, render, useServerMiddleware };
93
+ export { Frame, NotFoundError, ProvideFrames, ProvideFramesProps, RedirectState, UseServerState, mapFrames, reactRedirectsMiddleware, redirect, render, useServerMiddleware };
94
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/frames.tsx"],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -4,10 +4,10 @@ import { getContext } from "remix/async-context-middleware";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  import "remix/route-pattern";
6
6
  //#region src/frames.tsx
7
- function mapFrames(router, frames, { components, middleware }, config) {
7
+ function mapFrames(router, frames, { components, middleware = [] }, config) {
8
+ const { createTemporaryReferenceSet, fetchFrame, prerender, renderToReadableStream } = config;
8
9
  for (let [key, frame] of Object.entries(frames)) if (typeof frame.pattern?.test === "function") {
9
10
  const handler = ({ request }) => {
10
- const { createTemporaryReferenceSet, fetchFrame, prerender, renderToReadableStream } = config;
11
11
  return render({
12
12
  createTemporaryReferenceSet,
13
13
  prerender,
@@ -21,9 +21,15 @@ function mapFrames(router, frames, { components, middleware }, config) {
21
21
  })
22
22
  });
23
23
  };
24
+ const localMiddleware = typeof components[key] === "function" ? [] : components[key].middleware ?? [];
24
25
  const action = {
26
+ action: handler,
25
27
  handler,
26
- middleware
28
+ middleware: [
29
+ reactRedirectsMiddleware(renderToReadableStream),
30
+ ...middleware,
31
+ ...localMiddleware
32
+ ]
27
33
  };
28
34
  let route = frame.pattern;
29
35
  router.route("GET", route.source, action);
@@ -53,6 +59,17 @@ var RedirectState = class {
53
59
  this.location = location;
54
60
  }
55
61
  };
62
+ function reactRedirectsMiddleware(renderToReadableStream) {
63
+ return async ({ request }, next) => {
64
+ const response = await next();
65
+ const url = new URL(request.url);
66
+ let redirect;
67
+ if (isReactRequest(url) && (redirect = getRedirect(response))) return new Response(renderToReadableStream({
68
+ type: "redirect",
69
+ redirect
70
+ }), { headers: { "Content-Type": "text/x-component; charset=utf-8" } });
71
+ };
72
+ }
56
73
  function useServerMiddleware({ createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, loadServerAction }) {
57
74
  return async ({ request, set }, next) => {
58
75
  let formState;
@@ -82,7 +99,11 @@ function useServerMiddleware({ createTemporaryReferenceSet, decodeAction, decode
82
99
  return next();
83
100
  };
84
101
  }
85
- function redirect(location) {
102
+ function redirect(locationOrRedirect) {
103
+ let location;
104
+ if (typeof locationOrRedirect === "string") location = locationOrRedirect;
105
+ else location = getRedirect(locationOrRedirect);
106
+ if (!location) throw new Error("No redirect location provided");
86
107
  getContext().set(RedirectState, new RedirectState(location));
87
108
  }
88
109
  async function render({ createTemporaryReferenceSet, prerender, renderToReadableStream, request, root }) {
@@ -113,7 +134,7 @@ async function render({ createTemporaryReferenceSet, prerender, renderToReadable
113
134
  console.error(error);
114
135
  }
115
136
  });
116
- if (new URL(request.url).pathname.endsWith(".rsc")) return new Response(body, { headers: { "Content-Type": "text/x-component; charset=utf-8" } });
137
+ if (isReactRequest(new URL(request.url))) return new Response(body, { headers: { "Content-Type": "text/x-component; charset=utf-8" } });
117
138
  return await prerender(body);
118
139
  } catch (reason) {
119
140
  if (reason instanceof Error && reason.name === "NotFoundError") return new Response("Not Found", { status: 404 });
@@ -147,7 +168,7 @@ function Frame({ src }) {
147
168
  const cache = frameCache();
148
169
  if (!cache.components || !cache.frames) throw new Error("No frames provided");
149
170
  const url = new URL(src, "http://react-server-frame/");
150
- if (url.pathname.endsWith(".rsc")) url.pathname = url.pathname.slice(0, -4);
171
+ if (isReactRequest(url)) url.pathname = url.pathname.slice(0, -4);
151
172
  const Component = match(cache.frames, cache.components, url.href);
152
173
  if (!Component) throw new NotFoundError("No matching frame found");
153
174
  return /* @__PURE__ */ jsx(ClientFrame, {
@@ -156,12 +177,20 @@ function Frame({ src }) {
156
177
  });
157
178
  }
158
179
  function match(frames, components, href) {
159
- for (const [id, route] of Object.entries(frames)) if (typeof route.pattern?.test === "function") {
160
- if (route.pattern.test(href)) return components?.[id];
161
- } else {
180
+ for (const [id, route] of Object.entries(frames)) if (typeof route.pattern?.test === "function" && route.pattern.test(href)) return typeof components?.[id] === "object" && components[id].component ? components[id].component : components[id];
181
+ else {
162
182
  let matched = match(route, components?.[id], href);
163
183
  if (matched) return matched;
164
184
  }
165
185
  }
186
+ function isReactRequest(url) {
187
+ return url.pathname.endsWith(".rsc");
188
+ }
189
+ function getRedirect(response) {
190
+ if (response.status < 300 || response.status >= 400) return null;
191
+ return response.headers.get("Location");
192
+ }
166
193
  //#endregion
167
- export { Frame, NotFoundError, ProvideFrames, RedirectState, UseServerState, mapFrames, redirect, render, useServerMiddleware };
194
+ export { Frame, NotFoundError, ProvideFrames, RedirectState, UseServerState, mapFrames, reactRedirectsMiddleware, redirect, render, useServerMiddleware };
195
+
196
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/frames.tsx"],"sourcesContent":["import { cache } from \"react\";\nimport type { ReactFormState } from \"react-dom/client\";\nimport { getContext } from \"remix/async-context-middleware\";\nimport type { Middleware, RequestHandler, Router } from \"remix/fetch-router\";\nimport type { Route } from \"remix/fetch-router/routes\";\n\nimport { ClientFrame, FetchFrameProvider } from \"./frames.client.tsx\";\nimport type { Payload } from \"./generic-payload.ts\";\nimport { RoutePattern } from \"remix/route-pattern\";\n\nexport function mapFrames<Frames extends Routes>(\n router: Router<any>,\n frames: Frames,\n { components, middleware = [] }: { middleware?: Middleware[]; components: Components<Frames> },\n config: {\n createTemporaryReferenceSet: () => unknown;\n fetchFrame: (url: URL, signal: AbortSignal) => Promise<React.ReactNode>;\n prerender: (body: ReadableStream<Uint8Array>) => Promise<Response>;\n renderToReadableStream: (\n payload: any,\n options?: {\n temporaryReferences?: unknown;\n onError?: (error: unknown) => string | undefined;\n },\n ) => ReadableStream<Uint8Array>;\n },\n) {\n const { createTemporaryReferenceSet, fetchFrame, prerender, renderToReadableStream } = config;\n\n for (let [key, frame] of Object.entries(frames)) {\n if (typeof (frame as Route).pattern?.test === \"function\") {\n const handler: RequestHandler = ({ request }) => {\n return render({\n createTemporaryReferenceSet,\n prerender,\n renderToReadableStream,\n request,\n root: (\n <ProvideFrames fetchFrame={fetchFrame} frames={frames} components={components}>\n <Frame src={request.url} />\n </ProvideFrames>\n ),\n });\n };\n\n const localMiddleware =\n typeof components[key] === \"function\"\n ? []\n : ((components[key].middleware ?? []) as Middleware[]);\n\n const action = {\n action: handler,\n handler,\n middleware: [\n reactRedirectsMiddleware(renderToReadableStream),\n ...middleware,\n ...localMiddleware,\n ],\n };\n\n let route = frame.pattern as RoutePattern<string>;\n router.route(\"GET\", route.source, action);\n router.route(\"GET\", route.source + \".rsc\", action);\n router.route(\"POST\", route.source, action);\n router.route(\"POST\", route.source + \".rsc\", action);\n } else {\n mapFrames(\n router,\n frame as Routes,\n { components: components[key] as Components<Routes>, middleware },\n config,\n );\n }\n }\n}\n\nexport class UseServerState {\n formState?: ReactFormState;\n returnValue?: Promise<unknown>;\n temporaryReferences?: unknown;\n status?: number;\n\n constructor(\n formState: ReactFormState | undefined,\n returnValue: Promise<unknown> | undefined,\n temporaryReferences: unknown,\n status: number | undefined,\n ) {\n this.formState = formState;\n this.returnValue = returnValue;\n this.temporaryReferences = temporaryReferences;\n this.status = status;\n }\n}\n\nexport class RedirectState {\n location: string;\n constructor(location: string) {\n this.location = location;\n }\n}\n\nexport function reactRedirectsMiddleware(\n renderToReadableStream: (\n payload: any,\n options?: {\n temporaryReferences?: unknown;\n onError?: (error: unknown) => string | undefined;\n },\n ) => ReadableStream<Uint8Array>,\n): Middleware {\n return async ({ request }, next) => {\n const response = await next();\n const url = new URL(request.url);\n let redirect: string | null;\n if (isReactRequest(url) && (redirect = getRedirect(response))) {\n const payload: Payload = {\n type: \"redirect\",\n redirect,\n };\n return new Response(renderToReadableStream(payload), {\n headers: {\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n },\n });\n }\n };\n}\n\nexport function useServerMiddleware({\n createTemporaryReferenceSet,\n decodeAction,\n decodeFormState,\n decodeReply,\n loadServerAction,\n}: {\n createTemporaryReferenceSet: () => unknown;\n decodeAction: (formData: FormData) => Promise<() => Promise<void>>;\n decodeFormState: (actionResult: unknown, body: FormData) => Promise<ReactFormState | undefined>;\n decodeReply: (body: string | FormData, options?: object) => Promise<unknown[]>;\n loadServerAction: (id: string) => Promise<Function>;\n}): Middleware {\n return async ({ request, set }, next) => {\n let formState: ReactFormState | undefined;\n let returnValue: Promise<unknown> | undefined;\n let temporaryReferences: unknown;\n let actionStatus: number | undefined;\n\n if (request.method === \"POST\") {\n const actionId = request.headers.get(\"x-rsc-action\");\n\n if (actionId) {\n try {\n const contentType = request.headers.get(\"content-type\");\n const body = contentType?.startsWith(\"multipart/form-data\")\n ? await request.formData()\n : await request.text();\n temporaryReferences = createTemporaryReferenceSet();\n const args = await decodeReply(body, { temporaryReferences });\n const action = await loadServerAction(actionId);\n returnValue = action.apply(null, args);\n await returnValue;\n } catch (e) {\n actionStatus = 500;\n returnValue = Promise.reject(e);\n }\n } else {\n try {\n const formData = await request.formData();\n const decodedAction = await decodeAction(formData);\n const result = await decodedAction();\n formState = await decodeFormState(result, formData);\n } catch (e) {\n console.error(e);\n }\n }\n }\n\n set(\n UseServerState,\n new UseServerState(formState, returnValue, temporaryReferences, actionStatus),\n );\n return next();\n };\n}\n\nexport function redirect(locationOrRedirect: string | Response) {\n let location: string | null;\n if (typeof locationOrRedirect === \"string\") {\n location = locationOrRedirect;\n } else {\n location = getRedirect(locationOrRedirect);\n }\n\n if (!location) {\n throw new Error(\"No redirect location provided\");\n }\n\n const ctx = getContext();\n ctx.set(RedirectState, new RedirectState(location));\n}\n\nexport async function render({\n createTemporaryReferenceSet,\n prerender,\n renderToReadableStream,\n request,\n root,\n}: {\n createTemporaryReferenceSet: () => unknown;\n prerender: (body: ReadableStream<Uint8Array>) => Promise<Response>;\n renderToReadableStream: (\n payload: any,\n options?: {\n temporaryReferences: unknown;\n onError: (error: unknown) => string | undefined;\n },\n ) => ReadableStream<Uint8Array>;\n request: Request;\n root: React.ReactNode;\n}) {\n const ctx = getContext();\n let redirect: RedirectState | undefined;\n try {\n redirect = ctx.get(RedirectState);\n } catch {}\n let state: UseServerState | undefined;\n try {\n state = ctx.get(UseServerState);\n } catch {}\n\n try {\n const payload: Payload = redirect\n ? {\n type: \"redirect\",\n redirect: redirect.location,\n returnValue: state?.returnValue,\n }\n : {\n type: \"render\",\n root,\n returnValue: state?.returnValue,\n formState: state?.formState,\n };\n\n const temporaryReferences = state?.temporaryReferences ?? createTemporaryReferenceSet();\n\n const body = renderToReadableStream(payload, {\n temporaryReferences,\n onError(error: unknown) {\n if (error instanceof NotFoundError) {\n return \"404\";\n }\n if (request.signal.aborted) {\n return;\n }\n console.error(error);\n },\n });\n\n const url = new URL(request.url);\n if (isReactRequest(url)) {\n return new Response(body, {\n headers: {\n \"Content-Type\": \"text/x-component; charset=utf-8\",\n },\n });\n }\n\n return await prerender(body);\n } catch (reason) {\n if (reason instanceof Error && reason.name === \"NotFoundError\") {\n return new Response(\"Not Found\", { status: 404 });\n }\n\n if (!request.signal.aborted) {\n console.error(reason);\n }\n\n return new Response(\"Internal Server Error\", { status: 500 });\n }\n}\n\nconst frameCache = cache(\n (): {\n frames?: Record<string, Route>;\n components?: Record<string, React.ComponentType>;\n } => ({}),\n);\n\nexport class NotFoundError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"NotFoundError\";\n }\n}\n\ninterface Routes extends Record<string, Route | Routes> {}\n\ntype Components<R extends Routes> = {\n [K in keyof R]: R[K] extends Routes\n ? Components<R[K]>\n :\n | React.ComponentType\n | {\n middleware?: Middleware[];\n component: React.ComponentType;\n };\n};\n\nexport type ProvideFramesProps<Frames extends Routes> = {\n children?: React.ReactNode;\n components: Components<Frames>;\n fetchFrame: (url: URL, signal: AbortSignal) => Promise<React.ReactNode>;\n frames: Frames;\n};\n\nexport function ProvideFrames<Frames extends Routes>({\n children,\n components,\n fetchFrame,\n frames,\n}: ProvideFramesProps<Frames>) {\n const cache = frameCache();\n\n cache.components = { ...cache.components, ...components };\n cache.frames = { ...cache.frames, ...frames };\n\n return <FetchFrameProvider fetchFrame={fetchFrame}>{children}</FetchFrameProvider>;\n}\n\nexport function Frame({ src }: { src: string }) {\n const cache = frameCache();\n if (!cache.components || !cache.frames) throw new Error(\"No frames provided\");\n\n const url = new URL(src, \"http://react-server-frame/\");\n if (isReactRequest(url)) {\n url.pathname = url.pathname.slice(0, -4);\n }\n\n const Component = match(cache.frames, cache.components, url.href);\n if (!Component) throw new NotFoundError(\"No matching frame found\");\n\n return (\n <ClientFrame src={url.pathname + url.search}>\n <Component />\n </ClientFrame>\n );\n}\n\nfunction match(\n frames: Routes,\n components: Components<Routes>,\n href: string,\n): React.ComponentType | undefined {\n for (const [id, route] of Object.entries(frames)) {\n if (\n typeof (route as Route).pattern?.test === \"function\" &&\n (route as Route).pattern.test(href)\n ) {\n return typeof components?.[id] === \"object\" && components[id].component\n ? components[id].component\n : (components[id] as React.ComponentType);\n } else {\n let matched = match(route as Routes, components?.[id] as unknown as Components<Routes>, href);\n if (matched) return matched;\n }\n }\n}\n\nfunction isReactRequest(url: URL) {\n return url.pathname.endsWith(\".rsc\");\n}\n\nfunction getRedirect(response: Response) {\n if (response.status < 300 || response.status >= 400) return null;\n return response.headers.get(\"Location\");\n}\n"],"mappings":"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"}
@@ -3,4 +3,5 @@ import * as _$react from "react";
3
3
  //#region src/vite/fetch-frame.d.ts
4
4
  declare function fetchFrame(url: URL, signal: AbortSignal): Promise<string | number | bigint | boolean | Iterable<_$react.ReactNode> | _$react.ReactElement<unknown, string | _$react.JSXElementConstructor<any>> | _$react.ReactPortal | null | undefined>;
5
5
  //#endregion
6
- export { fetchFrame };
6
+ export { fetchFrame };
7
+ //# sourceMappingURL=fetch-frame.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-frame.d.mts","names":[],"sources":["../../src/vite/fetch-frame.ts"],"mappings":";;;iBAQsB,UAAA,CAAW,GAAA,EAAK,GAAA,EAAK,MAAA,EAAQ,WAAA,GAAW,OAAA,sCAAA,QAAA,CAAA,OAAA,CAAA,SAAA,IAAA,OAAA,CAAA,YAAA,mBAAA,OAAA,CAAA,qBAAA,SAAA,OAAA,CAAA,WAAA"}
@@ -8,3 +8,5 @@ async function fetchFrame(url, signal) {
8
8
  }
9
9
  //#endregion
10
10
  export { fetchFrame };
11
+
12
+ //# sourceMappingURL=fetch-frame.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-frame.mjs","names":["_fetchFrame"],"sources":["../../src/vite/fetch-frame.ts"],"sourcesContent":["\"use client\";\n\nimport { fetchFrame as _fetchFrame } from \"../frames.client.tsx\";\n\nif (typeof document !== \"undefined\") {\n void import(\"@vitejs/plugin-rsc/browser\");\n}\n\nexport async function fetchFrame(url: URL, signal: AbortSignal) {\n const { createFromFetch } = await import(\"@vitejs/plugin-rsc/browser\");\n return _fetchFrame(url, signal, createFromFetch);\n}\n"],"mappings":";;;AAIA,IAAI,OAAO,aAAa,YACjB,QAAO;AAGd,eAAsB,WAAW,KAAU,QAAqB;CAC9D,MAAM,EAAE,oBAAoB,MAAM,OAAO;AACzC,QAAOA,aAAY,KAAK,QAAQ,gBAAgB"}
@@ -10,4 +10,5 @@ declare function useServerMiddleware(): Middleware;
10
10
  declare function render(request: Request, root: React.ReactNode): Promise<Response>;
11
11
  declare function ProvideFrames(props: Omit<React.ComponentProps<typeof ProvideFrames$1>, "fetchFrame">): _$react_jsx_runtime0.JSX.Element;
12
12
  //#endregion
13
- export { ProvideFrames, mapFrames, render, useServerMiddleware };
13
+ export { ProvideFrames, mapFrames, render, useServerMiddleware };
14
+ //# sourceMappingURL=frames.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.d.mts","names":[],"sources":["../../src/vite/frames.tsx"],"mappings":";;;;;;UAoBU,MAAA,SAAe,MAAA,SAAe,KAAA,GAAQ,MAAA;AAAA,iBAEhC,SAAA,gBAAyB,MAAA,CAAA,CACvC,MAAA,EAAQ,UAAA,QAAkB,WAAA,CAAW,MAAA,OACrC,MAAA,EAAQ,UAAA,QAAkB,WAAA,CAAW,MAAA,OACrC,OAAA,EAAS,UAAA,QAAkB,WAAA,CAAW,MAAA;AAAA,iBAkBxB,mBAAA,CAAA,GAAuB,UAAA;AAAA,iBAUjB,MAAA,CAAO,OAAA,EAAS,OAAA,EAAS,IAAA,EAAM,KAAA,CAAM,SAAA,GAAS,OAAA,CAAA,QAAA;AAAA,iBAiBpD,aAAA,CACd,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,cAAA,QAAsB,eAAA,mBAA8B,oBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -39,3 +39,5 @@ function ProvideFrames(props) {
39
39
  }
40
40
  //#endregion
41
41
  export { ProvideFrames, mapFrames, render, useServerMiddleware };
42
+
43
+ //# sourceMappingURL=frames.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frames.mjs","names":["_mapFrames","_useServerMiddleware","_render","_ProvideFrames"],"sources":["../../src/vite/frames.tsx"],"sourcesContent":["import {\n createTemporaryReferenceSet,\n decodeAction,\n decodeFormState,\n decodeReply,\n loadServerAction,\n renderToReadableStream,\n} from \"@vitejs/plugin-rsc/rsc\";\nimport type { Middleware } from \"remix/fetch-router\";\nimport type { Route } from \"remix/fetch-router/routes\";\n\nimport {\n mapFrames as _mapFrames,\n ProvideFrames as _ProvideFrames,\n render as _render,\n useServerMiddleware as _useServerMiddleware,\n} from \"../frames.tsx\";\n\nimport { fetchFrame } from \"./fetch-frame.ts\";\n\ninterface Routes extends Record<string, Route | Routes> {}\n\nexport function mapFrames<Frames extends Routes>(\n router: Parameters<typeof _mapFrames<Frames>>[0],\n frames: Parameters<typeof _mapFrames<Frames>>[1],\n actions: Parameters<typeof _mapFrames<Frames>>[2],\n) {\n return _mapFrames<Frames>(router, frames, actions, {\n createTemporaryReferenceSet,\n fetchFrame,\n prerender: async (...args) => {\n const ssr = await import.meta.viteRsc.import<typeof import(\"./entry.ssr.tsx\")>(\n \"./entry.ssr.tsx\",\n {\n environment: \"ssr\",\n },\n );\n return ssr.prerender(...args);\n },\n renderToReadableStream,\n });\n}\n\nexport function useServerMiddleware(): Middleware {\n return _useServerMiddleware({\n createTemporaryReferenceSet,\n decodeAction,\n decodeFormState,\n decodeReply,\n loadServerAction,\n });\n}\n\nexport async function render(request: Request, root: React.ReactNode) {\n const ssr = await import.meta.viteRsc.import<typeof import(\"./entry.ssr.tsx\")>(\n \"./entry.ssr.tsx\",\n {\n environment: \"ssr\",\n },\n );\n\n return _render({\n createTemporaryReferenceSet,\n prerender: ssr.prerender,\n renderToReadableStream,\n request,\n root,\n });\n}\n\nexport function ProvideFrames(\n props: Omit<React.ComponentProps<typeof _ProvideFrames>, \"fetchFrame\">,\n) {\n return <_ProvideFrames {...props} fetchFrame={fetchFrame} />;\n}\n"],"mappings":";;;;;AAsBA,SAAgB,UACd,QACA,QACA,SACA;AACA,QAAOA,YAAmB,QAAQ,QAAQ,SAAS;EACjD;EACA;EACA,WAAW,OAAO,GAAG,SAAS;AAO5B,WANY,MAAM,OAAO,KAAK,QAAQ,OACpC,mBACA,EACE,aAAa,OACd,CACF,EACU,UAAU,GAAG,KAAK;;EAE/B;EACD,CAAC;;AAGJ,SAAgB,sBAAkC;AAChD,QAAOC,sBAAqB;EAC1B;EACA;EACA;EACA;EACA;EACD,CAAC;;AAGJ,eAAsB,OAAO,SAAkB,MAAuB;AAQpE,QAAOC,SAAQ;EACb;EACA,YATU,MAAM,OAAO,KAAK,QAAQ,OACpC,mBACA,EACE,aAAa,OACd,CACF,EAIgB;EACf;EACA;EACA;EACD,CAAC;;AAGJ,SAAgB,cACd,OACA;AACA,QAAO,oBAACC,iBAAD;EAAgB,GAAI;EAAmB;EAAc,CAAA"}
@@ -10,4 +10,5 @@ declare function reactServerFrame({
10
10
  config(this: Vite.ConfigPluginContext, userConfig: Vite.UserConfig): Record<string, any>;
11
11
  };
12
12
  //#endregion
13
- export { reactServerFrame };
13
+ export { reactServerFrame };
14
+ //# sourceMappingURL=plugin.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.mts","names":[],"sources":["../../src/vite/plugin.ts"],"mappings":";;;iBASgB,gBAAA,CAAA;EAAmB;AAAA;EAAiC,KAAA;AAAA"}
@@ -19,3 +19,5 @@ function reactServerFrame({ entry = "/src/entry.server" } = {}) {
19
19
  }
20
20
  //#endregion
21
21
  export { reactServerFrame };
22
+
23
+ //# sourceMappingURL=plugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../../src/vite/plugin.ts"],"sourcesContent":["import * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport * as Vite from \"vite\";\n\nfunction getEntry(file: string) {\n return Vite.normalizePath(path.join(path.dirname(fileURLToPath(import.meta.url)), file));\n}\n\nexport function reactServerFrame({ entry = \"/src/entry.server\" }: { entry?: string } = {}) {\n return {\n name: \"framework\",\n config(userConfig) {\n return Vite.mergeConfig(\n {\n environments: {\n client: {\n build: {\n rolldownOptions: {\n input: {\n index: getEntry(\"entry.client.tsx\"),\n },\n },\n },\n },\n rsc: {\n build: {\n rolldownOptions: {\n input: {\n index: entry,\n },\n },\n },\n },\n ssr: {\n build: {\n rolldownOptions: {\n input: {\n index: getEntry(\"entry.ssr.tsx\"),\n },\n },\n },\n },\n },\n } satisfies Vite.UserConfig,\n userConfig,\n true,\n );\n },\n } satisfies Vite.Plugin;\n}\n"],"mappings":";;;;AAKA,SAAS,SAAS,MAAc;AAC9B,QAAO,KAAK,cAAc,KAAK,KAAK,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC,EAAE,KAAK,CAAC;;AAG1F,SAAgB,iBAAiB,EAAE,QAAQ,wBAA4C,EAAE,EAAE;AACzF,QAAO;EACL,MAAM;EACN,OAAO,YAAY;AACjB,UAAO,KAAK,YACV,EACE,cAAc;IACZ,QAAQ,EACN,OAAO,EACL,iBAAiB,EACf,OAAO,EACL,OAAO,SAAS,mBAAmB,EACpC,EACF,EACF,EACF;IACD,KAAK,EACH,OAAO,EACL,iBAAiB,EACf,OAAO,EACL,OAAO,OACR,EACF,EACF,EACF;IACD,KAAK,EACH,OAAO,EACL,iBAAiB,EACf,OAAO,EACL,OAAO,SAAS,gBAAgB,EACjC,EACF,EACF,EACF;IACF,EACF,EACD,YACA,KACD;;EAEJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-server-frame",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "A new type of RSC routing.",
5
5
  "homepage": "https://github.com/jacob-ebey/react-server-frame#readme",
6
6
  "bugs": {
@@ -43,7 +43,7 @@
43
43
  "react": "canary",
44
44
  "react-dom": "canary",
45
45
  "react-server-dom-webpack": "canary",
46
- "remix": "3.0.0-alpha.4",
46
+ "remix": "remix-run/remix#preview/main&path:packages/remix",
47
47
  "typescript": "^6.0.2",
48
48
  "vite": "npm:@voidzero-dev/vite-plus-core@latest",
49
49
  "vite-plus": "latest"