fix: handle EEXIST race in peer dependency symlink creation

This commit is contained in:
saberzero1
2026-04-27 22:34:31 +02:00
parent 886bf6d7f6
commit 9fcc3f260c
2 changed files with 22 additions and 9 deletions

View File

@@ -127,6 +127,15 @@ function needsBuild(pluginDir) {
* 2. All other peers → symlink to the host Quartz node_modules so plugins
* share a single copy of packages like unified, vfile, rehype-raw, etc.
*/
function trySymlink(target, linkPath) {
try {
fs.symlinkSync(target, linkPath, "dir")
} catch (err) {
if (err.code === "EEXIST") return
throw err
}
}
function linkPeerPlugins(pluginDir) {
const pkgPath = path.join(pluginDir, "package.json")
if (!fs.existsSync(pkgPath)) return
@@ -134,16 +143,13 @@ function linkPeerPlugins(pluginDir) {
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"))
const peers = pkg.peerDependencies ?? {}
// Locate the host Quartz node_modules (two levels up from .quartz/plugins/<name>)
const quartzRoot = path.resolve(pluginDir, "..", "..", "..")
const hostNodeModules = path.join(quartzRoot, "node_modules")
for (const peerName of Object.keys(peers)) {
// Check if this peer is already satisfied (e.g. installed as a regular dep)
const peerNodeModulesPath = path.join(pluginDir, "node_modules", ...peerName.split("/"))
if (fs.existsSync(peerNodeModulesPath)) continue
// Case 1: @quartz-community scoped packages → sibling plugin symlink
if (peerName.startsWith("@quartz-community/")) {
const siblingPlugin = findPluginByPackageName(peerName)
if (!siblingPlugin) continue
@@ -152,15 +158,13 @@ function linkPeerPlugins(pluginDir) {
fs.mkdirSync(scopeDir, { recursive: true })
const target = path.relative(scopeDir, siblingPlugin)
fs.symlinkSync(target, peerNodeModulesPath, "dir")
trySymlink(target, peerNodeModulesPath)
continue
}
// Case 2: Other peers → resolve from host Quartz node_modules
const hostPeerPath = path.join(hostNodeModules, ...peerName.split("/"))
if (!fs.existsSync(hostPeerPath)) continue
// Ensure parent directory exists (for scoped packages like @napi-rs/simple-git)
const parts = peerName.split("/")
if (parts.length > 1) {
const scopeDir = path.join(pluginDir, "node_modules", parts[0])
@@ -170,7 +174,7 @@ function linkPeerPlugins(pluginDir) {
}
const target = path.relative(path.dirname(peerNodeModulesPath), hostPeerPath)
fs.symlinkSync(target, peerNodeModulesPath, "dir")
trySymlink(target, peerNodeModulesPath)
}
}