@@ -50,11 +50,33 @@ export namespace BunProc {
5050 } ) ,
5151 )
5252
53+ // For github: dependencies, bun installs under the package's actual name
54+ // (from its package.json "name" field), not under the github: specifier.
55+ // Resolve the real module path by reading the installed package name from
56+ // the cache lockfile.
57+ async function resolveModulePath ( pkg : string ) : Promise < string > {
58+ const nodeModules = path . join ( Global . Path . cache , "node_modules" )
59+ if ( ! pkg . startsWith ( "github:" ) ) return path . join ( nodeModules , pkg )
60+ const lockPath = path . join ( Global . Path . cache , "bun.lock" )
61+ const lock = await Filesystem . readText ( lockPath ) . catch ( ( ) => "" )
62+ // lockfile maps "actual-name": "github:owner/repo#ref"
63+ for ( const line of lock . split ( "\n" ) ) {
64+ if ( line . includes ( pkg ) ) {
65+ const match = line . match ( / ^ \s * " ( [ ^ " ] + ) " : \s * " / )
66+ if ( match && match [ 1 ] !== pkg ) return path . join ( nodeModules , match [ 1 ] )
67+ }
68+ }
69+ // Fallback: strip github: prefix and use repo name
70+ const repoName = pkg . replace ( / ^ g i t h u b : / , "" ) . split ( "#" ) [ 0 ] . split ( "/" ) . pop ( )
71+ if ( repoName ) return path . join ( nodeModules , repoName )
72+ return path . join ( nodeModules , pkg )
73+ }
74+
5375 export async function install ( pkg : string , version = "latest" ) {
5476 // Use lock to ensure only one install at a time
5577 using _ = await Lock . write ( "bun-install" )
5678
57- const mod = path . join ( Global . Path . cache , "node_modules" , pkg )
79+ const mod = await resolveModulePath ( pkg )
5880 const pkgjsonPath = path . join ( Global . Path . cache , "package.json" )
5981 const parsed = await Filesystem . readJson < { dependencies : Record < string , string > } > ( pkgjsonPath ) . catch ( async ( ) => {
6082 const result = { dependencies : { } as Record < string , string > }
@@ -85,7 +107,7 @@ export namespace BunProc {
85107 ...( proxied ( ) || process . env . CI ? [ "--no-cache" ] : [ ] ) ,
86108 "--cwd" ,
87109 Global . Path . cache ,
88- pkg + "@" + version ,
110+ pkg . includes ( "#" ) ? pkg : pkg + "@" + version ,
89111 ]
90112
91113 // Let Bun handle registry resolution:
@@ -108,11 +130,14 @@ export namespace BunProc {
108130 )
109131 } )
110132
133+ // Re-resolve after install in case lockfile changed
134+ const installedMod = await resolveModulePath ( pkg )
135+
111136 // Resolve actual version from installed package when using "latest"
112137 // This ensures subsequent starts use the cached version until explicitly updated
113138 let resolvedVersion = version
114139 if ( version === "latest" ) {
115- const installedPkg = await Filesystem . readJson < { version ?: string } > ( path . join ( mod , "package.json" ) ) . catch (
140+ const installedPkg = await Filesystem . readJson < { version ?: string } > ( path . join ( installedMod , "package.json" ) ) . catch (
116141 ( ) => null ,
117142 )
118143 if ( installedPkg ?. version ) {
@@ -122,6 +147,6 @@ export namespace BunProc {
122147
123148 parsed . dependencies [ pkg ] = resolvedVersion
124149 await Filesystem . writeJson ( pkgjsonPath , parsed )
125- return mod
150+ return installedMod
126151 }
127152}
0 commit comments