@cedarjs/vite 0.0.4

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 (213) hide show
  1. package/LICENSE +21 -0
  2. package/bins/rw-vite-build.mjs +61 -0
  3. package/bins/rw-vite-dev.mjs +57 -0
  4. package/bins/vite.mjs +12 -0
  5. package/dist/build/build.d.ts +21 -0
  6. package/dist/build/build.d.ts.map +1 -0
  7. package/dist/build/build.js +78 -0
  8. package/dist/buildFeServer.d.ts +6 -0
  9. package/dist/buildFeServer.d.ts.map +1 -0
  10. package/dist/buildFeServer.js +39 -0
  11. package/dist/buildRouteHooks.d.ts +3 -0
  12. package/dist/buildRouteHooks.d.ts.map +1 -0
  13. package/dist/buildRouteHooks.js +45 -0
  14. package/dist/buildRouteManifest.d.ts +6 -0
  15. package/dist/buildRouteManifest.d.ts.map +1 -0
  16. package/dist/buildRouteManifest.js +58 -0
  17. package/dist/buildRscClientAndServer.d.ts +4 -0
  18. package/dist/buildRscClientAndServer.d.ts.map +1 -0
  19. package/dist/buildRscClientAndServer.js +30 -0
  20. package/dist/bundled/react-server-dom-webpack.server.d.ts +2 -0
  21. package/dist/bundled/react-server-dom-webpack.server.d.ts.map +1 -0
  22. package/dist/bundled/react-server-dom-webpack.server.js +33529 -0
  23. package/dist/cjs/ClientRouter.d.ts +1 -0
  24. package/dist/cjs/build/build.d.ts +1 -0
  25. package/dist/cjs/build/build.js +116 -0
  26. package/dist/cjs/buildFeServer.d.ts +1 -0
  27. package/dist/cjs/buildFeServer.js +63 -0
  28. package/dist/cjs/buildRouteHooks.js +66 -0
  29. package/dist/cjs/buildRouteManifest.js +92 -0
  30. package/dist/cjs/buildRscClientAndServer.js +54 -0
  31. package/dist/cjs/client.d.ts +1 -0
  32. package/dist/cjs/clientSsr.d.ts +1 -0
  33. package/dist/cjs/devFeServer.js +153 -0
  34. package/dist/cjs/index.d.ts +1 -0
  35. package/dist/cjs/index.js +184 -0
  36. package/dist/cjs/lib/StatusError.js +36 -0
  37. package/dist/cjs/lib/entries.js +53 -0
  38. package/dist/cjs/lib/envVarDefinitions.js +87 -0
  39. package/dist/cjs/lib/getMergedConfig.js +187 -0
  40. package/dist/cjs/lib/onWarn.js +36 -0
  41. package/dist/cjs/lib/registerFwGlobalsAndShims.js +117 -0
  42. package/dist/cjs/middleware/index.js +22 -0
  43. package/dist/cjs/middleware/invokeMiddleware.js +52 -0
  44. package/dist/cjs/middleware/register.js +106 -0
  45. package/dist/cjs/middleware/types.js +16 -0
  46. package/dist/cjs/package.json +1 -0
  47. package/dist/cjs/plugins/vite-plugin-jsx-loader.js +42 -0
  48. package/dist/cjs/plugins/vite-plugin-remove-from-bundle.js +56 -0
  49. package/dist/cjs/plugins/vite-plugin-rsc-analyze.js +104 -0
  50. package/dist/cjs/plugins/vite-plugin-rsc-reload.js +75 -0
  51. package/dist/cjs/plugins/vite-plugin-rsc-routes-auto-loader.js +159 -0
  52. package/dist/cjs/plugins/vite-plugin-rsc-routes-imports.js +125 -0
  53. package/dist/cjs/plugins/vite-plugin-rsc-ssr-router-import.js +75 -0
  54. package/dist/cjs/plugins/vite-plugin-rsc-transform-client.js +229 -0
  55. package/dist/cjs/plugins/vite-plugin-rsc-transform-server.js +398 -0
  56. package/dist/cjs/plugins/vite-plugin-swap-apollo-provider.js +41 -0
  57. package/dist/cjs/rsc/rscBuildAnalyze.js +116 -0
  58. package/dist/cjs/rsc/rscBuildClient.js +91 -0
  59. package/dist/cjs/rsc/rscBuildCopyCssAssets.js +56 -0
  60. package/dist/cjs/rsc/rscBuildEntriesFile.js +115 -0
  61. package/dist/cjs/rsc/rscBuildForServer.js +157 -0
  62. package/dist/cjs/rsc/rscBuildForSsr.js +172 -0
  63. package/dist/cjs/rsc/rscBuildRwEnvVars.js +56 -0
  64. package/dist/cjs/rsc/rscRenderer.js +165 -0
  65. package/dist/cjs/rsc/rscRequestHandler.js +162 -0
  66. package/dist/cjs/rsc/rscStudioHandlers.js +154 -0
  67. package/dist/cjs/runFeServer.js +166 -0
  68. package/dist/cjs/streaming/buildForStreamingServer.js +65 -0
  69. package/dist/cjs/streaming/collectCss.js +52 -0
  70. package/dist/cjs/streaming/createReactStreamingHandler.js +173 -0
  71. package/dist/cjs/streaming/streamHelpers.js +228 -0
  72. package/dist/cjs/streaming/transforms/bufferedTransform.js +61 -0
  73. package/dist/cjs/streaming/transforms/cancelTimeoutTransform.js +34 -0
  74. package/dist/cjs/streaming/transforms/encode-decode.js +36 -0
  75. package/dist/cjs/streaming/transforms/serverInjectionTransform.js +84 -0
  76. package/dist/cjs/streaming/triggerRouteHooks.js +96 -0
  77. package/dist/cjs/types.js +16 -0
  78. package/dist/cjs/utils.js +91 -0
  79. package/dist/devFeServer.d.ts +2 -0
  80. package/dist/devFeServer.d.ts.map +1 -0
  81. package/dist/devFeServer.js +134 -0
  82. package/dist/index.d.ts +6 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +154 -0
  85. package/dist/lib/StatusError.d.ts +8 -0
  86. package/dist/lib/StatusError.d.ts.map +1 -0
  87. package/dist/lib/StatusError.js +11 -0
  88. package/dist/lib/entries.d.ts +3 -0
  89. package/dist/lib/entries.d.ts.map +1 -0
  90. package/dist/lib/entries.js +32 -0
  91. package/dist/lib/envVarDefinitions.d.ts +14 -0
  92. package/dist/lib/envVarDefinitions.d.ts.map +1 -0
  93. package/dist/lib/envVarDefinitions.js +53 -0
  94. package/dist/lib/getMergedConfig.d.ts +11 -0
  95. package/dist/lib/getMergedConfig.d.ts.map +1 -0
  96. package/dist/lib/getMergedConfig.js +153 -0
  97. package/dist/lib/onWarn.d.ts +3 -0
  98. package/dist/lib/onWarn.d.ts.map +1 -0
  99. package/dist/lib/onWarn.js +12 -0
  100. package/dist/lib/registerFwGlobalsAndShims.d.ts +12 -0
  101. package/dist/lib/registerFwGlobalsAndShims.d.ts.map +1 -0
  102. package/dist/lib/registerFwGlobalsAndShims.js +83 -0
  103. package/dist/middleware/index.d.ts +2 -0
  104. package/dist/middleware/index.d.ts.map +1 -0
  105. package/dist/middleware/index.js +1 -0
  106. package/dist/middleware/invokeMiddleware.d.ts +14 -0
  107. package/dist/middleware/invokeMiddleware.d.ts.map +1 -0
  108. package/dist/middleware/invokeMiddleware.js +32 -0
  109. package/dist/middleware/register.d.ts +23 -0
  110. package/dist/middleware/register.d.ts.map +1 -0
  111. package/dist/middleware/register.js +69 -0
  112. package/dist/middleware/types.d.ts +3 -0
  113. package/dist/middleware/types.d.ts.map +1 -0
  114. package/dist/middleware/types.js +0 -0
  115. package/dist/package.json +1 -0
  116. package/dist/plugins/vite-plugin-jsx-loader.d.ts +8 -0
  117. package/dist/plugins/vite-plugin-jsx-loader.d.ts.map +1 -0
  118. package/dist/plugins/vite-plugin-jsx-loader.js +18 -0
  119. package/dist/plugins/vite-plugin-remove-from-bundle.d.ts +17 -0
  120. package/dist/plugins/vite-plugin-remove-from-bundle.d.ts.map +1 -0
  121. package/dist/plugins/vite-plugin-remove-from-bundle.js +31 -0
  122. package/dist/plugins/vite-plugin-rsc-analyze.d.ts +3 -0
  123. package/dist/plugins/vite-plugin-rsc-analyze.d.ts.map +1 -0
  124. package/dist/plugins/vite-plugin-rsc-analyze.js +70 -0
  125. package/dist/plugins/vite-plugin-rsc-reload.d.ts +3 -0
  126. package/dist/plugins/vite-plugin-rsc-reload.d.ts.map +1 -0
  127. package/dist/plugins/vite-plugin-rsc-reload.js +41 -0
  128. package/dist/plugins/vite-plugin-rsc-routes-auto-loader.d.ts +3 -0
  129. package/dist/plugins/vite-plugin-rsc-routes-auto-loader.d.ts.map +1 -0
  130. package/dist/plugins/vite-plugin-rsc-routes-auto-loader.js +130 -0
  131. package/dist/plugins/vite-plugin-rsc-routes-imports.d.ts +3 -0
  132. package/dist/plugins/vite-plugin-rsc-routes-imports.d.ts.map +1 -0
  133. package/dist/plugins/vite-plugin-rsc-routes-imports.js +96 -0
  134. package/dist/plugins/vite-plugin-rsc-ssr-router-import.d.ts +7 -0
  135. package/dist/plugins/vite-plugin-rsc-ssr-router-import.d.ts.map +1 -0
  136. package/dist/plugins/vite-plugin-rsc-ssr-router-import.js +41 -0
  137. package/dist/plugins/vite-plugin-rsc-transform-client.d.ts +3 -0
  138. package/dist/plugins/vite-plugin-rsc-transform-client.d.ts.map +1 -0
  139. package/dist/plugins/vite-plugin-rsc-transform-client.js +195 -0
  140. package/dist/plugins/vite-plugin-rsc-transform-server.d.ts +3 -0
  141. package/dist/plugins/vite-plugin-rsc-transform-server.d.ts.map +1 -0
  142. package/dist/plugins/vite-plugin-rsc-transform-server.js +364 -0
  143. package/dist/plugins/vite-plugin-swap-apollo-provider.d.ts +12 -0
  144. package/dist/plugins/vite-plugin-swap-apollo-provider.d.ts.map +1 -0
  145. package/dist/plugins/vite-plugin-swap-apollo-provider.js +17 -0
  146. package/dist/rsc/rscBuildAnalyze.d.ts +16 -0
  147. package/dist/rsc/rscBuildAnalyze.d.ts.map +1 -0
  148. package/dist/rsc/rscBuildAnalyze.js +92 -0
  149. package/dist/rsc/rscBuildClient.d.ts +7 -0
  150. package/dist/rsc/rscBuildClient.d.ts.map +1 -0
  151. package/dist/rsc/rscBuildClient.js +67 -0
  152. package/dist/rsc/rscBuildCopyCssAssets.d.ts +7 -0
  153. package/dist/rsc/rscBuildCopyCssAssets.d.ts.map +1 -0
  154. package/dist/rsc/rscBuildCopyCssAssets.js +22 -0
  155. package/dist/rsc/rscBuildEntriesFile.d.ts +10 -0
  156. package/dist/rsc/rscBuildEntriesFile.d.ts.map +1 -0
  157. package/dist/rsc/rscBuildEntriesFile.js +81 -0
  158. package/dist/rsc/rscBuildForServer.d.ts +7 -0
  159. package/dist/rsc/rscBuildForServer.d.ts.map +1 -0
  160. package/dist/rsc/rscBuildForServer.js +133 -0
  161. package/dist/rsc/rscBuildForSsr.d.ts +9 -0
  162. package/dist/rsc/rscBuildForSsr.d.ts.map +1 -0
  163. package/dist/rsc/rscBuildForSsr.js +138 -0
  164. package/dist/rsc/rscBuildRwEnvVars.d.ts +10 -0
  165. package/dist/rsc/rscBuildRwEnvVars.d.ts.map +1 -0
  166. package/dist/rsc/rscBuildRwEnvVars.js +22 -0
  167. package/dist/rsc/rscRenderer.d.ts +9 -0
  168. package/dist/rsc/rscRenderer.d.ts.map +1 -0
  169. package/dist/rsc/rscRenderer.js +130 -0
  170. package/dist/rsc/rscRequestHandler.d.ts +10 -0
  171. package/dist/rsc/rscRequestHandler.d.ts.map +1 -0
  172. package/dist/rsc/rscRequestHandler.js +131 -0
  173. package/dist/rsc/rscStudioHandlers.d.ts +10 -0
  174. package/dist/rsc/rscStudioHandlers.d.ts.map +1 -0
  175. package/dist/rsc/rscStudioHandlers.js +120 -0
  176. package/dist/runFeServer.d.ts +2 -0
  177. package/dist/runFeServer.d.ts.map +1 -0
  178. package/dist/runFeServer.js +132 -0
  179. package/dist/streaming/buildForStreamingServer.d.ts +4 -0
  180. package/dist/streaming/buildForStreamingServer.d.ts.map +1 -0
  181. package/dist/streaming/buildForStreamingServer.js +41 -0
  182. package/dist/streaming/collectCss.d.ts +7 -0
  183. package/dist/streaming/collectCss.d.ts.map +1 -0
  184. package/dist/streaming/collectCss.js +27 -0
  185. package/dist/streaming/createReactStreamingHandler.d.ts +12 -0
  186. package/dist/streaming/createReactStreamingHandler.d.ts.map +1 -0
  187. package/dist/streaming/createReactStreamingHandler.js +139 -0
  188. package/dist/streaming/streamHelpers.d.ts +23 -0
  189. package/dist/streaming/streamHelpers.d.ts.map +1 -0
  190. package/dist/streaming/streamHelpers.js +192 -0
  191. package/dist/streaming/transforms/bufferedTransform.d.ts +2 -0
  192. package/dist/streaming/transforms/bufferedTransform.d.ts.map +1 -0
  193. package/dist/streaming/transforms/bufferedTransform.js +37 -0
  194. package/dist/streaming/transforms/cancelTimeoutTransform.d.ts +2 -0
  195. package/dist/streaming/transforms/cancelTimeoutTransform.d.ts.map +1 -0
  196. package/dist/streaming/transforms/cancelTimeoutTransform.js +10 -0
  197. package/dist/streaming/transforms/encode-decode.d.ts +3 -0
  198. package/dist/streaming/transforms/encode-decode.d.ts.map +1 -0
  199. package/dist/streaming/transforms/encode-decode.js +11 -0
  200. package/dist/streaming/transforms/serverInjectionTransform.d.ts +16 -0
  201. package/dist/streaming/transforms/serverInjectionTransform.d.ts.map +1 -0
  202. package/dist/streaming/transforms/serverInjectionTransform.js +60 -0
  203. package/dist/streaming/triggerRouteHooks.d.ts +26 -0
  204. package/dist/streaming/triggerRouteHooks.d.ts.map +1 -0
  205. package/dist/streaming/triggerRouteHooks.js +71 -0
  206. package/dist/types.d.ts +31 -0
  207. package/dist/types.d.ts.map +1 -0
  208. package/dist/types.js +0 -0
  209. package/dist/utils.d.ts +14 -0
  210. package/dist/utils.d.ts.map +1 -0
  211. package/dist/utils.js +62 -0
  212. package/inject/reactRefresh.js +7 -0
  213. package/package.json +116 -0
@@ -0,0 +1,131 @@
1
+ import { Readable } from "node:stream";
2
+ import * as DefaultFetchAPI from "@whatwg-node/fetch";
3
+ import { normalizeNodeRequest } from "@whatwg-node/server";
4
+ import busboy from "busboy";
5
+ import {
6
+ decodeReply,
7
+ decodeReplyFromBusboy
8
+ } from "../bundled/react-server-dom-webpack.server.js";
9
+ import { hasStatusCode } from "../lib/StatusError.js";
10
+ import { invoke } from "../middleware/invokeMiddleware.js";
11
+ import { renderRscToStream } from "./rscRenderer.js";
12
+ import { sendRscFlightToStudio } from "./rscStudioHandlers.js";
13
+ const BASE_PATH = "/rw-rsc/";
14
+ function createRscRequestHandler(options) {
15
+ return async (req, res, next) => {
16
+ console.log("BASE_PATH", BASE_PATH);
17
+ console.log("req.originalUrl", req.originalUrl, "req.url", req.url);
18
+ console.log("req.headers.host", req.headers.host);
19
+ console.log("req.headers['rw-rsc']", req.headers["rw-rsc"]);
20
+ const mwRouter = await options.getMiddlewareRouter();
21
+ if (mwRouter) {
22
+ const webReq = normalizeNodeRequest(req, DefaultFetchAPI);
23
+ const matchedMw = mwRouter.find(webReq.method, webReq.url);
24
+ const [mwResponse] = await invoke(
25
+ webReq,
26
+ matchedMw?.handler,
27
+ {
28
+ params: matchedMw?.params,
29
+ viteDevServer: options.viteDevServer
30
+ }
31
+ );
32
+ const webRes = mwResponse.toResponse();
33
+ webRes.headers.forEach((value, key) => {
34
+ res.setHeader(key, value);
35
+ });
36
+ if (mwResponse.isRedirect() || mwResponse.body) {
37
+ throw new Error(
38
+ "Not Implemented: What should happen if this RSC handler fails? And which part - Client side router?"
39
+ );
40
+ }
41
+ }
42
+ if (req.headers["rw-rsc"] !== "1") {
43
+ return next();
44
+ }
45
+ const url = new URL(req.originalUrl || "", "http://" + req.headers.host);
46
+ let rscId;
47
+ let rsaId;
48
+ let args = [];
49
+ if (url.pathname.startsWith(BASE_PATH)) {
50
+ rscId = url.pathname.split("/").pop();
51
+ rsaId = url.searchParams.get("action_id") || void 0;
52
+ console.log("rscId", rscId);
53
+ console.log("rsaId", rsaId);
54
+ if (rscId && rscId !== "_") {
55
+ res.setHeader("Content-Type", "text/x-component");
56
+ } else {
57
+ rscId = void 0;
58
+ }
59
+ args = await handleRsa(rsaId, req, args);
60
+ }
61
+ console.log("rscRequestHandler: args", args);
62
+ if (rscId || rsaId) {
63
+ const handleError = (err) => {
64
+ console.log("handleError() err", err);
65
+ if (hasStatusCode(err)) {
66
+ res.statusCode = err.statusCode;
67
+ } else {
68
+ console.info("Cannot render RSC", err);
69
+ res.statusCode = 500;
70
+ }
71
+ res.end(String(err));
72
+ };
73
+ try {
74
+ const readable = await renderRscToStream({ rscId, rsaId, args });
75
+ Readable.fromWeb(readable).pipe(res);
76
+ await sendRscFlightToStudio({
77
+ rscId,
78
+ rsaId,
79
+ args,
80
+ basePath: BASE_PATH,
81
+ req,
82
+ handleError
83
+ });
84
+ } catch (e) {
85
+ handleError(e);
86
+ }
87
+ }
88
+ };
89
+ }
90
+ async function handleRsa(rsaId, req, args) {
91
+ if (!rsaId) {
92
+ return args;
93
+ }
94
+ if (req.headers["content-type"]?.startsWith("multipart/form-data")) {
95
+ console.log("RSA: multipart/form-data");
96
+ const bb = busboy({ headers: req.headers });
97
+ const reply = decodeReplyFromBusboy(bb);
98
+ req.pipe(bb);
99
+ args = await reply;
100
+ if (args[0] instanceof FormData) {
101
+ const serializedFormData = {};
102
+ for (const [key, value] of args[0]) {
103
+ if (serializedFormData[key] !== void 0) {
104
+ if (!Array.isArray(serializedFormData[key])) {
105
+ serializedFormData[key] = [serializedFormData[key]];
106
+ }
107
+ serializedFormData[key].push(value);
108
+ } else {
109
+ serializedFormData[key] = value;
110
+ }
111
+ }
112
+ args[0] = {
113
+ __formData__: true,
114
+ state: serializedFormData
115
+ };
116
+ }
117
+ } else {
118
+ console.log("RSA: regular body");
119
+ let body = "";
120
+ for await (const chunk of req) {
121
+ body += chunk;
122
+ }
123
+ if (body) {
124
+ args = await decodeReply(body);
125
+ }
126
+ }
127
+ return args;
128
+ }
129
+ export {
130
+ createRscRequestHandler
131
+ };
@@ -0,0 +1,10 @@
1
+ import type { Request } from 'express';
2
+ import type { RenderInput } from './rscRenderer.js';
3
+ interface StudioRenderInput extends Omit<RenderInput, 'serverState'> {
4
+ basePath: string;
5
+ req: Request;
6
+ handleError: (e: Error) => void;
7
+ }
8
+ export declare const sendRscFlightToStudio: (input: StudioRenderInput) => Promise<void>;
9
+ export {};
10
+ //# sourceMappingURL=rscStudioHandlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rscStudioHandlers.d.ts","sourceRoot":"","sources":["../../src/rsc/rscStudioHandlers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAKtC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAyGnD,UAAU,iBAAkB,SAAQ,IAAI,CAAC,WAAW,EAAE,aAAa,CAAC;IAClE,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,OAAO,CAAA;IACZ,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;CAChC;AAED,eAAO,MAAM,qBAAqB,UAAiB,iBAAiB,kBA8CnE,CAAA"}
@@ -0,0 +1,120 @@
1
+ import http from "node:http";
2
+ import { getConfig, getRawConfig } from "@cedarjs/project-config";
3
+ import { renderRscToStream } from "./rscRenderer.js";
4
+ const isTest = () => {
5
+ return process.env.NODE_ENV === "test";
6
+ };
7
+ const isDevelopment = () => {
8
+ return process.env.NODE_ENV !== "production" && !isTest();
9
+ };
10
+ const isStudioEnabled = () => {
11
+ return getRawConfig()["studio"] !== void 0;
12
+ };
13
+ const shouldSendToStudio = () => {
14
+ return isStudioEnabled() && !isDevelopment();
15
+ };
16
+ const getStudioPort = () => {
17
+ return getConfig().studio.basePort;
18
+ };
19
+ const processRenderRscStream = async (readable) => {
20
+ return new Promise((resolve, reject) => {
21
+ const chunks = [];
22
+ const writable = new WritableStream({
23
+ write(chunk) {
24
+ chunks.push(chunk);
25
+ },
26
+ close() {
27
+ resolve(Buffer.concat(chunks).toString("utf8"));
28
+ }
29
+ });
30
+ readable.pipeTo(writable).catch((error) => reject(error));
31
+ });
32
+ };
33
+ const postFlightToStudio = (payload, metadata) => {
34
+ if (!shouldSendToStudio()) {
35
+ return;
36
+ }
37
+ const base64Payload = Buffer.from(payload).toString("base64");
38
+ const encodedMetadata = Buffer.from(JSON.stringify(metadata)).toString(
39
+ "base64"
40
+ );
41
+ const jsonBody = JSON.stringify({
42
+ flight: {
43
+ encodedPayload: base64Payload,
44
+ encoding: "base64",
45
+ encodedMetadata
46
+ }
47
+ });
48
+ const options = {
49
+ hostname: "localhost",
50
+ port: getStudioPort(),
51
+ path: "/.redwood/functions/rsc-flight",
52
+ method: "POST",
53
+ headers: {
54
+ "Content-Type": "application/json",
55
+ "Content-Length": Buffer.byteLength(jsonBody)
56
+ }
57
+ };
58
+ const req = http.request(options, (res) => {
59
+ res.setEncoding("utf8");
60
+ });
61
+ req.on("error", (e) => {
62
+ console.error("An error occurred sending the Flight Payload to Studio");
63
+ console.error(e);
64
+ });
65
+ req.write(jsonBody);
66
+ req.end();
67
+ };
68
+ const createStudioFlightHandler = (readable, metadata) => {
69
+ processRenderRscStream(readable).then((payload) => {
70
+ console.debug("Sending RSC Rendered stream to Studio");
71
+ postFlightToStudio(payload, metadata);
72
+ console.debug("Sent RSC Rendered stream to Studio");
73
+ console.debug("payload to Studio:", payload);
74
+ console.debug("metadata to Studio:", metadata);
75
+ }).catch((error) => {
76
+ console.error("An error occurred getting RSC Rendered steam:", error);
77
+ });
78
+ };
79
+ const sendRscFlightToStudio = async (input) => {
80
+ if (!shouldSendToStudio()) {
81
+ console.debug("Studio is not enabled");
82
+ return;
83
+ }
84
+ const { rscId, rsaId, args, basePath, req, handleError } = input;
85
+ try {
86
+ const startedAt = Date.now();
87
+ const start = performance.now();
88
+ const readable = await renderRscToStream({ rscId, rsaId, args });
89
+ const endedAt = Date.now();
90
+ const end = performance.now();
91
+ const duration = end - start;
92
+ const metadata = {
93
+ rsc: {
94
+ rscId,
95
+ rsaId,
96
+ args
97
+ },
98
+ request: {
99
+ basePath,
100
+ originalUrl: req.originalUrl,
101
+ url: req.url,
102
+ headers: req.headers
103
+ },
104
+ performance: {
105
+ startedAt,
106
+ endedAt,
107
+ duration
108
+ }
109
+ };
110
+ createStudioFlightHandler(readable, metadata);
111
+ } catch (e) {
112
+ if (e instanceof Error) {
113
+ console.error("An error occurred rendering RSC and sending to Studio:", e);
114
+ handleError(e);
115
+ }
116
+ }
117
+ };
118
+ export {
119
+ sendRscFlightToStudio
120
+ };
@@ -0,0 +1,2 @@
1
+ export declare function runFeServer(): Promise<void>;
2
+ //# sourceMappingURL=runFeServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runFeServer.d.ts","sourceRoot":"","sources":["../src/runFeServer.ts"],"names":[],"mappings":"AAkDA,wBAAsB,WAAW,kBAsJhC"}
@@ -0,0 +1,132 @@
1
+ import path from "node:path";
2
+ import url from "node:url";
3
+ import { createServerAdapter } from "@whatwg-node/server";
4
+ import { config as loadDotEnv } from "dotenv-defaults";
5
+ import express from "express";
6
+ import { createProxyMiddleware } from "http-proxy-middleware";
7
+ import WebSocket, { WebSocketServer } from "ws";
8
+ import { getConfig, getPaths } from "@cedarjs/project-config";
9
+ import { getRscStylesheetLinkGenerator } from "@cedarjs/router/rscCss";
10
+ import { createPerRequestMap, createServerStorage } from "@cedarjs/server-store";
11
+ import { registerFwGlobalsAndShims } from "./lib/registerFwGlobalsAndShims.js";
12
+ import { invoke } from "./middleware/invokeMiddleware.js";
13
+ import { createMiddlewareRouter } from "./middleware/register.js";
14
+ import { createReactStreamingHandler } from "./streaming/createReactStreamingHandler.js";
15
+ import { convertExpressHeaders, getFullUrl } from "./utils.js";
16
+ loadDotEnv({
17
+ path: path.join(getPaths().base, ".env"),
18
+ defaults: path.join(getPaths().base, ".env.defaults"),
19
+ // @ts-expect-error - Old typings. @types/dotenv-defaults depends on dotenv
20
+ // v8. dotenv-defaults uses dotenv v14
21
+ multiline: true
22
+ });
23
+ async function runFeServer() {
24
+ const app = express();
25
+ const rwPaths = getPaths();
26
+ const rwConfig = getConfig();
27
+ const rscEnabled = rwConfig.experimental?.rsc?.enabled;
28
+ registerFwGlobalsAndShims();
29
+ if (rscEnabled) {
30
+ const { setClientEntries } = await import("./rsc/rscRenderer.js");
31
+ createWebSocketServer();
32
+ try {
33
+ await setClientEntries();
34
+ } catch (e) {
35
+ console.error("Failed to load client entries");
36
+ console.error(e);
37
+ process.exit(1);
38
+ }
39
+ }
40
+ const routeManifestUrl = url.pathToFileURL(rwPaths.web.routeManifest).href;
41
+ const routeManifest = (await import(routeManifestUrl, { with: { type: "json" } })).default;
42
+ const clientBuildManifestUrl = url.pathToFileURL(
43
+ path.join(rwPaths.web.distBrowser, "client-build-manifest.json")
44
+ ).href;
45
+ const clientBuildManifest = (await import(clientBuildManifestUrl, { with: { type: "json" } })).default;
46
+ const clientEntry = rscEnabled ? clientBuildManifest["entry.client.tsx"] || clientBuildManifest["entry.client.jsx"] : Object.values(clientBuildManifest).find(
47
+ (manifestItem) => manifestItem.isEntry
48
+ );
49
+ if (!clientEntry) {
50
+ throw new Error("Could not find client entry in build manifest");
51
+ }
52
+ const middlewareRouter = await createMiddlewareRouter();
53
+ const serverStorage = createServerStorage();
54
+ const handleWithMiddleware = () => {
55
+ return createServerAdapter(async (req) => {
56
+ const matchedMw = middlewareRouter.find(req.method, req.url);
57
+ const handler = matchedMw?.handler;
58
+ if (!matchedMw) {
59
+ return new Response("No middleware found", { status: 404 });
60
+ }
61
+ const [mwRes] = await invoke(req, handler, {
62
+ params: matchedMw?.params
63
+ });
64
+ return mwRes.toResponse();
65
+ });
66
+ };
67
+ app.use(
68
+ "/assets",
69
+ express.static(rwPaths.web.distBrowser + "/assets", { index: false })
70
+ );
71
+ app.use("*", (req, _res, next) => {
72
+ const fullUrl = getFullUrl(req, rscEnabled);
73
+ const headers = convertExpressHeaders(req.headersDistinct);
74
+ const perReqStore = createPerRequestMap({ headers, fullUrl });
75
+ serverStorage.run(perReqStore, next);
76
+ });
77
+ app.use(
78
+ rwConfig.web.apiUrl,
79
+ createProxyMiddleware({
80
+ changeOrigin: false,
81
+ // Using 127.0.0.1 to force ipv4. With `localhost` you don't really know
82
+ // if it's going to be ipv4 or ipv6
83
+ target: `http://127.0.0.1:${rwConfig.api.port}`
84
+ })
85
+ );
86
+ if (rscEnabled) {
87
+ const { createRscRequestHandler } = await import("./rsc/rscRequestHandler.js");
88
+ app.use(
89
+ "/rw-rsc",
90
+ createRscRequestHandler({
91
+ getMiddlewareRouter: async () => middlewareRouter
92
+ })
93
+ );
94
+ }
95
+ app.use(express.static(rwPaths.web.distBrowser, { index: false }));
96
+ const getStylesheetLinks = rscEnabled ? getRscStylesheetLinkGenerator(clientEntry.css) : () => clientEntry.css || [];
97
+ const routeHandler = await createReactStreamingHandler({
98
+ routes: Object.values(routeManifest),
99
+ clientEntryPath: clientEntry.file,
100
+ getStylesheetLinks,
101
+ getMiddlewareRouter: async () => middlewareRouter
102
+ });
103
+ app.get("*", createServerAdapter(routeHandler));
104
+ app.post("*", handleWithMiddleware());
105
+ app.listen(rwConfig.web.port);
106
+ console.log(
107
+ `Started production FE server on http://localhost:${rwConfig.web.port}`
108
+ );
109
+ }
110
+ function createWebSocketServer() {
111
+ const wsServer = new WebSocketServer({ port: 18998 });
112
+ wsServer.on("connection", (ws) => {
113
+ console.log("A new client connected.");
114
+ ws.on("message", (data) => {
115
+ const message = data.toString();
116
+ console.log("runFeServer.ts: Received message:");
117
+ console.log(message.slice(0, 120) + "...");
118
+ wsServer.clients.forEach((client) => {
119
+ if (client.readyState === WebSocket.OPEN) {
120
+ client.send(message);
121
+ }
122
+ });
123
+ });
124
+ ws.on("close", () => {
125
+ console.log("A client disconnected.");
126
+ });
127
+ });
128
+ }
129
+ runFeServer();
130
+ export {
131
+ runFeServer
132
+ };
@@ -0,0 +1,4 @@
1
+ export declare function buildForStreamingServer({ verbose, }: {
2
+ verbose?: boolean;
3
+ }): Promise<void>;
4
+ //# sourceMappingURL=buildForStreamingServer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildForStreamingServer.d.ts","sourceRoot":"","sources":["../../src/streaming/buildForStreamingServer.ts"],"names":[],"mappings":"AAKA,wBAAsB,uBAAuB,CAAC,EAC5C,OAAe,GAChB,EAAE;IACD,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,iBAkCA"}
@@ -0,0 +1,41 @@
1
+ import { build as viteBuild } from "vite";
2
+ import { cjsInterop } from "vite-plugin-cjs-interop";
3
+ import { getPaths } from "@cedarjs/project-config";
4
+ async function buildForStreamingServer({
5
+ verbose = false
6
+ }) {
7
+ console.log("Starting streaming server build...\n");
8
+ const rwPaths = getPaths();
9
+ if (!rwPaths.web.viteConfig) {
10
+ throw new Error("Vite config not found");
11
+ }
12
+ await viteBuild({
13
+ configFile: rwPaths.web.viteConfig,
14
+ plugins: [
15
+ cjsInterop({
16
+ dependencies: [
17
+ // Skip ESM modules: rwjs/auth, rwjs/web, rwjs/auth-*-middleware, rwjs/router
18
+ "@cedarjs/forms",
19
+ "@cedarjs/prerender/*",
20
+ "@cedarjs/auth-*-api",
21
+ "@cedarjs/auth-*-web"
22
+ ]
23
+ })
24
+ ],
25
+ build: {
26
+ // TODO (RSC): Remove `minify: false` when we don't need to debug as often
27
+ minify: false,
28
+ outDir: rwPaths.web.distSsr,
29
+ ssr: true,
30
+ emptyOutDir: true
31
+ },
32
+ envFile: false,
33
+ define: {
34
+ "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV)
35
+ },
36
+ logLevel: verbose ? "info" : "warn"
37
+ });
38
+ }
39
+ export {
40
+ buildForStreamingServer
41
+ };
@@ -0,0 +1,7 @@
1
+ import type { ViteDevServer, ModuleNode } from 'vite';
2
+ /**
3
+ * Collect SSR CSS for Vite
4
+ */
5
+ export declare const componentsModules: (components: string[], vite: ViteDevServer) => Set<ModuleNode>;
6
+ export declare const collectCssPaths: (mods: Set<ModuleNode>, cssLinks?: Set<string>, checkedComponents?: Set<unknown>) => Set<string>;
7
+ //# sourceMappingURL=collectCss.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collectCss.d.ts","sourceRoot":"","sources":["../../src/streaming/collectCss.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA;AAGrD;;GAEG;AACH,eAAO,MAAM,iBAAiB,eAChB,MAAM,EAAE,QACd,aAAa,oBAUpB,CAAA;AAED,eAAO,MAAM,eAAe,SACpB,GAAG,CAAC,UAAU,CAAC,0EAmBtB,CAAA"}
@@ -0,0 +1,27 @@
1
+ import { normalizePath } from "vite";
2
+ const componentsModules = (components, vite) => {
3
+ const matchedModules = /* @__PURE__ */ new Set();
4
+ components.forEach((component) => {
5
+ const modules = vite.moduleGraph.getModulesByFile(normalizePath(component));
6
+ modules?.forEach((mod) => {
7
+ matchedModules.add(mod);
8
+ });
9
+ });
10
+ return matchedModules;
11
+ };
12
+ const collectCssPaths = (mods, cssLinks = /* @__PURE__ */ new Set(), checkedComponents = /* @__PURE__ */ new Set()) => {
13
+ for (const mod of mods) {
14
+ if (mod.file?.endsWith(".scss") || mod.file?.endsWith(".css") || mod.file?.endsWith(".less")) {
15
+ cssLinks.add(mod.url);
16
+ }
17
+ if (mod.importedModules.size > 0 && !checkedComponents.has(mod.id)) {
18
+ checkedComponents.add(mod.id);
19
+ collectCssPaths(mod.importedModules, cssLinks, checkedComponents);
20
+ }
21
+ }
22
+ return cssLinks;
23
+ };
24
+ export {
25
+ collectCssPaths,
26
+ componentsModules
27
+ };
@@ -0,0 +1,12 @@
1
+ import type Router from 'find-my-way';
2
+ import type { ViteDevServer } from 'vite';
3
+ import type { RouteSpec, RWRouteManifestItem } from '@cedarjs/internal';
4
+ interface CreateReactStreamingHandlerOptions {
5
+ routes: RWRouteManifestItem[];
6
+ clientEntryPath: string;
7
+ getStylesheetLinks: (route?: RWRouteManifestItem | RouteSpec) => string[];
8
+ getMiddlewareRouter: () => Promise<Router.Instance<any>>;
9
+ }
10
+ export declare const createReactStreamingHandler: ({ routes, clientEntryPath, getStylesheetLinks, getMiddlewareRouter, }: CreateReactStreamingHandlerOptions, viteDevServer?: ViteDevServer) => Promise<(req: Request) => Promise<Response>>;
11
+ export {};
12
+ //# sourceMappingURL=createReactStreamingHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createReactStreamingHandler.d.ts","sourceRoot":"","sources":["../../src/streaming/createReactStreamingHandler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AAGrC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAIzC,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAcvE,UAAU,kCAAkC;IAC1C,MAAM,EAAE,mBAAmB,EAAE,CAAA;IAC7B,eAAe,EAAE,MAAM,CAAA;IACvB,kBAAkB,EAAE,CAAC,KAAK,CAAC,EAAE,mBAAmB,GAAG,SAAS,KAAK,MAAM,EAAE,CAAA;IACzE,mBAAmB,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAA;CACzD;AAOD,eAAO,MAAM,2BAA2B,0EAMnC,kCAAkC,kBACrB,aAAa,mBA6BV,OAAO,uBA8I3B,CAAA"}
@@ -0,0 +1,139 @@
1
+ import path from "path";
2
+ import { Response } from "@whatwg-node/fetch";
3
+ import { createIsbotFromList, list as isbotList } from "isbot";
4
+ import { middlewareDefaultAuthProviderState } from "@cedarjs/auth/dist/AuthProvider/AuthProviderState.js";
5
+ import { getAppRouteHook, getConfig, getPaths } from "@cedarjs/project-config";
6
+ import { matchPath } from "@cedarjs/router/util";
7
+ import { MiddlewareResponse } from "@cedarjs/web/middleware";
8
+ import { invoke } from "../middleware/invokeMiddleware.js";
9
+ import { makeFilePath, ssrLoadEntryServer } from "../utils.js";
10
+ import { reactRenderToStreamResponse } from "./streamHelpers.js";
11
+ import { loadAndRunRouteHooks } from "./triggerRouteHooks.js";
12
+ const isbot = createIsbotFromList(
13
+ isbotList.filter((record) => !record.includes("chrome-lighthouse"))
14
+ );
15
+ const createReactStreamingHandler = async ({
16
+ routes,
17
+ clientEntryPath,
18
+ getStylesheetLinks,
19
+ getMiddlewareRouter
20
+ }, viteDevServer) => {
21
+ const rwPaths = getPaths();
22
+ const rwConfig = getConfig();
23
+ const isProd = !viteDevServer;
24
+ const middlewareRouter = await getMiddlewareRouter();
25
+ let entryServerImport;
26
+ let fallbackDocumentImport;
27
+ const rscEnabled = rwConfig.experimental?.rsc?.enabled;
28
+ if (isProd) {
29
+ if (rscEnabled) {
30
+ entryServerImport = await import(makeFilePath(rwPaths.web.distSsrEntryServer));
31
+ } else {
32
+ entryServerImport = await import(makeFilePath(rwPaths.web.distSsrEntryServer));
33
+ }
34
+ fallbackDocumentImport = await import(makeFilePath(rwPaths.web.distSsrDocument));
35
+ }
36
+ return async (req) => {
37
+ let mwResponse = MiddlewareResponse.next();
38
+ let decodedAuthState = {
39
+ ...middlewareDefaultAuthProviderState,
40
+ cookieHeader: req.headers.get("cookie"),
41
+ roles: []
42
+ };
43
+ let currentRoute;
44
+ let parsedParams = {};
45
+ const currentUrl = new URL(req.url);
46
+ for (const route of routes) {
47
+ const { match, ...rest } = matchPath(
48
+ route.pathDefinition,
49
+ currentUrl.pathname
50
+ );
51
+ if (match) {
52
+ currentRoute = route;
53
+ parsedParams = rest;
54
+ break;
55
+ }
56
+ }
57
+ const cssLinks = getStylesheetLinks(currentRoute);
58
+ if (middlewareRouter) {
59
+ const matchedMw = middlewareRouter.find(req.method, req.url);
60
+ [mwResponse, decodedAuthState] = await invoke(
61
+ req,
62
+ matchedMw?.handler,
63
+ {
64
+ route: currentRoute,
65
+ cssPaths: cssLinks,
66
+ params: matchedMw?.params,
67
+ viteDevServer
68
+ }
69
+ );
70
+ if (mwResponse.isRedirect() || mwResponse.body) {
71
+ return mwResponse.toResponse();
72
+ }
73
+ }
74
+ if (!currentRoute) {
75
+ throw new Error("404 handling not implemented");
76
+ }
77
+ if (currentRoute.redirect) {
78
+ return new Response(null, {
79
+ status: 302,
80
+ headers: {
81
+ Location: currentRoute.redirect.to
82
+ }
83
+ });
84
+ }
85
+ if (!isProd) {
86
+ entryServerImport = await ssrLoadEntryServer(viteDevServer);
87
+ fallbackDocumentImport = await viteDevServer.ssrLoadModule(
88
+ rwPaths.web.document
89
+ );
90
+ }
91
+ const ServerEntry = entryServerImport.ServerEntry || entryServerImport.default;
92
+ const FallbackDocument = fallbackDocumentImport.Document || fallbackDocumentImport.default;
93
+ let metaTags = [];
94
+ let routeHookPath = currentRoute.routeHooks;
95
+ if (isProd) {
96
+ routeHookPath = currentRoute.routeHooks ? path.join(rwPaths.web.distRouteHooks, currentRoute.routeHooks) : null;
97
+ }
98
+ const routeHookOutput = await loadAndRunRouteHooks({
99
+ paths: [getAppRouteHook(isProd), routeHookPath],
100
+ reqMeta: {
101
+ req,
102
+ parsedParams
103
+ },
104
+ viteDevServer
105
+ });
106
+ metaTags = routeHookOutput.meta;
107
+ const jsBundles = [viteDevServer ? clientEntryPath : "/" + clientEntryPath];
108
+ if (currentRoute.bundle) {
109
+ jsBundles.push("/" + currentRoute.bundle);
110
+ }
111
+ const isSeoCrawler = isbot(req.headers.get("user-agent") || "");
112
+ const reactResponse = await reactRenderToStreamResponse(
113
+ mwResponse,
114
+ {
115
+ ServerEntry,
116
+ FallbackDocument,
117
+ currentUrl,
118
+ metaTags,
119
+ cssLinks,
120
+ isProd,
121
+ jsBundles,
122
+ authState: decodedAuthState
123
+ },
124
+ {
125
+ waitForAllReady: isSeoCrawler,
126
+ onError: (err) => {
127
+ if (!isProd && viteDevServer) {
128
+ viteDevServer.ssrFixStacktrace(err);
129
+ }
130
+ console.error(err);
131
+ }
132
+ }
133
+ );
134
+ return reactResponse;
135
+ };
136
+ };
137
+ export {
138
+ createReactStreamingHandler
139
+ };
@@ -0,0 +1,23 @@
1
+ import type React from 'react';
2
+ import type { ServerAuthState } from '@cedarjs/auth/dist/AuthProvider/ServerAuthProvider.js';
3
+ import type { TagDescriptor } from '@cedarjs/web';
4
+ import type { MiddlewareResponse } from '@cedarjs/web/middleware';
5
+ import type { ServerEntryType } from '../types.js';
6
+ interface RenderToStreamArgs {
7
+ ServerEntry: ServerEntryType;
8
+ FallbackDocument: React.FunctionComponent;
9
+ currentUrl: URL;
10
+ metaTags: TagDescriptor[];
11
+ cssLinks: string[];
12
+ isProd: boolean;
13
+ jsBundles?: string[];
14
+ authState: ServerAuthState;
15
+ }
16
+ interface StreamOptions {
17
+ waitForAllReady?: boolean;
18
+ onError?: (err: Error) => void;
19
+ }
20
+ export declare function reactRenderToStreamResponse(mwRes: MiddlewareResponse, renderOptions: RenderToStreamArgs, streamOptions: StreamOptions): Promise<Response>;
21
+ export declare function importModule(mod: 'rd-server' | '__rwjs__react' | '__rwjs__location' | '__rwjs__server_auth_provider' | '__rwjs__server_inject'): Promise<any>;
22
+ export {};
23
+ //# sourceMappingURL=streamHelpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamHelpers.d.ts","sourceRoot":"","sources":["../../src/streaming/streamHelpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAQ9B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uDAAuD,CAAA;AAI5F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAGjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAYlD,UAAU,kBAAkB;IAC1B,WAAW,EAAE,eAAe,CAAA;IAC5B,gBAAgB,EAAE,KAAK,CAAC,iBAAiB,CAAA;IACzC,UAAU,EAAE,GAAG,CAAA;IACf,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;IACpB,SAAS,EAAE,eAAe,CAAA;CAC3B;AAED,UAAU,aAAa;IACrB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;CAC/B;AA2BD,wBAAsB,2BAA2B,CAC/C,KAAK,EAAE,kBAAkB,EACzB,aAAa,EAAE,kBAAkB,EACjC,aAAa,EAAE,aAAa,qBAgM7B;AA2BD,wBAAsB,YAAY,CAChC,GAAG,EACC,WAAW,GACX,eAAe,GACf,kBAAkB,GAClB,8BAA8B,GAC9B,uBAAuB,gBA2B5B"}