react-server-frame 0.0.5 → 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,10 +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 = {
25
26
  action: handler,
26
27
  handler,
27
- middleware
28
+ middleware: [
29
+ reactRedirectsMiddleware(renderToReadableStream),
30
+ ...middleware,
31
+ ...localMiddleware
32
+ ]
28
33
  };
29
34
  let route = frame.pattern;
30
35
  router.route("GET", route.source, action);
@@ -54,6 +59,17 @@ var RedirectState = class {
54
59
  this.location = location;
55
60
  }
56
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
+ }
57
73
  function useServerMiddleware({ createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, loadServerAction }) {
58
74
  return async ({ request, set }, next) => {
59
75
  let formState;
@@ -83,7 +99,11 @@ function useServerMiddleware({ createTemporaryReferenceSet, decodeAction, decode
83
99
  return next();
84
100
  };
85
101
  }
86
- 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");
87
107
  getContext().set(RedirectState, new RedirectState(location));
88
108
  }
89
109
  async function render({ createTemporaryReferenceSet, prerender, renderToReadableStream, request, root }) {
@@ -114,7 +134,7 @@ async function render({ createTemporaryReferenceSet, prerender, renderToReadable
114
134
  console.error(error);
115
135
  }
116
136
  });
117
- 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" } });
118
138
  return await prerender(body);
119
139
  } catch (reason) {
120
140
  if (reason instanceof Error && reason.name === "NotFoundError") return new Response("Not Found", { status: 404 });
@@ -148,7 +168,7 @@ function Frame({ src }) {
148
168
  const cache = frameCache();
149
169
  if (!cache.components || !cache.frames) throw new Error("No frames provided");
150
170
  const url = new URL(src, "http://react-server-frame/");
151
- if (url.pathname.endsWith(".rsc")) url.pathname = url.pathname.slice(0, -4);
171
+ if (isReactRequest(url)) url.pathname = url.pathname.slice(0, -4);
152
172
  const Component = match(cache.frames, cache.components, url.href);
153
173
  if (!Component) throw new NotFoundError("No matching frame found");
154
174
  return /* @__PURE__ */ jsx(ClientFrame, {
@@ -157,12 +177,20 @@ function Frame({ src }) {
157
177
  });
158
178
  }
159
179
  function match(frames, components, href) {
160
- for (const [id, route] of Object.entries(frames)) if (typeof route.pattern?.test === "function") {
161
- if (route.pattern.test(href)) return components?.[id];
162
- } 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 {
163
182
  let matched = match(route, components?.[id], href);
164
183
  if (matched) return matched;
165
184
  }
166
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
+ }
167
193
  //#endregion
168
- 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":";;;;;;AAUA,SAAgB,UACd,QACA,QACA,EAAE,YAAY,aAAa,EAAE,IAC7B,QAYA;CACA,MAAM,EAAE,6BAA6B,YAAY,WAAW,2BAA2B;AAEvF,MAAK,IAAI,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,CAC7C,KAAI,OAAQ,MAAgB,SAAS,SAAS,YAAY;EACxD,MAAM,WAA2B,EAAE,cAAc;AAC/C,UAAO,OAAO;IACZ;IACA;IACA;IACA;IACA,MACE,oBAAC,eAAD;KAA2B;KAAoB;KAAoB;eACjE,oBAAC,OAAD,EAAO,KAAK,QAAQ,KAAO,CAAA;KACb,CAAA;IAEnB,CAAC;;EAGJ,MAAM,kBACJ,OAAO,WAAW,SAAS,aACvB,EAAE,GACA,WAAW,KAAK,cAAc,EAAE;EAExC,MAAM,SAAS;GACb,QAAQ;GACR;GACA,YAAY;IACV,yBAAyB,uBAAuB;IAChD,GAAG;IACH,GAAG;IACJ;GACF;EAED,IAAI,QAAQ,MAAM;AAClB,SAAO,MAAM,OAAO,MAAM,QAAQ,OAAO;AACzC,SAAO,MAAM,OAAO,MAAM,SAAS,QAAQ,OAAO;AAClD,SAAO,MAAM,QAAQ,MAAM,QAAQ,OAAO;AAC1C,SAAO,MAAM,QAAQ,MAAM,SAAS,QAAQ,OAAO;OAEnD,WACE,QACA,OACA;EAAE,YAAY,WAAW;EAA4B;EAAY,EACjE,OACD;;AAKP,IAAa,iBAAb,MAA4B;CAC1B;CACA;CACA;CACA;CAEA,YACE,WACA,aACA,qBACA,QACA;AACA,OAAK,YAAY;AACjB,OAAK,cAAc;AACnB,OAAK,sBAAsB;AAC3B,OAAK,SAAS;;;AAIlB,IAAa,gBAAb,MAA2B;CACzB;CACA,YAAY,UAAkB;AAC5B,OAAK,WAAW;;;AAIpB,SAAgB,yBACd,wBAOY;AACZ,QAAO,OAAO,EAAE,WAAW,SAAS;EAClC,MAAM,WAAW,MAAM,MAAM;EAC7B,MAAM,MAAM,IAAI,IAAI,QAAQ,IAAI;EAChC,IAAI;AACJ,MAAI,eAAe,IAAI,KAAK,WAAW,YAAY,SAAS,EAK1D,QAAO,IAAI,SAAS,uBAJK;GACvB,MAAM;GACN;GACD,CACkD,EAAE,EACnD,SAAS,EACP,gBAAgB,mCACjB,EACF,CAAC;;;AAKR,SAAgB,oBAAoB,EAClC,6BACA,cACA,iBACA,aACA,oBAOa;AACb,QAAO,OAAO,EAAE,SAAS,OAAO,SAAS;EACvC,IAAI;EACJ,IAAI;EACJ,IAAI;EACJ,IAAI;AAEJ,MAAI,QAAQ,WAAW,QAAQ;GAC7B,MAAM,WAAW,QAAQ,QAAQ,IAAI,eAAe;AAEpD,OAAI,SACF,KAAI;IAEF,MAAM,OADc,QAAQ,QAAQ,IAAI,eAAe,EAC7B,WAAW,sBAAsB,GACvD,MAAM,QAAQ,UAAU,GACxB,MAAM,QAAQ,MAAM;AACxB,0BAAsB,6BAA6B;IACnD,MAAM,OAAO,MAAM,YAAY,MAAM,EAAE,qBAAqB,CAAC;AAE7D,mBADe,MAAM,iBAAiB,SAAS,EAC1B,MAAM,MAAM,KAAK;AACtC,UAAM;YACC,GAAG;AACV,mBAAe;AACf,kBAAc,QAAQ,OAAO,EAAE;;OAGjC,KAAI;IACF,MAAM,WAAW,MAAM,QAAQ,UAAU;AAGzC,gBAAY,MAAM,gBADH,OADO,MAAM,aAAa,SAAS,GACd,EACM,SAAS;YAC5C,GAAG;AACV,YAAQ,MAAM,EAAE;;;AAKtB,MACE,gBACA,IAAI,eAAe,WAAW,aAAa,qBAAqB,aAAa,CAC9E;AACD,SAAO,MAAM;;;AAIjB,SAAgB,SAAS,oBAAuC;CAC9D,IAAI;AACJ,KAAI,OAAO,uBAAuB,SAChC,YAAW;KAEX,YAAW,YAAY,mBAAmB;AAG5C,KAAI,CAAC,SACH,OAAM,IAAI,MAAM,gCAAgC;AAGtC,aAAY,CACpB,IAAI,eAAe,IAAI,cAAc,SAAS,CAAC;;AAGrD,eAAsB,OAAO,EAC3B,6BACA,WACA,wBACA,SACA,QAaC;CACD,MAAM,MAAM,YAAY;CACxB,IAAI;AACJ,KAAI;AACF,aAAW,IAAI,IAAI,cAAc;SAC3B;CACR,IAAI;AACJ,KAAI;AACF,UAAQ,IAAI,IAAI,eAAe;SACzB;AAER,KAAI;EAgBF,MAAM,OAAO,uBAfY,WACrB;GACE,MAAM;GACN,UAAU,SAAS;GACnB,aAAa,OAAO;GACrB,GACD;GACE,MAAM;GACN;GACA,aAAa,OAAO;GACpB,WAAW,OAAO;GACnB,EAIwC;GAC3C,qBAH0B,OAAO,uBAAuB,6BAA6B;GAIrF,QAAQ,OAAgB;AACtB,QAAI,iBAAiB,cACnB,QAAO;AAET,QAAI,QAAQ,OAAO,QACjB;AAEF,YAAQ,MAAM,MAAM;;GAEvB,CAAC;AAGF,MAAI,eADQ,IAAI,IAAI,QAAQ,IAAI,CACT,CACrB,QAAO,IAAI,SAAS,MAAM,EACxB,SAAS,EACP,gBAAgB,mCACjB,EACF,CAAC;AAGJ,SAAO,MAAM,UAAU,KAAK;UACrB,QAAQ;AACf,MAAI,kBAAkB,SAAS,OAAO,SAAS,gBAC7C,QAAO,IAAI,SAAS,aAAa,EAAE,QAAQ,KAAK,CAAC;AAGnD,MAAI,CAAC,QAAQ,OAAO,QAClB,SAAQ,MAAM,OAAO;AAGvB,SAAO,IAAI,SAAS,yBAAyB,EAAE,QAAQ,KAAK,CAAC;;;AAIjE,MAAM,aAAa,aAIX,EAAE,EACT;AAED,IAAa,gBAAb,cAAmC,MAAM;CACvC,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO;;;AAwBhB,SAAgB,cAAqC,EACnD,UACA,YACA,YACA,UAC6B;CAC7B,MAAM,QAAQ,YAAY;AAE1B,OAAM,aAAa;EAAE,GAAG,MAAM;EAAY,GAAG;EAAY;AACzD,OAAM,SAAS;EAAE,GAAG,MAAM;EAAQ,GAAG;EAAQ;AAE7C,QAAO,oBAAC,oBAAD;EAAgC;EAAa;EAA8B,CAAA;;AAGpF,SAAgB,MAAM,EAAE,OAAwB;CAC9C,MAAM,QAAQ,YAAY;AAC1B,KAAI,CAAC,MAAM,cAAc,CAAC,MAAM,OAAQ,OAAM,IAAI,MAAM,qBAAqB;CAE7E,MAAM,MAAM,IAAI,IAAI,KAAK,6BAA6B;AACtD,KAAI,eAAe,IAAI,CACrB,KAAI,WAAW,IAAI,SAAS,MAAM,GAAG,GAAG;CAG1C,MAAM,YAAY,MAAM,MAAM,QAAQ,MAAM,YAAY,IAAI,KAAK;AACjE,KAAI,CAAC,UAAW,OAAM,IAAI,cAAc,0BAA0B;AAElE,QACE,oBAAC,aAAD;EAAa,KAAK,IAAI,WAAW,IAAI;YACnC,oBAAC,WAAD,EAAa,CAAA;EACD,CAAA;;AAIlB,SAAS,MACP,QACA,YACA,MACiC;AACjC,MAAK,MAAM,CAAC,IAAI,UAAU,OAAO,QAAQ,OAAO,CAC9C,KACE,OAAQ,MAAgB,SAAS,SAAS,cACzC,MAAgB,QAAQ,KAAK,KAAK,CAEnC,QAAO,OAAO,aAAa,QAAQ,YAAY,WAAW,IAAI,YAC1D,WAAW,IAAI,YACd,WAAW;MACX;EACL,IAAI,UAAU,MAAM,OAAiB,aAAa,KAAsC,KAAK;AAC7F,MAAI,QAAS,QAAO;;;AAK1B,SAAS,eAAe,KAAU;AAChC,QAAO,IAAI,SAAS,SAAS,OAAO;;AAGtC,SAAS,YAAY,UAAoB;AACvC,KAAI,SAAS,SAAS,OAAO,SAAS,UAAU,IAAK,QAAO;AAC5D,QAAO,SAAS,QAAQ,IAAI,WAAW"}
@@ -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.5",
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"