@ivogt/rsc-router 0.0.0-experimental.7 → 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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ivogt/rsc-router",
3
- "version": "0.0.0-experimental.7",
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",
@@ -55,7 +55,7 @@
55
55
  },
56
56
  "./vite": {
57
57
  "types": "./src/vite/index.ts",
58
- "import": "./src/vite/index.ts"
58
+ "import": "./dist/vite/index.js"
59
59
  },
60
60
  "./types": {
61
61
  "types": "./src/vite/version.d.ts"
@@ -89,6 +89,7 @@
89
89
  },
90
90
  "files": [
91
91
  "src",
92
+ "dist",
92
93
  "README.md"
93
94
  ],
94
95
  "peerDependencies": {
@@ -117,11 +118,13 @@
117
118
  "@types/react-dom": "^19.2.3",
118
119
  "react": "^19.2.1",
119
120
  "react-dom": "^19.2.1",
121
+ "esbuild": "^0.27.0",
120
122
  "tinyexec": "^0.3.2",
121
123
  "typescript": "^5.3.0",
122
124
  "vitest": "^2.1.8"
123
125
  },
124
126
  "scripts": {
127
+ "build": "pnpm dlx esbuild src/vite/index.ts --bundle --format=esm --outfile=dist/vite/index.js --platform=node --packages=external",
125
128
  "typecheck": "tsc --noEmit",
126
129
  "test": "playwright test",
127
130
  "test:ui": "playwright test --ui",
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
+
@@ -5,47 +5,20 @@
5
5
  * appropriate aliases and exclude lists for Vite configuration.
6
6
  */
7
7
 
8
- import { existsSync, readFileSync } from "node:fs";
9
- import { resolve, dirname } from "node:path";
10
- import { fileURLToPath } from "node:url";
11
-
12
- // Get the directory of this file to find package.json
13
- const __dirname = dirname(fileURLToPath(import.meta.url));
14
-
15
- /**
16
- * Read the package name from package.json
17
- * This allows the name to change without updating hardcoded strings
18
- */
19
- function getPackageName(): string {
20
- try {
21
- // Navigate from src/vite/ to package root
22
- const packageJsonPath = resolve(__dirname, "../../package.json");
23
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
24
- return packageJson.name;
25
- } catch {
26
- // Fallback to known name if package.json read fails
27
- return "@ivogt/rsc-router";
28
- }
29
- }
8
+ import { existsSync } from "node:fs";
9
+ import { resolve } from "node:path";
10
+ import packageJson from "../../package.json" with { type: "json" };
30
11
 
31
12
  /**
32
13
  * The canonical name used in virtual entries (without scope)
33
14
  */
34
15
  const VIRTUAL_PACKAGE_NAME = "rsc-router";
35
16
 
36
- /**
37
- * Cached package name from package.json
38
- */
39
- let _packageName: string | null = null;
40
-
41
17
  /**
42
18
  * Get the published package name (e.g., "@ivogt/rsc-router")
43
19
  */
44
20
  export function getPublishedPackageName(): string {
45
- if (_packageName === null) {
46
- _packageName = getPackageName();
47
- }
48
- return _packageName;
21
+ return packageJson.name;
49
22
  }
50
23
 
51
24
  /**