From c37d41edb2f221dbda6a0a2254d782f1f6e3fbeb Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Fri, 19 Dec 2025 04:43:39 +0900 Subject: [PATCH] fix(auto-update-checker): add bun.lock handling to invalidatePackage() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removes package from node_modules, package.json dependencies, AND bun.lock (workspaces.dependencies + packages) - Fixes issue where 'update available' notification appeared but actual update didn't happen on restart due to bun.lock pinning old version - Added BunLockfile interface and stripTrailingCommas helper for JSON parsing 🤖 Generated with assistance of [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) --- src/hooks/auto-update-checker/cache.ts | 48 +++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/hooks/auto-update-checker/cache.ts b/src/hooks/auto-update-checker/cache.ts index d199679..fa4b6ed 100644 --- a/src/hooks/auto-update-checker/cache.ts +++ b/src/hooks/auto-update-checker/cache.ts @@ -3,6 +3,49 @@ import * as path from "node:path" import { CACHE_DIR, PACKAGE_NAME } from "./constants" import { log } from "../../shared/logger" +interface BunLockfile { + workspaces?: { + ""?: { + dependencies?: Record + } + } + packages?: Record +} + +function stripTrailingCommas(json: string): string { + return json.replace(/,(\s*[}\]])/g, "$1") +} + +function removeFromBunLock(packageName: string): boolean { + const lockPath = path.join(CACHE_DIR, "bun.lock") + if (!fs.existsSync(lockPath)) return false + + try { + const content = fs.readFileSync(lockPath, "utf-8") + const lock = JSON.parse(stripTrailingCommas(content)) as BunLockfile + let modified = false + + if (lock.workspaces?.[""]?.dependencies?.[packageName]) { + delete lock.workspaces[""].dependencies[packageName] + modified = true + } + + if (lock.packages?.[packageName]) { + delete lock.packages[packageName] + modified = true + } + + if (modified) { + fs.writeFileSync(lockPath, JSON.stringify(lock, null, 2)) + log(`[auto-update-checker] Removed from bun.lock: ${packageName}`) + } + + return modified + } catch { + return false + } +} + export function invalidatePackage(packageName: string = PACKAGE_NAME): boolean { try { const pkgDir = path.join(CACHE_DIR, "node_modules", packageName) @@ -10,6 +53,7 @@ export function invalidatePackage(packageName: string = PACKAGE_NAME): boolean { let packageRemoved = false let dependencyRemoved = false + let lockRemoved = false if (fs.existsSync(pkgDir)) { fs.rmSync(pkgDir, { recursive: true, force: true }) @@ -28,7 +72,9 @@ export function invalidatePackage(packageName: string = PACKAGE_NAME): boolean { } } - if (!packageRemoved && !dependencyRemoved) { + lockRemoved = removeFromBunLock(packageName) + + if (!packageRemoved && !dependencyRemoved && !lockRemoved) { log(`[auto-update-checker] Package not found, nothing to invalidate: ${packageName}`) return false }