@@ -3,34 +3,126 @@ import { constants as fsConstants } from "node:fs";
33import { access } from "node:fs/promises" ;
44import { join } from "node:path" ;
55
6- function execp ( bin , args , cwd ) {
6+ const INSTALL_COMMAND = "gh extension install github/gh-aw" ;
7+
8+ function combineOutput ( stdout , stderr ) {
9+ return [ stdout , stderr ] . filter ( Boolean ) . join ( "\n" ) . trim ( ) ;
10+ }
11+
12+ function execp ( bin , args , cwd , { combineIO = false , execFileFn = execFile , env = process . env } = { } ) {
713 return new Promise ( ( resolve , reject ) => {
8- execFile (
14+ execFileFn (
915 bin ,
1016 args ,
1117 {
1218 cwd,
13- env : { ...process . env , NO_COLOR : "1" , GH_NO_UPDATE_NOTIFIER : "1" } ,
19+ env : { ...env , CI : "1" , NO_COLOR : "1" , GH_NO_UPDATE_NOTIFIER : "1" } ,
1420 maxBuffer : 10 * 1024 * 1024 ,
1521 } ,
1622 ( err , stdout , stderr ) => {
17- if ( err ) reject ( Object . assign ( err , { stderr : stderr ?? "" } ) ) ;
18- else resolve ( stdout ) ;
23+ const output = combineOutput ( stdout ?? "" , stderr ?? "" ) ;
24+ if ( err ) reject ( Object . assign ( err , { stderr : stderr ?? "" , stdout : stdout ?? "" , output } ) ) ;
25+ else resolve ( combineIO ? output : stdout ) ;
1926 }
2027 ) ;
2128 } ) ;
2229}
2330
24- export function createGhAwRunner ( { getWorkspacePath } ) {
31+ function parseVersionFromOutput ( output ) {
32+ const trimmed = String ( output ?? "" ) . trim ( ) ;
33+ if ( ! trimmed ) return "" ;
34+ const match = trimmed . match ( / g h (?: - a w | a w ) v e r s i o n ( [ ^ \r \n ] + ) / i) ;
35+ return match ?. [ 1 ] ?. trim ( ) ?? "" ;
36+ }
37+
38+ function isMissingGhAwExtension ( error ) {
39+ const output = String ( error ?. output ?? error ?. stderr ?? error ?. message ?? "" ) ;
40+ return / e x t e n s i o n n o t f o u n d : \s * a w / i. test ( output ) || / u n k n o w n c o m m a n d [ " ' ] a w [ " ' ] f o r [ " ' ] g h [ " ' ] / i. test ( output ) ;
41+ }
42+
43+ async function findDevBinary ( cwd , accessFn = access , platform = process . platform ) {
44+ const devBin = join ( cwd , platform === "win32" ? "gh-aw.exe" : "gh-aw" ) ;
45+ try {
46+ await accessFn ( devBin , fsConstants . X_OK ) ;
47+ return devBin ;
48+ } catch {
49+ return null ;
50+ }
51+ }
52+
53+ export function createGhAwRunner ( { getWorkspacePath, accessFn = access , execFileFn = execFile , platform = process . platform , env = process . env } ) {
54+ async function runExec ( bin , args , cwd , options ) {
55+ return execp ( bin , args , cwd , { ...options , execFileFn, env } ) ;
56+ }
57+
2558 return async function runGhAw ( args ) {
2659 const cwd = getWorkspacePath ( ) ;
27- const isWin = process . platform === "win32" ;
28- const devBin = join ( cwd , isWin ? "gh-aw.exe" : "gh-aw" ) ;
60+ const devBin = await findDevBinary ( cwd , accessFn , platform ) ;
61+ if ( devBin ) {
62+ return runExec ( devBin , args , cwd ) ;
63+ }
64+
65+ return runExec ( "gh" , [ "aw" , ...args ] , cwd ) ;
66+ } ;
67+ }
68+
69+ export function createGhAwRunnerWithStatus ( options ) {
70+ const runGhAw = createGhAwRunner ( options ) ;
71+ const getStatus = async ( ) => {
72+ const cwd = options . getWorkspacePath ( ) ;
73+ const devBin = await findDevBinary ( cwd , options . accessFn ?? access , options . platform ?? process . platform ) ;
74+
75+ if ( devBin ) {
76+ const output = await execp ( devBin , [ "version" ] , cwd , {
77+ combineIO : true ,
78+ execFileFn : options . execFileFn ?? execFile ,
79+ env : options . env ?? process . env ,
80+ } ) ;
81+ return {
82+ available : true ,
83+ source : "dev-binary" ,
84+ version : parseVersionFromOutput ( output ) || "unknown" ,
85+ command : `${ devBin } version` ,
86+ installCommand : INSTALL_COMMAND ,
87+ } ;
88+ }
89+
2990 try {
30- await access ( devBin , fsConstants . X_OK ) ;
31- return await execp ( devBin , args , cwd ) ;
32- } catch {
33- return await execp ( "gh" , [ "aw" , ...args ] , cwd ) ;
91+ const output = await execp ( "gh" , [ "aw" , "version" ] , cwd , {
92+ combineIO : true ,
93+ execFileFn : options . execFileFn ?? execFile ,
94+ env : options . env ?? process . env ,
95+ } ) ;
96+ return {
97+ available : true ,
98+ source : "gh-extension" ,
99+ version : parseVersionFromOutput ( output ) || "unknown" ,
100+ command : "gh aw version" ,
101+ installCommand : INSTALL_COMMAND ,
102+ } ;
103+ } catch ( error ) {
104+ if ( isMissingGhAwExtension ( error ) ) {
105+ return {
106+ available : false ,
107+ source : "missing" ,
108+ version : "" ,
109+ command : "gh aw version" ,
110+ installCommand : INSTALL_COMMAND ,
111+ message : "gh aw is not installed. Install the GitHub CLI extension to use the dashboard outside a local dev build." ,
112+ } ;
113+ }
114+
115+ return {
116+ available : false ,
117+ source : "error" ,
118+ version : "" ,
119+ command : "gh aw version" ,
120+ installCommand : INSTALL_COMMAND ,
121+ message : String ( error ?. output ?? error ?. stderr ?? error ?. message ?? "Failed to detect gh aw." ) ,
122+ } ;
34123 }
35124 } ;
125+
126+ runGhAw . getStatus = getStatus ;
127+ return runGhAw ;
36128}
0 commit comments