rwsdk 0.0.84 → 0.0.85-test.20250528024240

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 (50) hide show
  1. package/dist/runtime/entries/no-react-server.d.ts +0 -0
  2. package/dist/runtime/entries/no-react-server.js +2 -0
  3. package/dist/runtime/entries/ssr.d.ts +1 -0
  4. package/dist/runtime/entries/ssr.js +1 -0
  5. package/dist/runtime/imports/ssr.d.ts +5 -0
  6. package/dist/runtime/imports/ssr.js +20 -0
  7. package/dist/runtime/register/ssr.d.ts +2 -0
  8. package/dist/runtime/register/ssr.js +13 -0
  9. package/dist/runtime/register/worker.js +4 -2
  10. package/dist/runtime/render/renderRscThenableToHtmlStream.d.ts +9 -0
  11. package/dist/runtime/render/renderRscThenableToHtmlStream.js +13 -0
  12. package/dist/runtime/render/transformRscToHtmlStream.d.ts +5 -5
  13. package/dist/runtime/render/transformRscToHtmlStream.js +8 -9
  14. package/dist/runtime/ssrBridge.d.ts +3 -0
  15. package/dist/runtime/ssrBridge.js +11 -0
  16. package/dist/runtime/worker.js +4 -4
  17. package/dist/vite/checkIsUsingPrisma.d.mts +5 -2
  18. package/dist/vite/checkIsUsingPrisma.mjs +11 -2
  19. package/dist/vite/configPlugin.d.mts +1 -2
  20. package/dist/vite/configPlugin.mjs +23 -31
  21. package/dist/vite/ensureAliasArray.d.mts +2 -0
  22. package/dist/vite/ensureAliasArray.mjs +11 -0
  23. package/dist/vite/moveStaticAssetsPlugin.mjs +1 -2
  24. package/dist/vite/prismaPlugin.d.mts +4 -0
  25. package/dist/vite/prismaPlugin.mjs +43 -0
  26. package/dist/vite/reactConditionsResolverPlugin.d.mts +17 -5
  27. package/dist/vite/reactConditionsResolverPlugin.mjs +83 -146
  28. package/dist/vite/redwoodPlugin.mjs +8 -23
  29. package/dist/vite/rscDirectivesPlugin.d.mts +4 -0
  30. package/dist/vite/rscDirectivesPlugin.mjs +88 -0
  31. package/dist/vite/ssrBridgePlugin.d.mts +6 -0
  32. package/dist/vite/ssrBridgePlugin.mjs +104 -0
  33. package/dist/vite/transformClientComponents.d.mts +7 -7
  34. package/dist/vite/transformClientComponents.mjs +58 -50
  35. package/dist/vite/transformClientComponents.test.d.mts +1 -0
  36. package/dist/vite/transformClientComponents.test.mjs +257 -0
  37. package/dist/vite/transformServerFunctions.d.mts +8 -0
  38. package/dist/vite/transformServerFunctions.mjs +216 -0
  39. package/dist/vite/transformServerFunctions.test.d.mts +1 -0
  40. package/dist/vite/transformServerFunctions.test.mjs +105 -0
  41. package/dist/vite/useClientLookupPlugin.d.mts +7 -7
  42. package/dist/vite/useClientLookupPlugin.mjs +11 -19
  43. package/dist/vite/useClientPlugin.d.mts +3 -7
  44. package/dist/vite/useClientPlugin.mjs +11 -294
  45. package/dist/vite/useClientPlugin.test.mjs +9 -4
  46. package/dist/vite/useServerPlugin.d.mts +1 -5
  47. package/dist/vite/useServerPlugin.mjs +1 -144
  48. package/dist/vite/wasmPlugin.d.mts +2 -0
  49. package/dist/vite/wasmPlugin.mjs +14 -0
  50. package/package.json +18 -8
File without changes
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ throw new Error("rwsdk: 'react-server' is not supported in this environment");
@@ -0,0 +1 @@
1
+ export * from "../register/ssr";
@@ -0,0 +1 @@
1
+ export * from "../register/ssr";
@@ -0,0 +1,5 @@
1
+ export declare const ssrLoadModule: ((id: string) => Promise<any>) & import("lodash").MemoizedFunction;
2
+ export declare const ssrGetModuleExport: (id: string) => Promise<any>;
3
+ export declare const ssrWebpackRequire: ((id: string) => Promise<{
4
+ [x: string]: any;
5
+ }>) & import("lodash").MemoizedFunction;
@@ -0,0 +1,20 @@
1
+ import memoize from "lodash/memoize";
2
+ export const ssrLoadModule = memoize(async (id) => {
3
+ const { useClientLookup } = await import("virtual:use-client-lookup");
4
+ const moduleFn = useClientLookup[id];
5
+ if (!moduleFn) {
6
+ throw new Error(`No module found for '${id}' in module lookup for "use client" directive`);
7
+ }
8
+ return await moduleFn();
9
+ });
10
+ export const ssrGetModuleExport = async (id) => {
11
+ const [file, name] = id.split("#");
12
+ const module = await ssrLoadModule(file);
13
+ return module[name];
14
+ };
15
+ // context(justinvdm, 2 Dec 2024): re memoize(): React relies on the same promise instance being returned for the same id
16
+ export const ssrWebpackRequire = memoize(async (id) => {
17
+ const [file, name] = id.split("#");
18
+ const module = await ssrLoadModule(file);
19
+ return { [id]: module[name] };
20
+ });
@@ -0,0 +1,2 @@
1
+ export declare const createServerReference: (id: string, name: string) => any;
2
+ export declare const registeredServerFunctions: Map<string, Function>;
@@ -0,0 +1,13 @@
1
+ import { createServerReference as baseCreateServerReference } from "react-server-dom-webpack/client.edge";
2
+ const ssrCallServer = (id, args) => {
3
+ const action = registeredServerFunctions.get(id);
4
+ if (!action) {
5
+ throw new Error(`Server function ${id} not found`);
6
+ }
7
+ return action(args);
8
+ };
9
+ export const createServerReference = (id, name) => {
10
+ id = id + "#" + name;
11
+ return baseCreateServerReference(id, ssrCallServer);
12
+ };
13
+ export const registeredServerFunctions = new Map();
@@ -1,10 +1,12 @@
1
1
  import { registerServerReference as baseRegisterServerReference, registerClientReference as baseRegisterClientReference, decodeReply, } from "react-server-dom-webpack/server.edge";
2
- import { getModuleExport } from "../imports/worker";
2
+ import { ssrGetModuleExport } from "rwsdk/__ssr_bridge";
3
3
  import { IS_DEV } from "../constants";
4
+ import { registeredServerFunctions } from "../ssrBridge";
4
5
  export function registerServerReference(action, id, name) {
5
6
  if (typeof action !== "function") {
6
7
  return action;
7
8
  }
9
+ registeredServerFunctions.set(id, action);
8
10
  return baseRegisterServerReference(action, id, name);
9
11
  }
10
12
  export function registerClientReference(id, exportName, target) {
@@ -30,7 +32,7 @@ export async function rscActionHandler(req) {
30
32
  if (IS_DEV && actionId === "__rsc_hot_update") {
31
33
  return null;
32
34
  }
33
- const action = await getModuleExport(actionId);
35
+ const action = await ssrGetModuleExport(actionId);
34
36
  if (typeof action !== "function") {
35
37
  throw new Error(`Action ${actionId} is not a function`);
36
38
  }
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import ReactServerDom from "react-dom/server.edge";
3
+ import { type DocumentProps } from "../lib/router";
4
+ import { type RequestInfo } from "../requestInfo/types";
5
+ export declare const renderRscThenableToHtmlStream: ({ thenable, Document, requestInfo, }: {
6
+ thenable: any;
7
+ Document: React.FC<DocumentProps>;
8
+ requestInfo: RequestInfo;
9
+ }) => Promise<ReactServerDom.ReactDOMServerReadableStream>;
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import ReactServerDom from "react-dom/server.edge";
4
+ const { use } = React;
5
+ const { renderToReadableStream } = ReactServerDom;
6
+ export const renderRscThenableToHtmlStream = async ({ thenable, Document, requestInfo, }) => {
7
+ const Component = () => {
8
+ return (_jsx(Document, { ...requestInfo, children: use(thenable).node }));
9
+ };
10
+ return await renderToReadableStream(_jsx(Component, {}), {
11
+ nonce: requestInfo.rw.nonce,
12
+ });
13
+ };
@@ -1,7 +1,7 @@
1
- export declare const transformRscToHtmlStream: ({ stream, Parent, nonce, }: {
1
+ import { DocumentProps } from "../lib/router";
2
+ import { RequestInfo } from "../requestInfo/types";
3
+ export declare const transformRscToHtmlStream: ({ stream, Document, requestInfo, }: {
2
4
  stream: ReadableStream;
3
- Parent: React.ComponentType<{
4
- children: React.ReactNode;
5
- }>;
6
- nonce?: string;
5
+ Document: React.FC<DocumentProps>;
6
+ requestInfo: RequestInfo;
7
7
  }) => Promise<import("react-dom/server.js").ReactDOMServerReadableStream>;
@@ -1,18 +1,17 @@
1
- import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
1
  import { createModuleMap } from "./createModuleMap.js";
3
- import { createFromReadableStream } from "react-server-dom-webpack/client.edge";
4
- import { use } from "react";
5
- import { renderToReadableStream } from "react-dom/server.edge";
6
- export const transformRscToHtmlStream = ({ stream, Parent = ({ children }) => _jsx(_Fragment, { children: children }), nonce, }) => {
2
+ import ReactServerDom from "react-server-dom-webpack/client.edge";
3
+ import { renderRscThenableToHtmlStream } from "../ssrBridge.js";
4
+ const { createFromReadableStream } = ReactServerDom;
5
+ export const transformRscToHtmlStream = ({ stream, Document, requestInfo, }) => {
7
6
  const thenable = createFromReadableStream(stream, {
8
7
  serverConsumerManifest: {
9
8
  moduleMap: createModuleMap(),
10
9
  moduleLoading: null,
11
10
  },
12
11
  });
13
- const Component = () => (_jsx(Parent, { children: use(thenable).node }));
14
- const el = _jsx(Component, {});
15
- return renderToReadableStream(el, {
16
- nonce,
12
+ return renderRscThenableToHtmlStream({
13
+ thenable,
14
+ Document,
15
+ requestInfo,
17
16
  });
18
17
  };
@@ -0,0 +1,3 @@
1
+ export { renderRscThenableToHtmlStream } from "./render/renderRscThenableToHtmlStream";
2
+ export { registeredServerFunctions } from "./register/ssr";
3
+ export { ssrLoadModule, ssrGetModuleExport, ssrWebpackRequire, } from "./imports/ssr";
@@ -0,0 +1,11 @@
1
+ // context(justinvdm, 28 May 2025): This is the "bridge" between the RSC side
2
+ // and and the SSR side, both run inside the same runtime environment. We have
3
+ // this separation so that they can each be processed with their own respective
4
+ // import conditions and bundling logic
5
+ //
6
+ // **NOTE:** Any time we need to import from SSR side in RSC side, we need to
7
+ // import it through this bridge file. We have bundler logic (ssrBridgePlugin)
8
+ // that looks out for imports to this exact file.
9
+ export { renderRscThenableToHtmlStream } from "./render/renderRscThenableToHtmlStream";
10
+ export { registeredServerFunctions } from "./register/ssr";
11
+ export { ssrLoadModule, ssrGetModuleExport, ssrWebpackRequire, } from "./imports/ssr";
@@ -1,7 +1,7 @@
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 { loadModule, ssrWebpackRequire } from "./imports/worker";
4
+ import { ssrLoadModule, ssrWebpackRequire } from "rwsdk/__ssr_bridge";
5
5
  import { rscActionHandler } from "./register/worker";
6
6
  import { injectRSCPayload } from "rsc-html-stream/server";
7
7
  import { ErrorResponse } from "./error";
@@ -102,8 +102,8 @@ export const defineApp = (routes) => {
102
102
  const [rscPayloadStream1, rscPayloadStream2] = rscPayloadStream.tee();
103
103
  const htmlStream = await transformRscToHtmlStream({
104
104
  stream: rscPayloadStream1,
105
- Parent: ({ children }) => (_jsx(rw.Document, { ...requestInfo, children: children })),
106
- nonce: rw.nonce,
105
+ Document: rw.Document,
106
+ requestInfo: requestInfo,
107
107
  });
108
108
  let html = htmlStream;
109
109
  if (rw.rscPayload) {
@@ -155,7 +155,7 @@ export const defineApp = (routes) => {
155
155
  };
156
156
  };
157
157
  export const SmokeTestWrapper = async ({ children }) => {
158
- const smokeTestInfo = await loadModule("/src/app/components/__SmokeTest.tsx");
158
+ const smokeTestInfo = await ssrLoadModule("/src/app/components/__SmokeTest.tsx");
159
159
  const SmokeTestInfo = smokeTestInfo.SmokeTestInfo;
160
160
  return (_jsxs(_Fragment, { children: [_jsx(SmokeTestInfo, {}), children] }));
161
161
  };
@@ -1,3 +1,6 @@
1
- export declare const checkIsUsingPrisma: ({ projectRootDir, }: {
1
+ export type PrismaCheckResult = {
2
+ isUsingPrisma: boolean;
3
+ };
4
+ export declare const checkPrismaStatus: ({ projectRootDir, }: {
2
5
  projectRootDir: string;
3
- }) => boolean;
6
+ }) => PrismaCheckResult;
@@ -1,9 +1,18 @@
1
1
  import enhancedResolve from "enhanced-resolve";
2
- export const checkIsUsingPrisma = ({ projectRootDir, }) => {
2
+ const isUsingPrisma = ({ projectRootDir }) => {
3
3
  try {
4
- return Boolean(enhancedResolve.sync(projectRootDir, "@prisma/client"));
4
+ const prismaClientPath = enhancedResolve.sync(projectRootDir, "@prisma/client");
5
+ if (!prismaClientPath) {
6
+ return false;
7
+ }
8
+ return true;
5
9
  }
6
10
  catch {
7
11
  return false;
8
12
  }
9
13
  };
14
+ export const checkPrismaStatus = ({ projectRootDir, }) => {
15
+ return {
16
+ isUsingPrisma: isUsingPrisma({ projectRootDir }),
17
+ };
18
+ };
@@ -1,9 +1,8 @@
1
1
  import { Plugin } from "vite";
2
- export declare const configPlugin: ({ mode, silent, projectRootDir, clientEntryPathname, workerEntryPathname, isUsingPrisma, }: {
2
+ export declare const configPlugin: ({ mode, silent, projectRootDir, clientEntryPathname, workerEntryPathname, }: {
3
3
  mode: "development" | "production";
4
4
  silent: boolean;
5
5
  projectRootDir: string;
6
6
  clientEntryPathname: string;
7
7
  workerEntryPathname: string;
8
- isUsingPrisma: boolean;
9
8
  }) => Plugin;
@@ -8,7 +8,7 @@ const ignoreVirtualModules = {
8
8
  });
9
9
  },
10
10
  };
11
- export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname, workerEntryPathname, isUsingPrisma, }) => ({
11
+ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname, workerEntryPathname, }) => ({
12
12
  name: "rwsdk:config",
13
13
  config: (_, { command }) => {
14
14
  const baseConfig = {
@@ -38,6 +38,9 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
38
38
  noDiscovery: false,
39
39
  esbuildOptions: {
40
40
  plugins: [ignoreVirtualModules],
41
+ define: {
42
+ "process.env.NODE_ENV": JSON.stringify(mode),
43
+ },
41
44
  },
42
45
  },
43
46
  },
@@ -50,30 +53,10 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
50
53
  noDiscovery: false,
51
54
  esbuildOptions: {
52
55
  conditions: ["workerd", "react-server"],
53
- plugins: [
54
- ...(isUsingPrisma
55
- ? [
56
- {
57
- name: "rwsdk:prisma-client-wasm",
58
- setup(build) {
59
- build.onResolve({ filter: /.prisma\/client\/default/ }, async (args) => {
60
- return {
61
- path: resolve(projectRootDir, "node_modules/.prisma/client/wasm.js"),
62
- };
63
- });
64
- },
65
- },
66
- ]
67
- : []),
68
- ignoreVirtualModules,
69
- ],
56
+ plugins: [ignoreVirtualModules],
70
57
  },
71
- include: [
72
- "react/jsx-runtime",
73
- "react/jsx-dev-runtime",
74
- "react-server-dom-webpack/client.edge",
75
- "react-server-dom-webpack/server.edge",
76
- ],
58
+ include: [],
59
+ exclude: [],
77
60
  },
78
61
  build: {
79
62
  outDir: resolve(projectRootDir, "dist", "worker"),
@@ -95,12 +78,21 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
95
78
  },
96
79
  resolve: {
97
80
  conditions: ["workerd"],
98
- alias: {
99
- ...(isUsingPrisma
100
- ? {
101
- ".prisma/client/default": resolve(projectRootDir, "node_modules/.prisma/client/wasm.js"),
102
- }
103
- : {}),
81
+ alias: [],
82
+ },
83
+ builder: {
84
+ buildApp: async (builder) => {
85
+ // note(justinvdm, 27 May 2025): **Ordering is important**:
86
+ // * When building, client needs to be build first, so that we have a
87
+ // manifest file to map to when looking at asset references in JSX
88
+ // (e.g. Document.tsx)
89
+ // * When bundling, the RSC build imports the SSR build - this way
90
+ // they each can have their own environments (e.g. with their own
91
+ // import conditions), while still having all worker-run code go
92
+ // through the processing done by `@cloudflare/vite-plugin`
93
+ await builder.build(builder.environments["client"]);
94
+ await builder.build(builder.environments["ssr"]);
95
+ await builder.build(builder.environments["rsc"]);
104
96
  },
105
97
  },
106
98
  };
@@ -110,7 +102,7 @@ export const configPlugin = ({ mode, silent, projectRootDir, clientEntryPathname
110
102
  worker: {
111
103
  build: {
112
104
  rollupOptions: {
113
- external: ["cloudflare:workers", "node:stream", /\.wasm$/],
105
+ external: ["cloudflare:workers", "node:stream"],
114
106
  },
115
107
  },
116
108
  },
@@ -0,0 +1,2 @@
1
+ import type { Alias, UserConfig } from "vite";
2
+ export declare const ensureAliasArray: (config: UserConfig) => Alias[];
@@ -0,0 +1,11 @@
1
+ export const ensureAliasArray = (config) => {
2
+ config.resolve ??= {};
3
+ if (!config.resolve?.alias) {
4
+ config.resolve.alias = [];
5
+ }
6
+ else if (!Array.isArray(config.resolve.alias)) {
7
+ const existingAlias = config.resolve.alias;
8
+ config.resolve.alias = Object.entries(existingAlias).map(([find, replacement]) => ({ find, replacement }));
9
+ }
10
+ return config.resolve.alias;
11
+ };
@@ -6,8 +6,7 @@ export const moveStaticAssetsPlugin = ({ rootDir, }) => ({
6
6
  if (this.environment.name === "worker") {
7
7
  await $sh({
8
8
  cwd: rootDir,
9
- }) `mv dist/worker/assets/* dist/client/assets || true`;
10
- await $sh({ cwd: rootDir }) `rmdir dist/worker/assets || true`;
9
+ }) `mv dist/worker/assets/*.css dist/client/assets/ || true`;
11
10
  }
12
11
  },
13
12
  });
@@ -0,0 +1,4 @@
1
+ import { Plugin } from "vite";
2
+ export declare const prismaPlugin: ({ projectRootDir, }: {
3
+ projectRootDir: string;
4
+ }) => Promise<Plugin | undefined>;
@@ -0,0 +1,43 @@
1
+ import { resolve } from "node:path";
2
+ import { invalidateCacheIfPrismaClientChanged } from "./invalidateCacheIfPrismaClientChanged.mjs";
3
+ import { checkPrismaStatus } from "./checkIsUsingPrisma.mjs";
4
+ import { ensureAliasArray } from "./ensureAliasArray.mjs";
5
+ export const prismaPlugin = async ({ projectRootDir, }) => {
6
+ if (!checkPrismaStatus({ projectRootDir }).isUsingPrisma) {
7
+ return;
8
+ }
9
+ // context(justinvdm, 10 Mar 2025): We need to use vite optimizeDeps for all deps to work with @cloudflare/vite-plugin.
10
+ // Thing is, @prisma/client has generated code. So users end up with a stale @prisma/client
11
+ // when they change their prisma schema and regenerate the client, until clearing out node_modules/.vite
12
+ // We can't exclude @prisma/client from optimizeDeps since we need it there for @cloudflare/vite-plugin to work.
13
+ // But we can manually invalidate the cache if the prisma schema changes.
14
+ await invalidateCacheIfPrismaClientChanged({
15
+ projectRootDir,
16
+ });
17
+ return {
18
+ name: "rwsdk:prisma",
19
+ configEnvironment(name, config) {
20
+ if (name !== "worker") {
21
+ return;
22
+ }
23
+ const wasmPath = resolve(projectRootDir, "node_modules/.prisma/client/wasm.js");
24
+ config.optimizeDeps ??= {};
25
+ config.optimizeDeps.esbuildOptions ??= {};
26
+ config.optimizeDeps.esbuildOptions.plugins ??= [];
27
+ config.optimizeDeps.esbuildOptions.plugins.push({
28
+ name: "rwsdk:prisma",
29
+ setup(build) {
30
+ build.onResolve({ filter: /^.prisma\/client\/default/ }, async () => {
31
+ return {
32
+ path: wasmPath,
33
+ };
34
+ });
35
+ },
36
+ });
37
+ ensureAliasArray(config).push({
38
+ find: /^\.prisma\/client\/default/,
39
+ replacement: wasmPath,
40
+ });
41
+ },
42
+ };
43
+ };
@@ -1,6 +1,18 @@
1
1
  import { Plugin } from "vite";
2
- export declare const reactConditionsResolverPlugin: ({ mode, command, }: {
3
- projectRootDir: string;
4
- mode?: "development" | "production";
5
- command?: "build" | "serve";
6
- }) => Promise<Plugin>;
2
+ import enhancedResolve from "enhanced-resolve";
3
+ export declare const REACT_IMPORTS: string[];
4
+ export declare const ENV_RESOLVERS: {
5
+ ssr: enhancedResolve.ResolveFunction;
6
+ worker: enhancedResolve.ResolveFunction;
7
+ client: enhancedResolve.ResolveFunction;
8
+ };
9
+ export declare const ENV_IMPORTS: {
10
+ [k: string]: {
11
+ aliases: {
12
+ find: RegExp;
13
+ replacement: string;
14
+ }[];
15
+ optimizeIncludes: string[];
16
+ };
17
+ };
18
+ export declare const reactConditionsResolverPlugin: () => Promise<Plugin>;