@@ -35,134 +35,13 @@ const getPackageManagerInfo = (targetDir: string) => {
3535 return pnpmResult ;
3636} ;
3737
38- /**
39- * @summary Workaround for pnpm's local tarball dependency resolution.
40- *
41- * @description
42- * When installing a new version of the SDK from a local tarball (e.g., during
43- * development with `rwsync`), pnpm creates a new, uniquely-named directory in
44- * the `.pnpm` store (e.g., `rwsdk@file+...`).
45- *
46- * A challenge arises when other packages list `rwsdk` as a peer dependency.
47- * pnpm may not consistently update the symlinks for these peer dependencies
48- * to point to the newest `rwsdk` instance. This can result in a state where
49- * multiple versions of `rwsdk` coexist in `node_modules`, with some parts of
50- * the application using a stale version.
51- *
52- * This function addresses the issue by:
53- * 1. Identifying the most recently installed `rwsdk` instance in the `.pnpm`
54- * store after a `pnpm install` run.
55- * 2. Forcefully updating the top-level `node_modules/rwsdk` symlink to point
56- * to this new instance.
57- * 3. Traversing all other `rwsdk`-related directories in the `.pnpm` store
58- * and updating their internal `rwsdk` symlinks to also point to the correct
59- * new instance.
60- *
61- * I am sorry for this ugly hack, I am sure there is a better way, and that it is me
62- * doing something wrong. The aim is not to go down this rabbit hole right now
63- * -- @justinvdm
64- */
65- const hackyPnpmSymlinkFix = async ( targetDir : string ) => {
66- console . log ( "💣 Performing pnpm symlink fix..." ) ;
67- const pnpmDir = path . join ( targetDir , "node_modules" , ".pnpm" ) ;
68- if ( ! existsSync ( pnpmDir ) ) {
69- console . log ( " 🤔 No .pnpm directory found." ) ;
70- return ;
71- }
72-
73- try {
74- const entries = await fs . readdir ( pnpmDir ) ;
75- // Find ALL rwsdk directories, not just file-based ones, to handle
76- // all kinds of stale peer dependencies.
77- const rwsdkDirs = entries . filter ( ( e ) => e . startsWith ( "rwsdk@" ) ) ;
78- console . log ( " Found rwsdk directories:" , rwsdkDirs ) ;
79-
80- if ( rwsdkDirs . length === 0 ) {
81- console . log ( " 🤔 No rwsdk directories found to hack." ) ;
82- return ;
83- }
84-
85- let latestDir = "" ;
86- let latestMtime = new Date ( 0 ) ;
87-
88- for ( const dir of rwsdkDirs ) {
89- const fullPath = path . join ( pnpmDir , dir ) ;
90- const stats = await fs . stat ( fullPath ) ;
91- if ( stats . mtime > latestMtime ) {
92- latestMtime = stats . mtime ;
93- latestDir = dir ;
94- }
95- }
96-
97- console . log ( " Latest rwsdk directory:" , latestDir ) ;
98-
99- if ( ! latestDir ) {
100- console . log ( " 🤔 Could not determine the latest rwsdk directory." ) ;
101- return ;
102- }
103-
104- const goldenSourcePath = path . join (
105- pnpmDir ,
106- latestDir ,
107- "node_modules" ,
108- "rwsdk" ,
109- ) ;
110-
111- if ( ! existsSync ( goldenSourcePath ) ) {
112- console . error (
113- ` ❌ Golden source path does not exist: ${ goldenSourcePath } ` ,
114- ) ;
115- return ;
116- }
117- console . log ( ` 🎯 Golden rwsdk path is: ${ goldenSourcePath } ` ) ;
118-
119- // 1. Fix top-level symlink
120- const topLevelSymlink = path . join ( targetDir , "node_modules" , "rwsdk" ) ;
121- await fs . rm ( topLevelSymlink , { recursive : true , force : true } ) ;
122- await fs . symlink ( goldenSourcePath , topLevelSymlink , "dir" ) ;
123- console . log ( ` ✅ Symlinked ${ topLevelSymlink } -> ${ goldenSourcePath } ` ) ;
124-
125- // 2. Fix peer dependency symlinks
126- const allPnpmDirs = await fs . readdir ( pnpmDir ) ;
127- for ( const dir of allPnpmDirs ) {
128- if ( dir === latestDir || ! dir . includes ( "rwsdk" ) ) continue ;
129-
130- const peerSymlink = path . join ( pnpmDir , dir , "node_modules" , "rwsdk" ) ;
131- if ( existsSync ( peerSymlink ) ) {
132- await fs . rm ( peerSymlink , { recursive : true , force : true } ) ;
133- await fs . symlink ( goldenSourcePath , peerSymlink , "dir" ) ;
134- console . log ( ` ✅ Hijacked symlink in ${ dir } ` ) ;
135- }
136- }
137- } catch ( error ) {
138- console . error ( " ❌ Failed during hacky pnpm symlink fix:" , error ) ;
139- }
140- } ;
141-
142- const performFullSync = async (
143- sdkDir : string ,
144- targetDir : string ,
145- cacheBust = false ,
146- ) => {
38+ const performFullSync = async ( sdkDir : string , targetDir : string ) => {
14739 const sdkPackageJsonPath = path . join ( sdkDir , "package.json" ) ;
14840 let originalSdkPackageJson : string | null = null ;
14941 let tarballPath = "" ;
15042 let tarballName = "" ;
15143
15244 try {
153- if ( cacheBust ) {
154- console . log ( "💥 Cache-busting version for full sync..." ) ;
155- originalSdkPackageJson = await fs . readFile ( sdkPackageJsonPath , "utf-8" ) ;
156- const packageJson = JSON . parse ( originalSdkPackageJson ) ;
157- const now = Date . now ( ) ;
158- // This is a temporary version used for cache busting
159- packageJson . version = `${ packageJson . version } -dev.${ now } ` ;
160- await fs . writeFile (
161- sdkPackageJsonPath ,
162- JSON . stringify ( packageJson , null , 2 ) ,
163- ) ;
164- }
165-
16645 console . log ( "📦 Packing SDK..." ) ;
16746 const packResult = await $ ( { cwd : sdkDir } ) `npm pack` ;
16847 tarballName = packResult . stdout ?. trim ( ) ?? "" ;
@@ -186,49 +65,25 @@ const performFullSync = async (
18665 . catch ( ( ) => null ) ;
18766
18867 try {
189- if ( pm . name === "pnpm" ) {
190- console . log ( "🛠️ Using pnpm overrides to install SDK..." ) ;
191- if ( originalPackageJson ) {
192- const targetPackageJson = JSON . parse ( originalPackageJson ) ;
193- targetPackageJson . pnpm = targetPackageJson . pnpm || { } ;
194- targetPackageJson . pnpm . overrides =
195- targetPackageJson . pnpm . overrides || { } ;
196- targetPackageJson . pnpm . overrides . rwsdk = `file:${ tarballPath } ` ;
197- await fs . writeFile (
198- packageJsonPath ,
199- JSON . stringify ( targetPackageJson , null , 2 ) ,
200- ) ;
201- }
202- // We use install here, which respects the overrides.
203- // We also don't want to fail if the lockfile is out of date.
204- await $ ( "pnpm" , [ "install" , "--no-frozen-lockfile" ] , {
205- cwd : targetDir ,
206- stdio : "inherit" ,
207- } ) ;
208- if ( process . env . RWSDK_PNPM_SYMLINK_FIX ) {
209- await hackyPnpmSymlinkFix ( targetDir ) ;
210- }
68+ const cmd = pm . name ;
69+ const args = [ pm . command ] ;
70+
71+ if ( pm . name === "yarn" ) {
72+ args . push ( `file:${ tarballPath } ` ) ;
21173 } else {
212- const cmd = pm . name ;
213- const args = [ pm . command ] ;
214-
215- if ( pm . name === "yarn" ) {
216- args . push ( `file:${ tarballPath } ` ) ;
217- } else {
218- args . push ( tarballPath ) ;
219- }
220-
221- await $ ( cmd , args , {
222- cwd : targetDir ,
223- stdio : "inherit" ,
224- } ) ;
74+ args . push ( tarballPath ) ;
22575 }
76+
77+ await $ ( cmd , args , {
78+ cwd : targetDir ,
79+ stdio : "inherit" ,
80+ } ) ;
22681 } finally {
22782 if ( originalPackageJson ) {
22883 console . log ( "Restoring package.json..." ) ;
22984 await fs . writeFile ( packageJsonPath , originalPackageJson ) ;
23085 }
231- if ( originalLockfile && pm . name !== "pnpm" ) {
86+ if ( originalLockfile ) {
23287 console . log ( `Restoring ${ pm . lockFile } ...` ) ;
23388 await fs . writeFile ( lockfilePath , originalLockfile ) ;
23489 }
@@ -285,7 +140,7 @@ const performSync = async (sdkDir: string, targetDir: string) => {
285140
286141 if ( forceFullSync ) {
287142 console . log ( "🏃 Force full sync mode is enabled." ) ;
288- await performFullSync ( sdkDir , targetDir , true ) ;
143+ await performFullSync ( sdkDir , targetDir ) ;
289144 console . log ( "✅ Done syncing" ) ;
290145 return ;
291146 }
@@ -328,9 +183,7 @@ const performSync = async (sdkDir: string, targetDir: string) => {
328183
329184 if ( packageJsonChanged ) {
330185 console . log ( "📦 package.json changed, performing full sync..." ) ;
331- // We always cache-bust on a full sync now to ensure pnpm's overrides
332- // see a new version and the hacky symlink fix runs on a clean slate.
333- await performFullSync ( sdkDir , targetDir , true ) ;
186+ await performFullSync ( sdkDir , targetDir ) ;
334187 } else {
335188 await performFastSync ( sdkDir , targetDir ) ;
336189 }
@@ -353,8 +206,7 @@ export const debugSync = async (opts: DebugSyncOptions) => {
353206 }
354207
355208 // --- Watch Mode Logic ---
356- // Use global lock based on SDK directory since all instances sync from the same source
357- const lockfilePath = path . join ( sdkDir , ".rwsync.lock" ) ;
209+ const lockfilePath = path . join ( targetDir , "node_modules" , ".rwsync.lock" ) ;
358210 let release : ( ) => Promise < void > ;
359211
360212 // Ensure the directory for the lockfile exists
@@ -367,7 +219,7 @@ export const debugSync = async (opts: DebugSyncOptions) => {
367219 } catch ( e : any ) {
368220 if ( e . code === "ELOCKED" ) {
369221 console . error (
370- `❌ Another rwsync process is already running for this SDK .` ,
222+ `❌ Another rwsync process is already watching ${ targetDir } .` ,
371223 ) ;
372224 console . error (
373225 ` If this is not correct, please remove the lockfile at ${ lockfilePath } ` ,
0 commit comments