rwsdk 0.1.0-alpha.8 โ†’ 0.1.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.
Files changed (89) hide show
  1. package/dist/runtime/client.d.ts +3 -1
  2. package/dist/runtime/client.js +16 -13
  3. package/dist/runtime/clientNavigation.d.ts +3 -0
  4. package/dist/runtime/clientNavigation.js +43 -0
  5. package/dist/runtime/entries/client.d.ts +1 -0
  6. package/dist/runtime/entries/client.js +1 -0
  7. package/dist/runtime/entries/worker.d.ts +2 -0
  8. package/dist/runtime/entries/worker.js +2 -0
  9. package/dist/runtime/imports/ClientOnly.d.ts +3 -0
  10. package/dist/runtime/imports/ClientOnly.js +8 -0
  11. package/dist/runtime/imports/NoSSRStub.d.ts +1 -0
  12. package/dist/runtime/imports/NoSSRStub.js +4 -0
  13. package/dist/runtime/imports/client.js +15 -2
  14. package/dist/runtime/imports/worker.d.ts +1 -1
  15. package/dist/runtime/imports/worker.js +7 -5
  16. package/dist/runtime/lib/db/DOWorkerDialect.d.ts +29 -0
  17. package/dist/runtime/lib/db/DOWorkerDialect.js +66 -0
  18. package/dist/runtime/lib/db/SqliteDurableObject.d.ts +14 -0
  19. package/dist/runtime/lib/db/SqliteDurableObject.js +42 -0
  20. package/dist/runtime/lib/db/create.d.ts +3 -0
  21. package/dist/runtime/lib/db/create.js +36 -0
  22. package/dist/runtime/lib/db/createDb.d.ts +2 -0
  23. package/dist/runtime/lib/db/createDb.js +27 -0
  24. package/dist/runtime/lib/db/index.d.ts +3 -0
  25. package/dist/runtime/lib/db/index.js +3 -0
  26. package/dist/runtime/lib/db/logger.d.ts +2 -0
  27. package/dist/runtime/lib/db/logger.js +41 -0
  28. package/dist/runtime/lib/db/migrations.d.ts +23 -0
  29. package/dist/runtime/lib/db/migrations.js +34 -0
  30. package/dist/runtime/lib/db/types.d.ts +0 -0
  31. package/dist/runtime/lib/db/types.js +1 -0
  32. package/dist/runtime/lib/debug.d.ts +2 -0
  33. package/dist/runtime/lib/debug.js +36 -0
  34. package/dist/runtime/lib/realtime/worker.d.ts +1 -1
  35. package/dist/runtime/lib/router.d.ts +31 -26
  36. package/dist/runtime/lib/router.js +9 -2
  37. package/dist/runtime/register/ssr.d.ts +2 -0
  38. package/dist/runtime/register/ssr.js +14 -1
  39. package/dist/runtime/register/worker.d.ts +1 -1
  40. package/dist/runtime/register/worker.js +5 -2
  41. package/dist/runtime/render/renderRscThenableToHtmlStream.d.ts +2 -1
  42. package/dist/runtime/render/renderRscThenableToHtmlStream.js +17 -3
  43. package/dist/runtime/render/renderToStream.d.ts +9 -0
  44. package/dist/runtime/render/renderToStream.js +26 -0
  45. package/dist/runtime/render/renderToString.d.ts +7 -0
  46. package/dist/runtime/render/renderToString.js +26 -0
  47. package/dist/runtime/render/transformRscToHtmlStream.js +1 -0
  48. package/dist/runtime/worker.d.ts +2 -1
  49. package/dist/runtime/worker.js +21 -14
  50. package/dist/scripts/debug-sync.mjs +8 -6
  51. package/dist/scripts/worker-run.mjs +1 -0
  52. package/dist/vite/configPlugin.mjs +8 -17
  53. package/dist/vite/createDirectiveLookupPlugin.d.mts +1 -0
  54. package/dist/vite/createDirectiveLookupPlugin.mjs +88 -49
  55. package/dist/vite/devServerTimingPlugin.d.mts +2 -0
  56. package/dist/vite/devServerTimingPlugin.mjs +24 -0
  57. package/dist/vite/directivesPlugin.mjs +168 -70
  58. package/dist/vite/findImportSpecifiers.d.mts +16 -0
  59. package/dist/vite/findImportSpecifiers.mjs +152 -0
  60. package/dist/vite/findImportSpecifiers.test.d.mts +1 -0
  61. package/dist/vite/findImportSpecifiers.test.mjs +73 -0
  62. package/dist/vite/findSpecifiers.d.mts +31 -0
  63. package/dist/vite/findSpecifiers.mjs +230 -0
  64. package/dist/vite/hasDirective.d.mts +7 -0
  65. package/dist/vite/hasDirective.mjs +54 -0
  66. package/dist/vite/hasOwnCloudflareVitePlugin.d.mts +3 -0
  67. package/dist/vite/hasOwnCloudflareVitePlugin.mjs +14 -0
  68. package/dist/vite/invalidateModule.d.mts +2 -0
  69. package/dist/vite/invalidateModule.mjs +14 -0
  70. package/dist/vite/miniflareHMRPlugin.d.mts +8 -0
  71. package/dist/vite/miniflareHMRPlugin.mjs +133 -0
  72. package/dist/vite/normalizeModulePath.mjs +12 -1
  73. package/dist/vite/redwoodPlugin.d.mts +1 -0
  74. package/dist/vite/redwoodPlugin.mjs +19 -4
  75. package/dist/vite/resolveModuleId.d.mts +6 -0
  76. package/dist/vite/resolveModuleId.mjs +14 -0
  77. package/dist/vite/ssrBridgePlugin.d.mts +5 -1
  78. package/dist/vite/ssrBridgePlugin.mjs +4 -43
  79. package/dist/vite/transformClientComponents.d.mts +1 -0
  80. package/dist/vite/transformClientComponents.mjs +61 -125
  81. package/dist/vite/transformJsxScriptTagsPlugin.mjs +14 -3
  82. package/dist/vite/transformServerFunctions.d.mts +11 -3
  83. package/dist/vite/transformServerFunctions.mjs +256 -171
  84. package/dist/vite/transformServerFunctions.test.mjs +22 -3
  85. package/dist/vite/useClientLookupPlugin.mjs +1 -0
  86. package/dist/vite/useServerLookupPlugin.mjs +1 -0
  87. package/dist/vite/useServerPlugin.d.mts +1 -1
  88. package/dist/vite/useServerPlugin.mjs +1 -1
  89. package/package.json +14 -3
@@ -1,51 +1,56 @@
1
1
  import React from "react";
2
2
  import { RequestInfo } from "../requestInfo/types";
3
- export type DocumentProps = RequestInfo & {
3
+ import type { Kysely } from "kysely";
4
+ export type DocumentProps<T extends RequestInfo = RequestInfo> = T & {
4
5
  children: React.ReactNode;
5
6
  };
6
- export type LayoutProps = {
7
+ export type LayoutProps<T extends RequestInfo = RequestInfo> = {
7
8
  children?: React.ReactNode;
8
- requestInfo?: RequestInfo;
9
+ requestInfo?: T;
9
10
  };
10
11
  export type RwContext = {
11
12
  nonce: string;
12
- Document: React.FC<DocumentProps>;
13
+ Document: React.FC<DocumentProps<any>>;
13
14
  rscPayload: boolean;
14
- layouts?: React.FC<LayoutProps>[];
15
+ ssr: boolean;
16
+ layouts?: React.FC<LayoutProps<any>>[];
17
+ databases: Map<string, Kysely<any>>;
15
18
  };
16
- export type RouteMiddleware = (requestInfo: RequestInfo) => Response | Promise<Response> | void | Promise<void> | Promise<Response | void>;
17
- type RouteFunction = (requestInfo: RequestInfo) => Response | Promise<Response>;
19
+ export type RouteMiddleware<T extends RequestInfo = RequestInfo> = (requestInfo: T) => Response | Promise<Response> | void | Promise<void> | Promise<Response | void>;
20
+ type RouteFunction<T extends RequestInfo = RequestInfo> = (requestInfo: T) => Response | Promise<Response>;
18
21
  type MaybePromise<T> = T | Promise<T>;
19
- type RouteComponent = (requestInfo: RequestInfo) => MaybePromise<React.JSX.Element | Response>;
20
- type RouteHandler = RouteFunction | RouteComponent | [...RouteMiddleware[], RouteFunction | RouteComponent];
21
- export type Route = RouteMiddleware | RouteDefinition | Array<Route>;
22
- export type RouteDefinition = {
22
+ type RouteComponent<T extends RequestInfo = RequestInfo> = (requestInfo: T) => MaybePromise<React.JSX.Element | Response>;
23
+ type RouteHandler<T extends RequestInfo = RequestInfo> = RouteFunction<T> | RouteComponent<T> | [...RouteMiddleware<T>[], RouteFunction<T> | RouteComponent<T>];
24
+ export type Route<T extends RequestInfo = RequestInfo> = RouteMiddleware<T> | RouteDefinition<T> | Array<Route<T>>;
25
+ export type RouteDefinition<T extends RequestInfo = RequestInfo> = {
23
26
  path: string;
24
- handler: RouteHandler;
25
- layouts?: React.FC<LayoutProps>[];
27
+ handler: RouteHandler<T>;
28
+ layouts?: React.FC<LayoutProps<T>>[];
26
29
  };
27
- export declare function matchPath(routePath: string, requestPath: string): RequestInfo["params"] | null;
28
- export declare function defineRoutes(routes: Route[]): {
29
- routes: Route[];
30
+ export declare function matchPath<T extends RequestInfo = RequestInfo>(routePath: string, requestPath: string): T["params"] | null;
31
+ export declare function defineRoutes<T extends RequestInfo = RequestInfo>(routes: Route<T>[]): {
32
+ routes: Route<T>[];
30
33
  handle: ({ request, renderPage, getRequestInfo, onError, runWithRequestInfoOverrides, }: {
31
34
  request: Request;
32
- renderPage: (requestInfo: RequestInfo, Page: React.FC, onError: (error: unknown) => void) => Promise<Response>;
33
- getRequestInfo: () => RequestInfo;
35
+ renderPage: (requestInfo: T, Page: React.FC, onError: (error: unknown) => void) => Promise<Response>;
36
+ getRequestInfo: () => T;
34
37
  onError: (error: unknown) => void;
35
- runWithRequestInfoOverrides: <Result>(overrides: Partial<RequestInfo>, fn: () => Promise<Result>) => Promise<Result>;
38
+ runWithRequestInfoOverrides: <Result>(overrides: Partial<T>, fn: () => Promise<Result>) => Promise<Result>;
36
39
  }) => Response | Promise<Response>;
37
40
  };
38
- export declare function route(path: string, handler: RouteHandler): RouteDefinition;
39
- export declare function index(handler: RouteHandler): RouteDefinition;
40
- export declare function prefix(prefixPath: string, routes: Route[]): Route[];
41
- export declare function layout(LayoutComponent: React.FC<LayoutProps>, routes: Route[]): Route[];
42
- export declare function render(Document: React.FC<DocumentProps>, routes: Route[],
41
+ export declare function route<T extends RequestInfo = RequestInfo>(path: string, handler: RouteHandler<T>): RouteDefinition<T>;
42
+ export declare function index<T extends RequestInfo = RequestInfo>(handler: RouteHandler<T>): RouteDefinition<T>;
43
+ export declare function prefix<T extends RequestInfo = RequestInfo>(prefixPath: string, routes: Route<T>[]): Route<T>[];
44
+ export declare function layout<T extends RequestInfo = RequestInfo>(LayoutComponent: React.FC<LayoutProps<T>>, routes: Route<T>[]): Route<T>[];
45
+ export declare function render<T extends RequestInfo = RequestInfo>(Document: React.FC<DocumentProps<T>>, routes: Route<T>[],
43
46
  /**
44
47
  * @param options - Configuration options for rendering.
45
48
  * @param options.rscPayload - Toggle the RSC payload that's appended to the Document. Disabling this will mean that interactivity no longer works.
49
+ * @param options.ssr - Disable sever side rendering for all these routes. This only allow client side rendering`, which requires `rscPayload` to be enabled.
46
50
  */
47
51
  options?: {
48
- rscPayload: boolean;
49
- }): Route[];
52
+ rscPayload?: boolean;
53
+ ssr?: boolean;
54
+ }): Route<T>[];
50
55
  export declare const isClientReference: (Component: React.FC<any>) => boolean;
51
56
  export {};
@@ -186,11 +186,18 @@ export function render(Document, routes,
186
186
  /**
187
187
  * @param options - Configuration options for rendering.
188
188
  * @param options.rscPayload - Toggle the RSC payload that's appended to the Document. Disabling this will mean that interactivity no longer works.
189
+ * @param options.ssr - Disable sever side rendering for all these routes. This only allow client side rendering`, which requires `rscPayload` to be enabled.
189
190
  */
190
- options = { rscPayload: true }) {
191
+ options = {}) {
192
+ options = {
193
+ rscPayload: true,
194
+ ssr: true,
195
+ ...options,
196
+ };
191
197
  const documentMiddleware = ({ rw }) => {
192
198
  rw.Document = Document;
193
- rw.rscPayload = options.rscPayload;
199
+ rw.rscPayload = options.rscPayload ?? true;
200
+ rw.ssr = options.ssr ?? true;
194
201
  };
195
202
  return [documentMiddleware, ...routes];
196
203
  }
@@ -1 +1,3 @@
1
+ export declare const loadServerModule: ((id: string) => Promise<any>) & import("lodash").MemoizedFunction;
2
+ export declare const getServerModuleExport: (id: string) => Promise<any>;
1
3
  export declare const createServerReference: (id: string, name: string) => any;
@@ -1,5 +1,18 @@
1
+ import memoize from "lodash/memoize";
1
2
  import { createServerReference as baseCreateServerReference } from "react-server-dom-webpack/client.edge";
2
- import { getServerModuleExport } from "../imports/worker.js";
3
+ export const loadServerModule = memoize(async (id) => {
4
+ const { useServerLookup } = await import("virtual:use-server-lookup");
5
+ const moduleFn = useServerLookup[id];
6
+ if (!moduleFn) {
7
+ throw new Error(`(worker) No module found for '${id}' in module lookup for "use server" directive`);
8
+ }
9
+ return await moduleFn();
10
+ });
11
+ export const getServerModuleExport = async (id) => {
12
+ const [file, name] = id.split("#");
13
+ const module = await loadServerModule(file);
14
+ return module[name];
15
+ };
3
16
  const ssrCallServer = async (id, args) => {
4
17
  const action = await getServerModuleExport(id);
5
18
  if (typeof action !== "function") {
@@ -1,4 +1,4 @@
1
1
  export declare function registerServerReference(action: Function, id: string, name: string): Function;
2
- export declare function registerClientReference<Target extends Record<string, any>>(id: string, exportName: string): () => null;
2
+ export declare function registerClientReference<Target extends Record<string, any>>(id: string, exportName: string, value: any): any;
3
3
  export declare function __smokeTestActionHandler(timestamp?: number): Promise<unknown>;
4
4
  export declare function rscActionHandler(req: Request): Promise<unknown>;
@@ -8,9 +8,12 @@ export function registerServerReference(action, id, name) {
8
8
  // Note: We no longer need to register in a Map since we use virtual lookup
9
9
  return baseRegisterServerReference(action, id, name);
10
10
  }
11
- export function registerClientReference(id, exportName) {
11
+ export function registerClientReference(id, exportName, value) {
12
+ const wrappedValue = (value && typeof value === "function") || typeof value === "object"
13
+ ? value
14
+ : () => null;
12
15
  const reference = baseRegisterClientReference({}, id, exportName);
13
- return Object.defineProperties(() => null, {
16
+ return Object.defineProperties(wrappedValue, {
14
17
  ...Object.getOwnPropertyDescriptors(reference),
15
18
  $$async: { value: true },
16
19
  $$isClientReference: { value: true },
@@ -1,7 +1,8 @@
1
1
  import { type DocumentProps } from "../lib/router";
2
2
  import { type RequestInfo } from "../requestInfo/types";
3
- export declare const renderRscThenableToHtmlStream: ({ thenable, Document, requestInfo, }: {
3
+ export declare const renderRscThenableToHtmlStream: ({ thenable, Document, requestInfo, shouldSSR, }: {
4
4
  thenable: any;
5
5
  Document: React.FC<DocumentProps>;
6
6
  requestInfo: RequestInfo;
7
+ shouldSSR: boolean;
7
8
  }) => Promise<import("react-dom/server").ReactDOMServerReadableStream>;
@@ -1,9 +1,23 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { use } from "react";
3
3
  import { renderToReadableStream } from "react-dom/server.edge";
4
- export const renderRscThenableToHtmlStream = async ({ thenable, Document, requestInfo, }) => {
4
+ export const renderRscThenableToHtmlStream = async ({ thenable, Document, requestInfo, shouldSSR, }) => {
5
5
  const Component = () => {
6
- return (_jsx(Document, { ...requestInfo, children: use(thenable).node }));
6
+ const node = use(thenable).node;
7
+ // todo(justinvdm, 18 Jun 2025): We can build on this later to allow users
8
+ // surface context. e.g:
9
+ // * we assign `user: requestInfo.clientCtx` here
10
+ // * user populates requestInfo.clientCtx on worker side
11
+ // * user can import a read only `import { clientCtx } from "rwsdk/client"`
12
+ // on client side
13
+ const clientContext = {
14
+ rw: {
15
+ ssr: shouldSSR,
16
+ },
17
+ };
18
+ return (_jsxs(Document, { ...requestInfo, children: [_jsx("script", { nonce: requestInfo.rw.nonce, dangerouslySetInnerHTML: {
19
+ __html: `globalThis.__RWSDK_CONTEXT = ${JSON.stringify(clientContext)}`,
20
+ } }), _jsx("div", { id: "hydrate-root", children: node })] }));
7
21
  };
8
22
  return await renderToReadableStream(_jsx(Component, {}), {
9
23
  nonce: requestInfo.rw.nonce,
@@ -0,0 +1,9 @@
1
+ import { ReactElement, FC } from "react";
2
+ import { DocumentProps } from "../lib/router";
3
+ export interface RenderToStreamOptions {
4
+ Document?: FC<DocumentProps>;
5
+ injectRSCPayload?: boolean;
6
+ onError?: (error: unknown) => void;
7
+ }
8
+ export declare const IdentityDocument: FC<DocumentProps>;
9
+ export declare const renderToStream: (element: ReactElement, { Document, injectRSCPayload: shouldInjectRSCPayload, onError, }?: RenderToStreamOptions) => Promise<ReadableStream>;
@@ -0,0 +1,26 @@
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { renderToRscStream } from "./renderToRscStream";
3
+ import { transformRscToHtmlStream } from "./transformRscToHtmlStream";
4
+ import { requestInfo } from "../requestInfo/worker";
5
+ import { injectRSCPayload } from "rsc-html-stream/server";
6
+ export const IdentityDocument = ({ children }) => (_jsx(_Fragment, { children: children }));
7
+ export const renderToStream = async (element, { Document = IdentityDocument, injectRSCPayload: shouldInjectRSCPayload = false, onError, } = {}) => {
8
+ let rscStream = renderToRscStream({
9
+ node: element,
10
+ actionResult: null,
11
+ onError,
12
+ });
13
+ if (shouldInjectRSCPayload) {
14
+ const [rscPayloadStream1, rscPayloadStream2] = rscStream.tee();
15
+ rscStream = rscPayloadStream1;
16
+ rscStream = rscStream.pipeThrough(injectRSCPayload(rscPayloadStream2, {
17
+ nonce: requestInfo.rw.nonce,
18
+ }));
19
+ }
20
+ const htmlStream = await transformRscToHtmlStream({
21
+ stream: rscStream,
22
+ Document,
23
+ requestInfo,
24
+ });
25
+ return htmlStream;
26
+ };
@@ -0,0 +1,7 @@
1
+ import { FC, ReactElement } from "react";
2
+ import { DocumentProps } from "../lib/router";
3
+ export interface RenderToStringOptions {
4
+ Document?: FC<DocumentProps>;
5
+ injectRSCPayload?: boolean;
6
+ }
7
+ export declare const renderToString: (element: ReactElement, options?: RenderToStringOptions) => Promise<string>;
@@ -0,0 +1,26 @@
1
+ import { renderToStream } from "./renderToStream";
2
+ export const renderToString = async (element, options) => {
3
+ const stream = await new Promise((resolve, reject) => renderToStream(element, {
4
+ ...options,
5
+ onError: reject,
6
+ })
7
+ .then(resolve)
8
+ .catch(reject));
9
+ const reader = stream.getReader();
10
+ const decoder = new TextDecoder();
11
+ let result = "";
12
+ try {
13
+ while (true) {
14
+ const { done, value } = await reader.read();
15
+ if (done)
16
+ break;
17
+ result += decoder.decode(value, { stream: true });
18
+ }
19
+ // Flush any remaining bytes
20
+ result += decoder.decode();
21
+ return result;
22
+ }
23
+ finally {
24
+ reader.releaseLock();
25
+ }
26
+ };
@@ -13,5 +13,6 @@ export const transformRscToHtmlStream = ({ stream, Document, requestInfo, }) =>
13
13
  thenable,
14
14
  Document,
15
15
  requestInfo,
16
+ shouldSSR: requestInfo.rw.ssr,
16
17
  });
17
18
  };
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+ import { RequestInfo, DefaultAppContext } from "./requestInfo/types";
2
3
  import { Route } from "./lib/router";
3
4
  declare global {
4
5
  type Env = {
@@ -6,7 +7,7 @@ declare global {
6
7
  DB: D1Database;
7
8
  };
8
9
  }
9
- export declare const defineApp: (routes: Route[]) => {
10
+ export declare const defineApp: <T extends RequestInfo = RequestInfo<any, DefaultAppContext>>(routes: Route<T>[]) => {
10
11
  fetch: (request: Request, env: Env, cf: ExecutionContext) => Promise<Response>;
11
12
  };
12
13
  export declare const SmokeTestWrapper: React.FC<{
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { transformRscToHtmlStream } from "./render/transformRscToHtmlStream";
3
3
  import { renderToRscStream } from "./render/renderToRscStream";
4
- import { ssrWebpackRequire } from "rwsdk/__ssr_bridge";
5
4
  import { rscActionHandler } from "./register/worker";
6
5
  import { injectRSCPayload } from "rsc-html-stream/server";
7
6
  import { ErrorResponse } from "./error";
@@ -9,6 +8,7 @@ import { getRequestInfo, runWithRequestInfo, runWithRequestInfoOverrides, } from
9
8
  import { defineRoutes } from "./lib/router";
10
9
  import { generateNonce } from "./lib/utils";
11
10
  import { IS_DEV } from "./constants";
11
+ import { ssrWebpackRequire } from "./imports/worker";
12
12
  export const defineApp = (routes) => {
13
13
  return {
14
14
  fetch: async (request, env, cf) => {
@@ -31,13 +31,16 @@ export const defineApp = (routes) => {
31
31
  }
32
32
  try {
33
33
  const url = new URL(request.url);
34
- const isRSCRequest = url.searchParams.has("__rsc");
34
+ const isRSCRequest = url.searchParams.has("__rsc") ||
35
+ request.headers.get("accept")?.includes("text/x-component");
35
36
  const isSmokeTest = url.searchParams.has("__smoke_test");
36
37
  const userHeaders = new Headers();
37
38
  const rw = {
38
39
  Document: DefaultDocument,
39
40
  nonce: generateNonce(),
40
41
  rscPayload: true,
42
+ ssr: true,
43
+ databases: new Map(),
41
44
  };
42
45
  const outerRequestInfo = {
43
46
  request,
@@ -50,8 +53,7 @@ export const defineApp = (routes) => {
50
53
  const createPageElement = (requestInfo, Page) => {
51
54
  let pageElement;
52
55
  if (isClientReference(Page)) {
53
- const { ctx, params } = requestInfo;
54
- // context(justinvdm, 25 Feb 2025): If the page is a client reference, we need to avoid passing
56
+ const { ctx, params } = requestInfo; // context(justinvdm, 25 Feb 2025): If the page is a client reference, we need to avoid passing
55
57
  // down props the client shouldn't get (e.g. env). For safety, we pick the allowed props explicitly.
56
58
  pageElement = _jsx(Page, { ctx: ctx, params: params });
57
59
  }
@@ -87,7 +89,8 @@ export const defineApp = (routes) => {
87
89
  actionResult = await rscActionHandler(request);
88
90
  }
89
91
  const pageElement = createPageElement(requestInfo, Page);
90
- const rscPayloadStream = renderToRscStream({
92
+ const { rscPayload: shouldInjectRSCPayload } = rw;
93
+ let rscPayloadStream = renderToRscStream({
91
94
  node: pageElement,
92
95
  actionResult: actionResult instanceof Response ? null : actionResult,
93
96
  onError,
@@ -99,17 +102,21 @@ export const defineApp = (routes) => {
99
102
  },
100
103
  });
101
104
  }
102
- const [rscPayloadStream1, rscPayloadStream2] = rscPayloadStream.tee();
103
- const htmlStream = await transformRscToHtmlStream({
104
- stream: rscPayloadStream1,
105
+ let injectRSCPayloadStream;
106
+ if (shouldInjectRSCPayload) {
107
+ const [rscPayloadStream1, rscPayloadStream2] = rscPayloadStream.tee();
108
+ rscPayloadStream = rscPayloadStream1;
109
+ injectRSCPayloadStream = injectRSCPayload(rscPayloadStream2, {
110
+ nonce: rw.nonce,
111
+ });
112
+ }
113
+ let html = await transformRscToHtmlStream({
114
+ stream: rscPayloadStream,
105
115
  Document: rw.Document,
106
116
  requestInfo: requestInfo,
107
117
  });
108
- let html = htmlStream;
109
- if (rw.rscPayload) {
110
- html = htmlStream.pipeThrough(injectRSCPayload(rscPayloadStream2, {
111
- nonce: rw.nonce,
112
- }));
118
+ if (injectRSCPayloadStream) {
119
+ html = html.pipeThrough(injectRSCPayloadStream);
113
120
  }
114
121
  return new Response(html, {
115
122
  headers: {
@@ -122,7 +129,7 @@ export const defineApp = (routes) => {
122
129
  resolve(await router.handle({
123
130
  request,
124
131
  renderPage,
125
- getRequestInfo,
132
+ getRequestInfo: getRequestInfo,
126
133
  runWithRequestInfoOverrides,
127
134
  onError: reject,
128
135
  }));
@@ -8,12 +8,14 @@ export const debugSync = async (opts) => {
8
8
  const syncCommand = `echo ๐Ÿ—๏ธ rebuilding... && pnpm build && rm -rf ${targetDir}/node_modules/rwsdk/dist ${targetDir}/node_modules/rwsdk/package.json && echo ๐Ÿ“ syncing sdk from ${process.cwd()} to ${targetDir}/node_modules/rwsdk/... && cp -r package.json dist ${targetDir}/node_modules/rwsdk/ && echo โœ… done syncing`;
9
9
  // Run initial sync
10
10
  await $({ stdio: "inherit", shell: true }) `${syncCommand}`;
11
- console.log("๐Ÿงน Cleaning Vite cache...");
12
- await $({
13
- stdio: "inherit",
14
- shell: true,
15
- cwd: targetDir,
16
- }) `npm run clean:vite`;
11
+ if (!process.env.NO_CLEAN_VITE) {
12
+ console.log("๐Ÿงน Cleaning Vite cache...");
13
+ await $({
14
+ stdio: "inherit",
15
+ shell: true,
16
+ cwd: targetDir,
17
+ }) `rm -rf node_modules/.vite`;
18
+ }
17
19
  // If dev flag is present, clean vite cache and start dev server
18
20
  if (dev) {
19
21
  console.log("๐Ÿš€ Starting dev server...");
@@ -41,6 +41,7 @@ export const runWorkerScript = async (relativeScriptPath) => {
41
41
  plugins: [
42
42
  redwood({
43
43
  configPath: tmpWorkerPath.path,
44
+ includeCloudflarePlugin: true,
44
45
  entry: {
45
46
  worker: scriptPath,
46
47
  },
@@ -49,6 +49,7 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
49
49
  },
50
50
  optimizeDeps: {
51
51
  noDiscovery: false,
52
+ include: ["rwsdk/client"],
52
53
  esbuildOptions: {
53
54
  jsx: "automatic",
54
55
  jsxImportSource: "react",
@@ -58,23 +59,13 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
58
59
  },
59
60
  },
60
61
  },
62
+ resolve: {
63
+ conditions: ["browser", "module"],
64
+ },
61
65
  },
62
66
  ssr: {
63
67
  resolve: {
64
- conditions: [
65
- "workerd",
66
- // context(justinvdm, 11 Jun 2025): Some packages meant for cloudflare workers, yet
67
- // their deps have only node import conditions, e.g. `agents` package (meant for CF),
68
- // has `pkce-challenge` package as a dep, which has only node import conditions.
69
- // https://github.com/crouchcd/pkce-challenge/blob/master/package.json#L17
70
- //
71
- // Once the transformed code for this environment is in turn processed in the `worker` environment,
72
- // @cloudflare/vite-plugin should take care of any relevant polyfills for deps with
73
- // node builtins imports that can be polyfilled though, so it is worth us including this condition here.
74
- // However, it does mean we will try to run packages meant for node that cannot be run on cloudflare workers.
75
- // That's the trade-off, but arguably worth it. (context(justinvdm, 11 Jun 2025))
76
- "node",
77
- ],
68
+ conditions: ["workerd", "module", "browser"],
78
69
  noExternal: true,
79
70
  },
80
71
  define: {
@@ -84,11 +75,10 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
84
75
  noDiscovery: false,
85
76
  entries: [workerEntryPathname],
86
77
  exclude: externalModules,
87
- include: ["rwsdk/__ssr_bridge"],
78
+ include: ["rwsdk/__ssr", "rwsdk/__ssr_bridge"],
88
79
  esbuildOptions: {
89
80
  jsx: "automatic",
90
81
  jsxImportSource: "react",
91
- conditions: ["workerd"],
92
82
  plugins: [],
93
83
  },
94
84
  },
@@ -108,6 +98,7 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
108
98
  conditions: [
109
99
  "workerd",
110
100
  "react-server",
101
+ "module",
111
102
  // context(justinvdm, 11 Jun 2025): Some packages meant for cloudflare workers, yet
112
103
  // their deps have only node import conditions, e.g. `agents` package (meant for CF),
113
104
  // has `pkce-challenge` package as a dep, which has only node import conditions.
@@ -126,7 +117,7 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
126
117
  },
127
118
  optimizeDeps: {
128
119
  noDiscovery: false,
129
- include: [],
120
+ include: ["rwsdk/worker"],
130
121
  exclude: [],
131
122
  entries: [workerEntryPathname],
132
123
  esbuildOptions: {
@@ -1,5 +1,6 @@
1
1
  import { Plugin } from "vite";
2
2
  interface DirectiveLookupConfig {
3
+ kind: "client" | "server";
3
4
  directive: "use client" | "use server";
4
5
  virtualModuleName: string;
5
6
  exportName: string;