11#!/usr/bin/env -S pkgx --quiet deno^2.1 run --ext=ts --allow-sys=uid --allow-run --allow-env --allow-read --allow-write --allow-ffi
22import {
33 hooks ,
4+ Installation ,
45 Path ,
56 plumbing ,
67 SemVer ,
@@ -62,13 +63,13 @@ if (parsedArgs.help) {
6263 break ;
6364 case "local-install" :
6465 case "li" :
65- await install ( args , ` ${ Deno . env . get ( "HOME" ) ! } /.local` ) ;
66+ await install ( args , Path . home ( ) . join ( ".local" ) . string ) ;
6667 break ;
6768 case "stub" :
6869 case "shim" :
6970 // this uses the old behavior of pkgx v1, which is to install to ~/.local/bin
7071 // if we want to write to /usr/local, we need to use sudo
71- await shim ( args , ` ${ Deno . env . get ( "HOME" ) ! } /.local` ) ;
72+ await shim ( args , Path . home ( ) . join ( ".local" ) . string ) ;
7273 break ;
7374 case "uninstall" :
7475 case "rm" :
@@ -117,8 +118,9 @@ async function install(args: string[], basePath: string) {
117118 const pkgx = get_pkgx ( ) ;
118119
119120 const [ json , env ] = await query_pkgx ( pkgx , args ) ;
120- // deno-lint-ignore no-explicit-any
121- const pkg_prefixes = json . pkgs . map ( ( x : any ) => `${ x . project } /v${ x . version } ` ) ;
121+ const pkg_prefixes = json . pkgs . map ( ( x ) =>
122+ `${ x . pkg . project } /v${ x . pkg . version } `
123+ ) ;
122124
123125 const self = fromFileUrl ( import . meta. url ) ;
124126 const pkgx_dir = Deno . env . get ( "PKGX_DIR" ) || `${ Deno . env . get ( "HOME" ) } /.pkgx` ;
@@ -217,13 +219,19 @@ async function shim(args: string[], basePath: string) {
217219
218220 for ( const pkg of json . pkgs ) {
219221 for ( const bin of [ "bin" , "sbin" ] ) {
220- const bin_prefix = join ( pkg . path , bin ) ;
221- if ( ! existsSync ( bin_prefix ) ) continue ;
222- for await ( const entry of Deno . readDir ( bin_prefix ) ) {
222+ const bin_prefix = pkg . path . join ( bin ) ;
223+ if ( ! bin_prefix . exists ( ) ) continue ;
224+ for await ( const entry of Deno . readDir ( bin_prefix . string ) ) {
223225 if ( ! entry . isFile && ! entry . isSymlink ) continue ;
224226 const name = entry . name ;
227+ const quick_shim = Deno . build . os == "darwin" &&
228+ pkgx == "/usr/local/bin/pkgx" ;
229+ const interpreter = quick_shim
230+ ? "/usr/local/bin/pkgx"
231+ : "/usr/bin/env -S pkgx" ;
232+
225233 const shim =
226- `#!/usr/bin/env -S pkgx -- shebang --quiet +${ pkg . project } =${ pkg . version } -- ${ name } ` ;
234+ `#!${ interpreter } -- shebang --quiet +${ pkg . pkg . project } =${ pkg . pkg . version } -- ${ name } ` ;
227235
228236 if ( existsSync ( join ( basePath , "bin" , name ) ) ) {
229237 await Deno . remove ( join ( basePath , "bin" , name ) ) ;
@@ -237,7 +245,17 @@ async function shim(args: string[], basePath: string) {
237245 }
238246}
239247
240- async function query_pkgx ( pkgx : string , args : string [ ] ) {
248+ interface JsonResponse {
249+ runtime_env : Record < string , Record < string , string > > ;
250+ pkgs : Installation [ ] ;
251+ env : Record < string , Record < string , string > > ;
252+ pkg : Installation ;
253+ }
254+
255+ async function query_pkgx (
256+ pkgx : string ,
257+ args : string [ ] ,
258+ ) : Promise < [ JsonResponse , Record < string , string > ] > {
241259 args = args . map ( ( x ) => `+${ x } ` ) ;
242260
243261 const env : Record < string , string > = {
@@ -265,7 +283,23 @@ async function query_pkgx(pkgx: string, args: string[]) {
265283 }
266284
267285 const out = await proc . output ( ) ;
268- return [ JSON . parse ( new TextDecoder ( ) . decode ( out . stdout ) ) , env ] ;
286+ const json = JSON . parse ( new TextDecoder ( ) . decode ( out . stdout ) ) ;
287+ const pkgs =
288+ ( json . pkgs as { path : string ; project : string ; version : string } [ ] ) . map (
289+ ( x ) => {
290+ return {
291+ path : new Path ( x . path ) ,
292+ pkg : { project : x . project , version : new SemVer ( x . version ) } ,
293+ } ;
294+ } ,
295+ ) ;
296+ const pkg = pkgs . find ( ( x ) => `+${ x . pkg . project } ` == args [ 0 ] ) ! ;
297+ return [ {
298+ pkg,
299+ pkgs,
300+ env : json . env ,
301+ runtime_env : json . runtime_env ,
302+ } , env ] ;
269303}
270304
271305async function mirror_directory ( dst : string , src : string , prefix : string ) {
@@ -376,20 +410,20 @@ async function create_v_symlinks(prefix: string) {
376410}
377411
378412function expand_runtime_env (
379- // deno-lint-ignore no-explicit-any
380- json : Record < string , any > ,
413+ json : JsonResponse ,
381414 basePath : string ,
382415) {
383- const runtime_env = json . runtime_env as Record < string , string > ;
416+ const { runtime_env, pkgs } = json ;
384417
385418 //FIXME this combines all runtime env which is strictly overkill
386419 // for transitive deps that may not need it
387420
388421 const expanded : Record < string , Set < string > > = { } ;
389422 for ( const [ _project , env ] of Object . entries ( runtime_env ) ) {
390423 for ( const [ key , value ] of Object . entries ( env ) ) {
391- //TODO expand all moustaches
392- const new_value = value . replaceAll ( / \$ ? { { .* p r e f i x } } / g, basePath ) ;
424+ const pkg = pkgs . find ( ( x ) => x . pkg . project == _project ) ! . pkg ;
425+ const mm = hooks . useMoustaches ( ) . tokenize . all ( pkg , json . pkgs ) ;
426+ const new_value = hooks . useMoustaches ( ) . apply ( value , mm ) ;
393427 expanded [ key ] ??= new Set < string > ( ) ;
394428 expanded [ key ] . add ( new_value ) ;
395429 }
@@ -407,9 +441,8 @@ function expand_runtime_env(
407441 }
408442
409443 // DUMB but easiest way to fix a bug
410- // deno-lint-ignore no-explicit-any
411- const rv2 : Record < string , any > = { } ;
412- for ( const { project } of json . pkgs as Record < string , string > [ ] ) {
444+ const rv2 : Record < string , Record < string , string > > = { } ;
445+ for ( const { pkg : { project } } of json . pkgs ) {
413446 rv2 [ project ] = rv ;
414447 }
415448
0 commit comments