rwsdk 1.0.0-alpha.2 → 1.0.0-alpha.20-test.20250929144616

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 (214) hide show
  1. package/dist/lib/constants.mjs +1 -2
  2. package/dist/lib/e2e/browser.d.mts +10 -0
  3. package/dist/lib/e2e/browser.mjs +123 -0
  4. package/dist/lib/e2e/dev.d.mts +8 -0
  5. package/dist/lib/e2e/dev.mjs +242 -0
  6. package/dist/lib/e2e/environment.d.mts +10 -0
  7. package/dist/lib/e2e/environment.mjs +210 -0
  8. package/dist/lib/e2e/index.d.mts +8 -0
  9. package/dist/lib/e2e/index.mjs +8 -0
  10. package/dist/lib/e2e/poll.d.mts +8 -0
  11. package/dist/lib/e2e/poll.mjs +31 -0
  12. package/dist/lib/e2e/release.d.mts +56 -0
  13. package/dist/lib/e2e/release.mjs +559 -0
  14. package/dist/lib/e2e/retry.d.mts +4 -0
  15. package/dist/lib/e2e/retry.mjs +16 -0
  16. package/dist/lib/e2e/setup.d.mts +2 -0
  17. package/dist/lib/e2e/setup.mjs +1 -0
  18. package/dist/lib/e2e/tarball.d.mts +14 -0
  19. package/dist/lib/e2e/tarball.mjs +99 -0
  20. package/dist/lib/e2e/testHarness.d.mts +132 -0
  21. package/dist/lib/e2e/testHarness.mjs +436 -0
  22. package/dist/lib/e2e/types.d.mts +32 -0
  23. package/dist/lib/getShortName.mjs +6 -2
  24. package/dist/lib/getShortName.test.d.mts +1 -0
  25. package/dist/lib/getShortName.test.mjs +25 -0
  26. package/dist/lib/getSrcPaths.js +2 -2
  27. package/dist/lib/hasPkgScript.d.mts +4 -1
  28. package/dist/lib/hasPkgScript.mjs +9 -6
  29. package/dist/lib/hasPkgScript.test.d.mts +1 -0
  30. package/dist/lib/hasPkgScript.test.mjs +33 -0
  31. package/dist/lib/jsonUtils.mjs +3 -0
  32. package/dist/lib/jsonUtils.test.d.mts +1 -0
  33. package/dist/lib/jsonUtils.test.mjs +90 -0
  34. package/dist/lib/normalizeModulePath.d.mts +5 -0
  35. package/dist/lib/normalizeModulePath.mjs +1 -1
  36. package/dist/lib/normalizeModulePath.test.d.mts +1 -0
  37. package/dist/lib/{normalizeModulePath.test.js → normalizeModulePath.test.mjs} +21 -2
  38. package/dist/lib/setupEnvFiles.mjs +2 -2
  39. package/dist/lib/smokeTests/artifacts.mjs +2 -2
  40. package/dist/lib/smokeTests/browser.d.mts +1 -1
  41. package/dist/lib/smokeTests/browser.mjs +8 -100
  42. package/dist/lib/smokeTests/cleanup.mjs +6 -9
  43. package/dist/lib/smokeTests/codeUpdates.mjs +5 -5
  44. package/dist/lib/smokeTests/development.mjs +3 -224
  45. package/dist/lib/smokeTests/environment.d.mts +3 -11
  46. package/dist/lib/smokeTests/environment.mjs +17 -151
  47. package/dist/lib/smokeTests/release.d.mts +2 -49
  48. package/dist/lib/smokeTests/release.mjs +4 -504
  49. package/dist/lib/smokeTests/reporting.mjs +2 -2
  50. package/dist/lib/smokeTests/runSmokeTests.mjs +4 -4
  51. package/dist/lib/smokeTests/utils.mjs +3 -3
  52. package/dist/lib/testUtils/stubEnvVars.mjs +1 -1
  53. package/dist/llms/rules/middleware.d.ts +1 -1
  54. package/dist/llms/rules/middleware.js +4 -4
  55. package/dist/runtime/client/client.d.ts +2 -2
  56. package/dist/runtime/client/client.js +2 -2
  57. package/dist/runtime/client/navigation.test.js +1 -1
  58. package/dist/runtime/client/types.d.ts +1 -1
  59. package/dist/runtime/entries/client.d.ts +2 -2
  60. package/dist/runtime/entries/client.js +2 -2
  61. package/dist/runtime/entries/router.d.ts +1 -1
  62. package/dist/runtime/entries/router.js +1 -1
  63. package/dist/runtime/entries/worker.d.ts +5 -6
  64. package/dist/runtime/entries/worker.js +5 -6
  65. package/dist/runtime/imports/worker.js +1 -1
  66. package/dist/runtime/lib/auth/session.d.ts +2 -2
  67. package/dist/runtime/lib/auth/session.js +5 -5
  68. package/dist/runtime/lib/db/DOWorkerDialect.d.ts +1 -1
  69. package/dist/runtime/lib/db/DOWorkerDialect.js +1 -1
  70. package/dist/runtime/lib/db/SqliteDurableObject.js +2 -2
  71. package/dist/runtime/lib/db/index.d.ts +2 -2
  72. package/dist/runtime/lib/db/index.js +2 -2
  73. package/dist/runtime/lib/db/migrations.d.ts +1 -1
  74. package/dist/runtime/lib/db/typeInference/builders/alterTable.d.ts +3 -3
  75. package/dist/runtime/lib/db/typeInference/builders/columnDefinition.d.ts +1 -1
  76. package/dist/runtime/lib/db/typeInference/builders/createTable.d.ts +2 -2
  77. package/dist/runtime/lib/db/typeInference/builders/createView.d.ts +1 -1
  78. package/dist/runtime/lib/db/typeInference/builders/dropTable.d.ts +1 -1
  79. package/dist/runtime/lib/db/typeInference/builders/dropView.d.ts +1 -1
  80. package/dist/runtime/lib/db/typeInference/builders/schema.d.ts +3 -3
  81. package/dist/runtime/lib/db/typeInference/database.d.ts +2 -2
  82. package/dist/runtime/lib/memoizeOnId.test.d.ts +1 -0
  83. package/dist/runtime/lib/memoizeOnId.test.js +49 -0
  84. package/dist/runtime/lib/realtime/client.js +2 -2
  85. package/dist/runtime/lib/realtime/durableObject.js +1 -1
  86. package/dist/runtime/lib/realtime/protocol.test.d.ts +1 -0
  87. package/dist/runtime/lib/realtime/protocol.test.js +107 -0
  88. package/dist/runtime/lib/realtime/shared.test.d.ts +1 -0
  89. package/dist/runtime/lib/realtime/shared.test.js +18 -0
  90. package/dist/runtime/lib/realtime/validateUpgradeRequest.test.d.ts +1 -0
  91. package/dist/runtime/lib/realtime/validateUpgradeRequest.test.js +66 -0
  92. package/dist/runtime/lib/realtime/worker.d.ts +1 -1
  93. package/dist/runtime/lib/realtime/worker.js +2 -2
  94. package/dist/runtime/lib/router.d.ts +1 -1
  95. package/dist/runtime/lib/router.js +40 -22
  96. package/dist/runtime/lib/router.test.js +591 -3
  97. package/dist/runtime/lib/rwContext.d.ts +22 -0
  98. package/dist/runtime/lib/rwContext.js +1 -0
  99. package/dist/runtime/lib/stitchDocumentAndAppStreams.d.ts +18 -0
  100. package/dist/runtime/lib/stitchDocumentAndAppStreams.js +143 -0
  101. package/dist/runtime/lib/turnstile/useTurnstile.js +1 -1
  102. package/dist/runtime/lib/turnstile/verifyTurnstileToken.d.ts +2 -1
  103. package/dist/runtime/lib/turnstile/verifyTurnstileToken.js +6 -6
  104. package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.d.ts +1 -0
  105. package/dist/runtime/lib/turnstile/verifyTurnstileToken.test.js +49 -0
  106. package/dist/runtime/register/worker.d.ts +1 -1
  107. package/dist/runtime/register/worker.js +34 -22
  108. package/dist/runtime/render/assembleDocument.d.ts +6 -0
  109. package/dist/runtime/render/assembleDocument.js +22 -0
  110. package/dist/runtime/render/createThenableFromReadableStream.d.ts +1 -0
  111. package/dist/runtime/render/createThenableFromReadableStream.js +9 -0
  112. package/dist/runtime/render/normalizeActionResult.d.ts +1 -0
  113. package/dist/runtime/render/normalizeActionResult.js +43 -0
  114. package/dist/runtime/render/preloads.d.ts +3 -3
  115. package/dist/runtime/render/preloads.js +2 -3
  116. package/dist/runtime/render/{renderRscThenableToHtmlStream.d.ts → renderDocumentHtmlStream.d.ts} +3 -3
  117. package/dist/runtime/render/renderDocumentHtmlStream.js +39 -0
  118. package/dist/runtime/render/renderHtmlStream.d.ts +7 -0
  119. package/dist/runtime/render/renderHtmlStream.js +31 -0
  120. package/dist/runtime/render/renderToRscStream.d.ts +5 -3
  121. package/dist/runtime/render/renderToRscStream.js +12 -41
  122. package/dist/runtime/render/renderToStream.d.ts +3 -2
  123. package/dist/runtime/render/renderToStream.js +17 -10
  124. package/dist/runtime/render/stylesheets.d.ts +2 -2
  125. package/dist/runtime/render/stylesheets.js +2 -3
  126. package/dist/runtime/requestInfo/types.d.ts +0 -2
  127. package/dist/runtime/requestInfo/worker.d.ts +1 -1
  128. package/dist/runtime/requestInfo/worker.js +1 -9
  129. package/dist/runtime/script.js +1 -1
  130. package/dist/runtime/ssrBridge.d.ts +3 -2
  131. package/dist/runtime/ssrBridge.js +3 -2
  132. package/dist/runtime/worker.d.ts +2 -1
  133. package/dist/runtime/worker.js +13 -16
  134. package/dist/scripts/addon.d.mts +1 -0
  135. package/dist/scripts/addon.mjs +75 -0
  136. package/dist/scripts/debug-sync.mjs +106 -137
  137. package/dist/scripts/ensure-deploy-env.mjs +6 -6
  138. package/dist/scripts/migrate-new.mjs +3 -4
  139. package/dist/scripts/smoke-test.mjs +2 -2
  140. package/dist/scripts/worker-run.mjs +7 -9
  141. package/dist/vite/buildApp.d.mts +2 -1
  142. package/dist/vite/buildApp.mjs +10 -6
  143. package/dist/vite/checkIsUsingPrisma.d.mts +4 -0
  144. package/dist/vite/checkIsUsingPrisma.mjs +2 -2
  145. package/dist/vite/checkIsUsingPrisma.test.d.mts +1 -0
  146. package/dist/vite/checkIsUsingPrisma.test.mjs +30 -0
  147. package/dist/vite/configPlugin.mjs +55 -15
  148. package/dist/vite/createDirectiveLookupPlugin.d.mts +9 -0
  149. package/dist/vite/createDirectiveLookupPlugin.mjs +34 -30
  150. package/dist/vite/createDirectiveLookupPlugin.test.d.mts +1 -0
  151. package/dist/vite/createDirectiveLookupPlugin.test.mjs +40 -0
  152. package/dist/vite/createViteAwareResolver.d.mts +1 -2
  153. package/dist/vite/createViteAwareResolver.mjs +1 -1
  154. package/dist/vite/directiveModulesDevPlugin.d.mts +4 -1
  155. package/dist/vite/directiveModulesDevPlugin.mjs +9 -8
  156. package/dist/vite/directiveModulesDevPlugin.test.d.mts +1 -0
  157. package/dist/vite/directiveModulesDevPlugin.test.mjs +59 -0
  158. package/dist/vite/directivesPlugin.d.mts +1 -0
  159. package/dist/vite/directivesPlugin.mjs +4 -4
  160. package/dist/vite/directivesPlugin.test.d.mts +1 -0
  161. package/dist/vite/directivesPlugin.test.mjs +24 -0
  162. package/dist/vite/ensureAliasArray.test.d.mts +1 -0
  163. package/dist/vite/ensureAliasArray.test.mjs +71 -0
  164. package/dist/vite/findSpecifiers.mjs +3 -2
  165. package/dist/vite/findSpecifiers.test.d.mts +1 -0
  166. package/dist/vite/findSpecifiers.test.mjs +202 -0
  167. package/dist/vite/findSsrSpecifiers.mjs +1 -1
  168. package/dist/vite/findSsrSpecifiers.test.d.mts +1 -0
  169. package/dist/vite/findSsrSpecifiers.test.mjs +99 -0
  170. package/dist/vite/getViteEsbuild.mjs +1 -1
  171. package/dist/vite/hasDirective.d.mts +6 -3
  172. package/dist/vite/hasDirective.mjs +43 -27
  173. package/dist/vite/hasDirective.test.d.mts +1 -0
  174. package/dist/vite/hasDirective.test.mjs +107 -0
  175. package/dist/vite/index.d.mts +1 -1
  176. package/dist/vite/invalidateCacheIfPrismaClientChanged.mjs +2 -2
  177. package/dist/vite/isJsFile.test.d.mts +1 -0
  178. package/dist/vite/isJsFile.test.mjs +38 -0
  179. package/dist/vite/{reactConditionsResolverPlugin.d.mts → knownDepsResolverPlugin.d.mts} +3 -3
  180. package/dist/vite/{reactConditionsResolverPlugin.mjs → knownDepsResolverPlugin.mjs} +29 -24
  181. package/dist/vite/linkerPlugin.d.mts +8 -0
  182. package/dist/vite/linkerPlugin.mjs +32 -24
  183. package/dist/vite/linkerPlugin.test.d.mts +1 -0
  184. package/dist/vite/linkerPlugin.test.mjs +41 -0
  185. package/dist/vite/miniflareHMRPlugin.d.mts +5 -0
  186. package/dist/vite/miniflareHMRPlugin.mjs +7 -7
  187. package/dist/vite/miniflareHMRPlugin.test.d.mts +1 -0
  188. package/dist/vite/miniflareHMRPlugin.test.mjs +42 -0
  189. package/dist/vite/prismaPlugin.mjs +1 -1
  190. package/dist/vite/redwoodPlugin.d.mts +9 -0
  191. package/dist/vite/redwoodPlugin.mjs +44 -20
  192. package/dist/vite/redwoodPlugin.test.d.mts +1 -0
  193. package/dist/vite/redwoodPlugin.test.mjs +34 -0
  194. package/dist/vite/resolveForcedPaths.d.mts +4 -0
  195. package/dist/vite/resolveForcedPaths.mjs +9 -0
  196. package/dist/vite/runDirectivesScan.d.mts +22 -1
  197. package/dist/vite/runDirectivesScan.mjs +109 -61
  198. package/dist/vite/runDirectivesScan.test.d.mts +1 -0
  199. package/dist/vite/runDirectivesScan.test.mjs +73 -0
  200. package/dist/vite/ssrBridgePlugin.mjs +10 -3
  201. package/dist/vite/transformClientComponents.mjs +8 -6
  202. package/dist/vite/transformClientComponents.test.mjs +117 -59
  203. package/dist/vite/transformJsxScriptTagsPlugin.mjs +1 -1
  204. package/dist/vite/transformJsxScriptTagsPlugin.test.mjs +2 -2
  205. package/dist/vite/transformServerFunctions.d.mts +1 -1
  206. package/dist/vite/transformServerFunctions.mjs +5 -5
  207. package/dist/vite/transformServerFunctions.test.mjs +3 -3
  208. package/package.json +61 -47
  209. package/dist/runtime/imports/resolveSSRValue.d.ts +0 -1
  210. package/dist/runtime/imports/resolveSSRValue.js +0 -8
  211. package/dist/runtime/render/renderRscThenableToHtmlStream.js +0 -54
  212. package/dist/runtime/render/transformRscToHtmlStream.d.ts +0 -8
  213. package/dist/runtime/render/transformRscToHtmlStream.js +0 -19
  214. /package/dist/lib/{normalizeModulePath.test.d.ts → e2e/types.mjs} +0 -0
@@ -1,27 +1,34 @@
1
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
2
  import { injectRSCPayload } from "rsc-html-stream/server";
3
+ import { requestInfo } from "../requestInfo/worker";
4
+ import { renderDocumentHtmlStream } from "./renderDocumentHtmlStream";
5
+ import { renderToRscStream } from "./renderToRscStream";
6
6
  export const IdentityDocument = ({ children }) => (_jsx(_Fragment, { children: children }));
7
- export const renderToStream = async (element, { Document = IdentityDocument, injectRSCPayload: shouldInjectRSCPayload = false, onError = () => { }, } = {}) => {
7
+ export const renderToStream = async (element, { ssr: shouldSSR = true, Document = IdentityDocument, injectRSCPayload: shouldInjectRSCPayload = true, onError = () => { }, } = {}) => {
8
8
  let rscStream = renderToRscStream({
9
- node: element,
10
- actionResult: null,
9
+ input: {
10
+ node: element,
11
+ actionResult: undefined,
12
+ },
11
13
  onError,
12
14
  });
15
+ let injectRSCStream;
13
16
  if (shouldInjectRSCPayload) {
14
17
  const [rscPayloadStream1, rscPayloadStream2] = rscStream.tee();
15
18
  rscStream = rscPayloadStream1;
16
- rscStream = rscStream.pipeThrough(injectRSCPayload(rscPayloadStream2, {
19
+ injectRSCStream = injectRSCPayload(rscPayloadStream2, {
17
20
  nonce: requestInfo.rw.nonce,
18
- }));
21
+ });
19
22
  }
20
- const htmlStream = await transformRscToHtmlStream({
21
- stream: rscStream,
23
+ let htmlStream = await renderDocumentHtmlStream({
24
+ rscPayloadStream: rscStream,
22
25
  Document,
23
26
  requestInfo,
27
+ shouldSSR,
24
28
  onError,
25
29
  });
30
+ if (injectRSCStream) {
31
+ htmlStream = htmlStream.pipeThrough(injectRSCStream);
32
+ }
26
33
  return htmlStream;
27
34
  };
@@ -1,4 +1,4 @@
1
1
  import { type RequestInfo } from "../requestInfo/types.js";
2
- export declare const Stylesheets: ({ requestInfo }: {
2
+ export declare const Stylesheets: ({ requestInfo, }: {
3
3
  requestInfo: RequestInfo;
4
- }) => import("react/jsx-runtime.js").JSX.Element;
4
+ }) => Promise<import("react/jsx-runtime").JSX.Element>;
@@ -1,5 +1,4 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { use } from "react";
3
2
  import { getManifest } from "../lib/manifest.js";
4
3
  const findCssForModule = (scriptId, manifest) => {
5
4
  const css = new Set();
@@ -22,8 +21,8 @@ const findCssForModule = (scriptId, manifest) => {
22
21
  inner(scriptId);
23
22
  return Array.from(css);
24
23
  };
25
- export const Stylesheets = ({ requestInfo }) => {
26
- const manifest = use(getManifest());
24
+ export const Stylesheets = async ({ requestInfo, }) => {
25
+ const manifest = await getManifest();
27
26
  const allStylesheets = new Set();
28
27
  for (const scriptId of requestInfo.rw.scriptsToBeLoaded) {
29
28
  const css = findCssForModule(scriptId, manifest);
@@ -5,8 +5,6 @@ export interface RequestInfo<Params = any, AppContext = DefaultAppContext> {
5
5
  request: Request;
6
6
  params: Params;
7
7
  ctx: AppContext;
8
- /** @deprecated: Use `response.headers` instead */
9
- headers: Headers;
10
8
  rw: RwContext;
11
9
  cf: ExecutionContext;
12
10
  response: ResponseInit & {
@@ -1,4 +1,4 @@
1
- import { RequestInfo, DefaultAppContext } from "./types";
1
+ import { DefaultAppContext, RequestInfo } from "./types";
2
2
  type DefaultRequestInfo = RequestInfo<DefaultAppContext>;
3
3
  export declare const requestInfo: DefaultRequestInfo;
4
4
  export declare function getRequestInfo(): RequestInfo;
@@ -2,15 +2,7 @@ import { AsyncLocalStorage } from "async_hooks";
2
2
  const requestInfoDeferred = Promise.withResolvers();
3
3
  const requestInfoStore = new AsyncLocalStorage();
4
4
  const requestInfoBase = {};
5
- const REQUEST_INFO_KEYS = [
6
- "request",
7
- "params",
8
- "ctx",
9
- "headers",
10
- "rw",
11
- "cf",
12
- "response",
13
- ];
5
+ const REQUEST_INFO_KEYS = ["request", "params", "ctx", "rw", "cf", "response"];
14
6
  REQUEST_INFO_KEYS.forEach((key) => {
15
7
  Object.defineProperty(requestInfoBase, key, {
16
8
  enumerable: true,
@@ -1,5 +1,5 @@
1
- import { defineApp } from "./worker";
2
1
  import { env } from "cloudflare:workers";
2
+ import { defineApp } from "./worker";
3
3
  export const defineScript = (fn) => {
4
4
  const app = defineApp([
5
5
  async () => {
@@ -1,2 +1,3 @@
1
- export { renderRscThenableToHtmlStream } from "./render/renderRscThenableToHtmlStream";
2
- export { ssrLoadModule, ssrGetModuleExport, ssrWebpackRequire, } from "./imports/ssr";
1
+ export { createThenableFromReadableStream } from "./render/createThenableFromReadableStream";
2
+ export { renderHtmlStream } from "./render/renderHtmlStream";
3
+ export { ssrGetModuleExport, ssrLoadModule, ssrWebpackRequire, } from "./imports/ssr";
@@ -7,5 +7,6 @@
7
7
  // import it through this bridge module, using the bare import path
8
8
  // `rwsdk/__ssr_bridge`. We have bundler logic (ssrBridgePlugin) that looks out
9
9
  // for imports to it.
10
- export { renderRscThenableToHtmlStream } from "./render/renderRscThenableToHtmlStream";
11
- export { ssrLoadModule, ssrGetModuleExport, ssrWebpackRequire, } from "./imports/ssr";
10
+ export { createThenableFromReadableStream } from "./render/createThenableFromReadableStream";
11
+ export { renderHtmlStream } from "./render/renderHtmlStream";
12
+ export { ssrGetModuleExport, ssrLoadModule, ssrWebpackRequire, } from "./imports/ssr";
@@ -1,6 +1,7 @@
1
1
  import React from "react";
2
- import { RequestInfo, DefaultAppContext } from "./requestInfo/types";
2
+ import { DefaultAppContext, RequestInfo } from "./requestInfo/types";
3
3
  import { Route } from "./lib/router";
4
+ export * from "./requestInfo/types";
4
5
  declare global {
5
6
  type Env = {
6
7
  ASSETS: Fetcher;
@@ -1,13 +1,15 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { transformRscToHtmlStream } from "./render/transformRscToHtmlStream";
2
+ import { normalizeActionResult } from "./render/normalizeActionResult";
3
+ import { renderDocumentHtmlStream } from "./render/renderDocumentHtmlStream";
3
4
  import { renderToRscStream } from "./render/renderToRscStream";
4
- import { rscActionHandler } from "./register/worker";
5
5
  import { injectRSCPayload } from "rsc-html-stream/server";
6
6
  import { ErrorResponse } from "./error";
7
+ import { rscActionHandler } from "./register/worker";
7
8
  import { getRequestInfo, runWithRequestInfo, runWithRequestInfoOverrides, } from "./requestInfo/worker";
9
+ import { ssrWebpackRequire } from "./imports/worker";
8
10
  import { defineRoutes } from "./lib/router";
9
11
  import { generateNonce } from "./lib/utils";
10
- import { ssrWebpackRequire } from "./imports/worker";
12
+ export * from "./requestInfo/types";
11
13
  export const defineApp = (routes) => {
12
14
  return {
13
15
  fetch: async (request, env, cf) => {
@@ -34,7 +36,6 @@ export const defineApp = (routes) => {
34
36
  const isRSCRequest = url.searchParams.has("__rsc") ||
35
37
  request.headers.get("accept")?.includes("text/x-component");
36
38
  const isAction = url.searchParams.has("__rsc_action_id");
37
- const userHeaders = new Headers();
38
39
  const rw = {
39
40
  Document: DefaultDocument,
40
41
  nonce: generateNonce(),
@@ -50,7 +51,6 @@ export const defineApp = (routes) => {
50
51
  };
51
52
  const outerRequestInfo = {
52
53
  request,
53
- headers: userHeaders,
54
54
  cf,
55
55
  params: {},
56
56
  ctx: {},
@@ -79,12 +79,14 @@ export const defineApp = (routes) => {
79
79
  status: 500,
80
80
  });
81
81
  }
82
- const actionResult = requestInfo.rw.actionResult;
82
+ const actionResult = normalizeActionResult(requestInfo.rw.actionResult);
83
83
  const pageElement = createPageElement(requestInfo, Page);
84
84
  const { rscPayload: shouldInjectRSCPayload } = rw;
85
85
  let rscPayloadStream = renderToRscStream({
86
- node: pageElement,
87
- actionResult: actionResult instanceof Response ? null : actionResult,
86
+ input: {
87
+ node: pageElement,
88
+ actionResult,
89
+ },
88
90
  onError,
89
91
  });
90
92
  if (isRSCRequest) {
@@ -104,11 +106,12 @@ export const defineApp = (routes) => {
104
106
  nonce: rw.nonce,
105
107
  });
106
108
  }
107
- let html = await transformRscToHtmlStream({
108
- stream: rscPayloadStream,
109
+ let html = await renderDocumentHtmlStream({
110
+ rscPayloadStream: rscPayloadStream,
109
111
  Document: rw.Document,
110
112
  requestInfo: requestInfo,
111
113
  onError,
114
+ shouldSSR: rw.ssr,
112
115
  });
113
116
  if (injectRSCPayloadStream) {
114
117
  html = html.pipeThrough(injectRSCPayloadStream);
@@ -139,12 +142,6 @@ export const defineApp = (routes) => {
139
142
  // context(justinvdm, 18 Mar 2025): In some cases, such as a .fetch() call to a durable object instance, or Response.redirect(),
140
143
  // we need to return a mutable response object.
141
144
  const mutableResponse = new Response(response.body, response);
142
- // Merge user headers from the legacy headers object
143
- for (const [key, value] of userHeaders.entries()) {
144
- if (!response.headers.has(key)) {
145
- mutableResponse.headers.set(key, value);
146
- }
147
- }
148
145
  // Merge headers from user response init (these take precedence)
149
146
  if (userResponseInit.headers) {
150
147
  const userResponseHeaders = new Headers(userResponseInit.headers);
@@ -0,0 +1 @@
1
+ export declare const addon: () => Promise<void>;
@@ -0,0 +1,75 @@
1
+ import decompress from "decompress";
2
+ import { findUp } from "find-up";
3
+ import { createWriteStream } from "node:fs";
4
+ import fs from "node:fs/promises";
5
+ import os from "node:os";
6
+ import path from "node:path";
7
+ import { Readable } from "node:stream";
8
+ import { pipeline } from "node:stream/promises";
9
+ async function getRwSdkProjectRootDir(cwd) {
10
+ const pnpmWorkspaceYamlPath = await findUp("pnpm-workspace.yaml", { cwd });
11
+ if (pnpmWorkspaceYamlPath) {
12
+ return path.dirname(pnpmWorkspaceYamlPath);
13
+ }
14
+ const packageJsonPath = await findUp("package.json", { cwd });
15
+ if (packageJsonPath) {
16
+ const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
17
+ const packageJson = JSON.parse(packageJsonContent);
18
+ if (packageJson.workspaces) {
19
+ return path.dirname(packageJsonPath);
20
+ }
21
+ }
22
+ // If not in a monorepo, assume the current directory is the project root
23
+ return cwd;
24
+ }
25
+ export const addon = async () => {
26
+ const addonName = process.argv[3];
27
+ if (!addonName) {
28
+ console.error("Please specify the addon name.");
29
+ console.error("Usage: rw-scripts addon <addon-name>");
30
+ process.exit(1);
31
+ }
32
+ try {
33
+ const projectRootDir = await getRwSdkProjectRootDir(process.cwd());
34
+ const packageJsonPath = path.resolve(projectRootDir, "package.json");
35
+ const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
36
+ const { dependencies, devDependencies } = JSON.parse(packageJsonContent);
37
+ const rwsdkVersion = dependencies?.rwsdk || devDependencies?.rwsdk;
38
+ if (!rwsdkVersion) {
39
+ console.error('Could not find "rwsdk" in your dependencies or devDependencies.');
40
+ process.exit(1);
41
+ }
42
+ const tmpDir = path.resolve(projectRootDir, ".tmp", "addons", addonName);
43
+ await fs.rm(tmpDir, { recursive: true, force: true });
44
+ await fs.mkdir(tmpDir, { recursive: true });
45
+ const downloadUrl = `https://github.com/redwoodjs/sdk/releases/download/${rwsdkVersion}/${addonName}-${rwsdkVersion}.tar.gz`;
46
+ console.log(`Downloading addon "${addonName}" version ${rwsdkVersion}...`);
47
+ const filePath = path.join(os.tmpdir(), `rwsdk-addon-${addonName}-${rwsdkVersion}.tar.gz`);
48
+ const response = await fetch(downloadUrl);
49
+ if (!response.ok) {
50
+ console.error(`Error downloading addon: ${response.statusText}`);
51
+ process.exit(1);
52
+ }
53
+ if (!response.body) {
54
+ console.error(`\nError: Failed to download addon "${addonName}". The response contained no data.`);
55
+ process.exit(1);
56
+ }
57
+ await pipeline(Readable.fromWeb(response.body), createWriteStream(filePath));
58
+ await decompress(filePath, tmpDir);
59
+ console.log();
60
+ console.log("Download complete!");
61
+ console.log(`The addon files are located in: ${path.relative(projectRootDir, tmpDir)}`);
62
+ console.log();
63
+ console.log("To continue, open the step-by-step instructions:");
64
+ const instructionsPath = path.join(tmpDir, "INSTRUCTIONS.md");
65
+ console.log(`code ${instructionsPath}`);
66
+ }
67
+ catch (e) {
68
+ console.error(`Could not download addon "${addonName}". Please check the name and try again.`);
69
+ console.error(e.message);
70
+ process.exit(1);
71
+ }
72
+ };
73
+ if (import.meta.url === new URL(process.argv[1], import.meta.url).href) {
74
+ addon();
75
+ }
@@ -1,32 +1,11 @@
1
- import path from "node:path";
2
- import { fileURLToPath } from "node:url";
1
+ import chokidar from "chokidar";
3
2
  import { $ } from "execa";
4
- import fs from "node:fs/promises";
5
3
  import { existsSync } from "node:fs";
6
- import chokidar from "chokidar";
4
+ import fs from "node:fs/promises";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
7
  import { lock } from "proper-lockfile";
8
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
- const getPackageManagerInfo = (targetDir) => {
10
- if (existsSync(path.join(targetDir, "bun.lock"))) {
11
- return { name: "bun", lockFile: "bun.lock", command: "add" };
12
- }
13
- const pnpmResult = {
14
- name: "pnpm",
15
- lockFile: "pnpm-lock.yaml",
16
- command: "add",
17
- };
18
- if (existsSync(path.join(targetDir, "yarn.lock"))) {
19
- return { name: "yarn", lockFile: "yarn.lock", command: "add" };
20
- }
21
- if (existsSync(path.join(targetDir, "pnpm-lock.yaml")) ||
22
- existsSync(path.join(targetDir, "node_modules", ".pnpm"))) {
23
- return pnpmResult;
24
- }
25
- if (existsSync(path.join(targetDir, "package-lock.json"))) {
26
- return { name: "npm", lockFile: "package-lock.json", command: "install" };
27
- }
28
- return pnpmResult;
29
- };
30
9
  const cleanupViteEntries = async (targetDir) => {
31
10
  const nodeModulesDir = path.join(targetDir, "node_modules");
32
11
  if (!existsSync(nodeModulesDir)) {
@@ -58,91 +37,6 @@ const cleanupViteEntries = async (targetDir) => {
58
37
  console.log(`Failed to cleanup vite cache entries: ${error}`);
59
38
  }
60
39
  };
61
- const performFullSync = async (sdkDir, targetDir) => {
62
- let tarballPath = "";
63
- let tarballName = "";
64
- // Clean up vite cache
65
- await cleanupViteEntries(targetDir);
66
- try {
67
- console.log("📦 Packing SDK...");
68
- const packResult = await $({ cwd: sdkDir }) `npm pack --json`;
69
- const json = JSON.parse(packResult.stdout || "[]");
70
- const packInfo = Array.isArray(json) ? json[0] : undefined;
71
- tarballName = (packInfo && (packInfo.filename || packInfo.name)) || "";
72
- if (!tarballName) {
73
- console.error("❌ Failed to get tarball name from npm pack.");
74
- return;
75
- }
76
- tarballPath = path.resolve(sdkDir, tarballName);
77
- console.log(`💿 Installing ${tarballName} in ${targetDir}...`);
78
- const pm = getPackageManagerInfo(targetDir);
79
- const packageJsonPath = path.join(targetDir, "package.json");
80
- const lockfilePath = path.join(targetDir, pm.lockFile);
81
- const originalPackageJson = await fs
82
- .readFile(packageJsonPath, "utf-8")
83
- .catch(() => null);
84
- const originalLockfile = await fs
85
- .readFile(lockfilePath, "utf-8")
86
- .catch(() => null);
87
- try {
88
- // For bun, we need to remove the existing dependency from package.json
89
- // before adding the tarball to avoid a dependency loop error.
90
- if (pm.name === "bun" && originalPackageJson) {
91
- try {
92
- const targetPackageJson = JSON.parse(originalPackageJson);
93
- let modified = false;
94
- if (targetPackageJson.dependencies?.rwsdk) {
95
- delete targetPackageJson.dependencies.rwsdk;
96
- modified = true;
97
- }
98
- if (targetPackageJson.devDependencies?.rwsdk) {
99
- delete targetPackageJson.devDependencies.rwsdk;
100
- modified = true;
101
- }
102
- if (modified) {
103
- console.log("Temporarily removing rwsdk from target package.json to prevent dependency loop with bun.");
104
- await fs.writeFile(packageJsonPath, JSON.stringify(targetPackageJson, null, 2));
105
- }
106
- }
107
- catch (e) {
108
- console.warn("Could not modify target package.json, proceeding anyway.");
109
- }
110
- }
111
- const cmd = pm.name;
112
- const args = [pm.command];
113
- if (pm.name === "yarn") {
114
- // For modern yarn, disable PnP to avoid resolution issues with local tarballs
115
- process.env.YARN_NODE_LINKER = "node-modules";
116
- args.push(`rwsdk@file:${tarballPath}`);
117
- }
118
- else {
119
- args.push(tarballPath);
120
- }
121
- await $(cmd, args, {
122
- cwd: targetDir,
123
- stdio: "inherit",
124
- });
125
- }
126
- finally {
127
- if (originalPackageJson) {
128
- console.log("Restoring package.json...");
129
- await fs.writeFile(packageJsonPath, originalPackageJson);
130
- }
131
- if (originalLockfile) {
132
- console.log(`Restoring ${pm.lockFile}...`);
133
- await fs.writeFile(lockfilePath, originalLockfile);
134
- }
135
- }
136
- }
137
- finally {
138
- if (tarballPath) {
139
- console.log("Removing tarball...");
140
- await fs.unlink(tarballPath).catch(() => {
141
- // ignore if deletion fails
142
- });
143
- }
144
- }
145
- };
146
40
  const syncFilesWithRsyncOrFs = async (sdkDir, destDir, filesEntries) => {
147
41
  const sources = filesEntries.map((p) => path.join(sdkDir, p));
148
42
  // Always include package.json in sync
@@ -191,45 +85,120 @@ const syncFilesWithRsyncOrFs = async (sdkDir, destDir, filesEntries) => {
191
85
  }
192
86
  }
193
87
  };
194
- const performFastSync = async (sdkDir, targetDir) => {
195
- console.log("⚡️ No dependency changes, performing fast sync...");
196
- // Clean up vite cache
197
- await cleanupViteEntries(targetDir);
198
- const nodeModulesPkgDir = path.join(targetDir, "node_modules", "rwsdk");
199
- // Copy directories/files declared in package.json#files (plus package.json)
200
- const filesToSync = JSON.parse(await fs.readFile(path.join(sdkDir, "package.json"), "utf-8"))
201
- .files || [];
202
- await syncFilesWithRsyncOrFs(sdkDir, nodeModulesPkgDir, filesToSync);
88
+ const findUp = async (names, startDir) => {
89
+ let dir = startDir;
90
+ while (dir !== path.dirname(dir)) {
91
+ for (const name of names) {
92
+ const filePath = path.join(dir, name);
93
+ if (existsSync(filePath)) {
94
+ return dir;
95
+ }
96
+ }
97
+ dir = path.dirname(dir);
98
+ }
99
+ return undefined;
100
+ };
101
+ const getMonorepoRoot = async (startDir) => {
102
+ try {
103
+ // `pnpm root` is the most reliable way to find the workspace root node_modules
104
+ const { stdout } = await $({
105
+ cwd: startDir,
106
+ }) `pnpm root`;
107
+ // pnpm root returns the node_modules path, so we go up one level
108
+ return path.resolve(stdout, "..");
109
+ }
110
+ catch (e) {
111
+ console.warn(`Could not determine pnpm root from ${startDir}. Falling back to file search.`);
112
+ const root = await findUp(["pnpm-workspace.yaml"], startDir);
113
+ if (root) {
114
+ return root;
115
+ }
116
+ }
117
+ console.warn("Could not find pnpm monorepo root. Using parent directory of target as fallback.");
118
+ return path.resolve(startDir, "..");
203
119
  };
204
120
  const areDependenciesEqual = (deps1, deps2) => {
205
121
  // Simple string comparison for this use case is sufficient
206
122
  return JSON.stringify(deps1 ?? {}) === JSON.stringify(deps2 ?? {});
207
123
  };
124
+ const performFullSync = async (sdkDir, targetDir, monorepoRoot) => {
125
+ console.log("📦 Performing full sync with tarball...");
126
+ let tarballPath = "";
127
+ const projectName = path.basename(targetDir);
128
+ const rwsyncDir = path.join(monorepoRoot, "node_modules", `.rwsync_${projectName}`);
129
+ try {
130
+ // 1. Pack the SDK
131
+ const packResult = await $({ cwd: sdkDir }) `npm pack --json`;
132
+ const json = JSON.parse(packResult.stdout || "[]");
133
+ const packInfo = Array.isArray(json) ? json[0] : undefined;
134
+ const tarballName = (packInfo && (packInfo.filename || packInfo.name)) || "";
135
+ if (!tarballName) {
136
+ throw new Error("Failed to get tarball name from npm pack.");
137
+ }
138
+ tarballPath = path.resolve(sdkDir, tarballName);
139
+ // 2. Prepare isolated install directory
140
+ console.log(`Preparing isolated install directory at ${rwsyncDir}`);
141
+ await fs.rm(rwsyncDir, { recursive: true, force: true });
142
+ await fs.mkdir(rwsyncDir, { recursive: true });
143
+ await fs.writeFile(path.join(rwsyncDir, "package.json"), JSON.stringify({ name: `rwsync-env-${projectName}` }, null, 2));
144
+ // 3. Perform isolated install
145
+ console.log(`Installing ${tarballName} in isolation...`);
146
+ await $("pnpm", ["add", tarballPath], {
147
+ cwd: rwsyncDir,
148
+ stdio: "inherit",
149
+ });
150
+ // 4. Create symlink
151
+ const symlinkSource = path.join(rwsyncDir, "node_modules", "rwsdk");
152
+ const symlinkTarget = path.join(targetDir, "node_modules", "rwsdk");
153
+ console.log(`Symlinking ${symlinkTarget} -> ${symlinkSource}`);
154
+ await fs.rm(symlinkTarget, { recursive: true, force: true });
155
+ await fs.mkdir(path.dirname(symlinkTarget), { recursive: true });
156
+ await fs.symlink(symlinkSource, symlinkTarget, "dir");
157
+ }
158
+ finally {
159
+ if (tarballPath) {
160
+ console.log("Removing tarball...");
161
+ await fs.unlink(tarballPath).catch(() => { });
162
+ }
163
+ }
164
+ };
165
+ const performFastSync = async (sdkDir, targetDir, monorepoRoot) => {
166
+ console.log("⚡️ Performing fast sync with rsync...");
167
+ const projectName = path.basename(targetDir);
168
+ const rwsyncDir = path.join(monorepoRoot, "node_modules", `.rwsync_${projectName}`);
169
+ const syncDestDir = path.join(rwsyncDir, "node_modules", "rwsdk");
170
+ // Copy directories/files declared in package.json#files (plus package.json)
171
+ const filesToSync = JSON.parse(await fs.readFile(path.join(sdkDir, "package.json"), "utf-8"))
172
+ .files || [];
173
+ await syncFilesWithRsyncOrFs(sdkDir, syncDestDir, filesToSync);
174
+ };
208
175
  const performSync = async (sdkDir, targetDir) => {
209
176
  console.log("🏗️ Rebuilding SDK...");
210
177
  await $ `pnpm build`;
211
- const forceFullSync = Boolean(process.env.RWSDK_FORCE_FULL_SYNC);
212
- if (forceFullSync) {
213
- console.log("🏃 Force full sync mode is enabled.");
214
- await performFullSync(sdkDir, targetDir);
215
- console.log(" Done syncing");
216
- return;
178
+ // Clean up vite cache in the target project
179
+ await cleanupViteEntries(targetDir);
180
+ const monorepoRoot = await getMonorepoRoot(targetDir);
181
+ const projectName = path.basename(targetDir);
182
+ const installedSdkPackageJsonPath = path.join(monorepoRoot, "node_modules", `.rwsync_${projectName}`, "node_modules", "rwsdk", "package.json");
183
+ let needsFullSync = false;
184
+ if (!existsSync(installedSdkPackageJsonPath)) {
185
+ console.log("No previous sync found, performing full sync.");
186
+ needsFullSync = true;
217
187
  }
218
- const sdkPackageJsonPath = path.join(sdkDir, "package.json");
219
- const installedSdkPackageJsonPath = path.join(targetDir, "node_modules/rwsdk/package.json");
220
- let packageJsonChanged = true;
221
- if (existsSync(installedSdkPackageJsonPath)) {
222
- const sdkPackageJsonContent = await fs.readFile(sdkPackageJsonPath, "utf-8");
223
- const installedSdkPackageJsonContent = await fs.readFile(installedSdkPackageJsonPath, "utf-8");
224
- packageJsonChanged =
225
- sdkPackageJsonContent !== installedSdkPackageJsonContent;
188
+ else {
189
+ const sdkPackageJson = JSON.parse(await fs.readFile(path.join(sdkDir, "package.json"), "utf-8"));
190
+ const installedSdkPackageJson = JSON.parse(await fs.readFile(installedSdkPackageJsonPath, "utf-8"));
191
+ if (!areDependenciesEqual(sdkPackageJson.dependencies, installedSdkPackageJson.dependencies) ||
192
+ !areDependenciesEqual(sdkPackageJson.devDependencies, installedSdkPackageJson.devDependencies)) {
193
+ console.log("Dependency changes detected, performing full sync.");
194
+ needsFullSync = true;
195
+ }
226
196
  }
227
- if (packageJsonChanged) {
228
- console.log("📦 package.json changed, performing full sync...");
229
- await performFullSync(sdkDir, targetDir);
197
+ if (needsFullSync) {
198
+ await performFullSync(sdkDir, targetDir, monorepoRoot);
230
199
  }
231
200
  else {
232
- await performFastSync(sdkDir, targetDir);
201
+ await performFastSync(sdkDir, targetDir, monorepoRoot);
233
202
  }
234
203
  console.log("✅ Done syncing");
235
204
  };
@@ -1,13 +1,13 @@
1
- import { $ } from "../lib/$.mjs";
2
- import { readFile, writeFile } from "fs/promises";
3
- import { resolve, basename, join } from "path";
4
1
  import { randomBytes } from "crypto";
2
+ import { pathExists } from "fs-extra";
3
+ import { readFile, writeFile } from "fs/promises";
5
4
  import { glob } from "glob";
6
5
  import { parse as parseJsonc } from "jsonc-parser";
7
- import { uniqueNamesGenerator, adjectives, animals, } from "unique-names-generator";
6
+ import { basename, join, resolve } from "path";
8
7
  import * as readline from "readline";
9
- import { pathExists } from "fs-extra";
10
- import { parseJson, extractAllJson } from "../lib/jsonUtils.mjs";
8
+ import { adjectives, animals, uniqueNamesGenerator, } from "unique-names-generator";
9
+ import { $ } from "../lib/$.mjs";
10
+ import { extractAllJson, parseJson } from "../lib/jsonUtils.mjs";
11
11
  const promptForDeployment = async () => {
12
12
  const rl = readline.createInterface({
13
13
  input: process.stdin,
@@ -1,9 +1,8 @@
1
+ import { mkdirp } from "fs-extra";
2
+ import { readdir, writeFile } from "fs/promises";
1
3
  import snakeCase from "lodash/snakeCase.js";
2
- import { $ } from "../lib/$.mjs";
3
- import { readdir } from "fs/promises";
4
4
  import { resolve } from "path";
5
- import { mkdirp } from "fs-extra";
6
- import { writeFile } from "fs/promises";
5
+ import { $ } from "../lib/$.mjs";
7
6
  const getNextMigrationNumber = async () => {
8
7
  await mkdirp(resolve(process.cwd(), "./migrations"));
9
8
  const files = await readdir(resolve(process.cwd(), "./migrations"));
@@ -1,6 +1,6 @@
1
- import { fileURLToPath } from "url";
2
- import { join } from "path";
3
1
  import debug from "debug";
2
+ import { join } from "path";
3
+ import { fileURLToPath } from "url";
4
4
  import { runSmokeTests } from "../lib/smokeTests/runSmokeTests.mjs";
5
5
  import { isRunningInCI } from "../lib/smokeTests/utils.mjs";
6
6
  // Set up debug logging
@@ -1,15 +1,13 @@
1
- import path from "path";
2
- import { resolve } from "path";
3
- import { writeFile } from "fs/promises";
4
- import { unstable_readConfig } from "wrangler";
5
- import { createServer as createViteServer } from "vite";
6
- import tmp from "tmp-promise";
1
+ import { Lang, parse } from "@ast-grep/napi";
7
2
  import baseDebug from "debug";
8
3
  import enhancedResolve from "enhanced-resolve";
9
- import { readFile } from "fs/promises";
10
- import { Lang, parse } from "@ast-grep/napi";
11
- import { redwood } from "../vite/index.mjs";
4
+ import { readFile, writeFile } from "fs/promises";
5
+ import path, { resolve } from "path";
6
+ import tmp from "tmp-promise";
7
+ import { createServer as createViteServer } from "vite";
8
+ import { unstable_readConfig } from "wrangler";
12
9
  import { findWranglerConfig } from "../lib/findWranglerConfig.mjs";
10
+ import { redwood } from "../vite/index.mjs";
13
11
  const debug = baseDebug("rwsdk:worker-run");
14
12
  export const runWorkerScript = async (relativeScriptPath) => {
15
13
  if (!relativeScriptPath) {