@ivogt/rsc-router 0.0.0-experimental.8 → 0.0.0-experimental.9

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.
@@ -675,7 +675,7 @@ import { resolve } from "node:path";
675
675
  // package.json
676
676
  var package_default = {
677
677
  name: "@ivogt/rsc-router",
678
- version: "0.0.0-experimental.8",
678
+ version: "0.0.0-experimental.9",
679
679
  type: "module",
680
680
  description: "Type-safe RSC router with partial rendering support",
681
681
  author: "Ivo Todorov",
@@ -1226,8 +1226,57 @@ async function rscRouter(options) {
1226
1226
  if (rscEntryPath) {
1227
1227
  plugins.push(createVersionInjectorPlugin(rscEntryPath));
1228
1228
  }
1229
+ plugins.push(createCjsToEsmPlugin());
1229
1230
  return plugins;
1230
1231
  }
1232
+ function createCjsToEsmPlugin() {
1233
+ return {
1234
+ name: "rsc-router:cjs-to-esm",
1235
+ enforce: "pre",
1236
+ transform(code, id) {
1237
+ const cleanId = id.split("?")[0];
1238
+ if (cleanId.includes("vendor/react-server-dom/client.browser.js") || cleanId.includes("vendor\\react-server-dom\\client.browser.js")) {
1239
+ const isProd = process.env.NODE_ENV === "production";
1240
+ const cjsFile = isProd ? "./cjs/react-server-dom-webpack-client.browser.production.js" : "./cjs/react-server-dom-webpack-client.browser.development.js";
1241
+ return {
1242
+ code: `export * from "${cjsFile}";`,
1243
+ map: null
1244
+ };
1245
+ }
1246
+ if ((cleanId.includes("vendor/react-server-dom/cjs/") || cleanId.includes("vendor\\react-server-dom\\cjs\\")) && cleanId.includes("client.browser")) {
1247
+ let transformed = code;
1248
+ const licenseMatch = transformed.match(/^\/\*\*[\s\S]*?\*\//);
1249
+ const license = licenseMatch ? licenseMatch[0] : "";
1250
+ if (license) {
1251
+ transformed = transformed.slice(license.length);
1252
+ }
1253
+ transformed = transformed.replace(
1254
+ /^\s*["']use strict["'];\s*["']production["']\s*!==\s*process\.env\.NODE_ENV\s*&&\s*\(function\s*\(\)\s*\{/,
1255
+ ""
1256
+ );
1257
+ transformed = transformed.replace(/\}\)\(\);?\s*$/, "");
1258
+ transformed = transformed.replace(
1259
+ /var\s+React\s*=\s*require\s*\(\s*["']react["']\s*\)\s*,[\s\n]+ReactDOM\s*=\s*require\s*\(\s*["']react-dom["']\s*\)\s*,/g,
1260
+ 'import React from "react";\nimport ReactDOM from "react-dom";\nvar '
1261
+ );
1262
+ transformed = transformed.replace(
1263
+ /exports\.(\w+)\s*=\s*function\s*\(/g,
1264
+ "export function $1("
1265
+ );
1266
+ transformed = transformed.replace(
1267
+ /exports\.(\w+)\s*=/g,
1268
+ "export const $1 ="
1269
+ );
1270
+ transformed = license + "\n" + transformed;
1271
+ return {
1272
+ code: transformed,
1273
+ map: null
1274
+ };
1275
+ }
1276
+ return null;
1277
+ }
1278
+ };
1279
+ }
1231
1280
  export {
1232
1281
  exposeActionId,
1233
1282
  exposeHandleId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ivogt/rsc-router",
3
- "version": "0.0.0-experimental.8",
3
+ "version": "0.0.0-experimental.9",
4
4
  "type": "module",
5
5
  "description": "Type-safe RSC router with partial rendering support",
6
6
  "author": "Ivo Todorov",
package/src/vite/index.ts CHANGED
@@ -678,6 +678,92 @@ export async function rscRouter(
678
678
  plugins.push(createVersionInjectorPlugin(rscEntryPath));
679
679
  }
680
680
 
681
+ // Add CJS to ESM transformation for react-server-dom vendor files
682
+ plugins.push(createCjsToEsmPlugin());
683
+
681
684
  return plugins;
682
685
  }
683
686
 
687
+ /**
688
+ * Transform CJS vendor files from @vitejs/plugin-rsc to ESM for browser compatibility.
689
+ * The react-server-dom vendor files are shipped as CJS which doesn't work in browsers.
690
+ */
691
+ function createCjsToEsmPlugin(): Plugin {
692
+ return {
693
+ name: "rsc-router:cjs-to-esm",
694
+ enforce: "pre",
695
+ transform(code, id) {
696
+ const cleanId = id.split("?")[0];
697
+
698
+ // Transform the client.browser.js entry point to re-export from CJS
699
+ if (
700
+ cleanId.includes("vendor/react-server-dom/client.browser.js") ||
701
+ cleanId.includes("vendor\\react-server-dom\\client.browser.js")
702
+ ) {
703
+ const isProd = process.env.NODE_ENV === "production";
704
+ const cjsFile = isProd
705
+ ? "./cjs/react-server-dom-webpack-client.browser.production.js"
706
+ : "./cjs/react-server-dom-webpack-client.browser.development.js";
707
+
708
+ return {
709
+ code: `export * from "${cjsFile}";`,
710
+ map: null,
711
+ };
712
+ }
713
+
714
+ // Transform the actual CJS files to ESM
715
+ if (
716
+ (cleanId.includes("vendor/react-server-dom/cjs/") ||
717
+ cleanId.includes("vendor\\react-server-dom\\cjs\\")) &&
718
+ cleanId.includes("client.browser")
719
+ ) {
720
+ let transformed = code;
721
+
722
+ // Extract the license comment to preserve it
723
+ const licenseMatch = transformed.match(/^\/\*\*[\s\S]*?\*\//);
724
+ const license = licenseMatch ? licenseMatch[0] : "";
725
+ if (license) {
726
+ transformed = transformed.slice(license.length);
727
+ }
728
+
729
+ // Remove "use strict" and the conditional IIFE wrapper
730
+ transformed = transformed.replace(
731
+ /^\s*["']use strict["'];\s*["']production["']\s*!==\s*process\.env\.NODE_ENV\s*&&\s*\(function\s*\(\)\s*\{/,
732
+ ""
733
+ );
734
+
735
+ // Remove the closing of the conditional IIFE at the end
736
+ transformed = transformed.replace(/\}\)\(\);?\s*$/, "");
737
+
738
+ // Replace require('react') and require('react-dom') with imports
739
+ transformed = transformed.replace(
740
+ /var\s+React\s*=\s*require\s*\(\s*["']react["']\s*\)\s*,[\s\n]+ReactDOM\s*=\s*require\s*\(\s*["']react-dom["']\s*\)\s*,/g,
741
+ 'import React from "react";\nimport ReactDOM from "react-dom";\nvar '
742
+ );
743
+
744
+ // Transform exports.xyz = function() to export function xyz()
745
+ transformed = transformed.replace(
746
+ /exports\.(\w+)\s*=\s*function\s*\(/g,
747
+ "export function $1("
748
+ );
749
+
750
+ // Transform exports.xyz = value to export const xyz = value
751
+ transformed = transformed.replace(
752
+ /exports\.(\w+)\s*=/g,
753
+ "export const $1 ="
754
+ );
755
+
756
+ // Reconstruct with license at the top
757
+ transformed = license + "\n" + transformed;
758
+
759
+ return {
760
+ code: transformed,
761
+ map: null,
762
+ };
763
+ }
764
+
765
+ return null;
766
+ },
767
+ };
768
+ }
769
+