Skip to content

Commit 7b8281c

Browse files
committed
Fix rwsync some more
1 parent 8c52813 commit 7b8281c

File tree

1 file changed

+17
-165
lines changed

1 file changed

+17
-165
lines changed

sdk/src/scripts/debug-sync.mts

Lines changed: 17 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)