@@ -55,20 +55,6 @@ function closeReadline() {
5555}
5656
5757// Helper functions for spawning processes - use Node.js child_process for compatibility
58- async function execPromise ( command : string ) : Promise < { stdout : string ; stderr : string } > {
59- return new Promise ( ( resolve , reject ) => {
60- childProcess . exec ( command , ( error , stdout , stderr ) => {
61- if ( error ) {
62- const err = error as Error & { code : number } ;
63- err . code = typeof error . code === "number" ? error . code : 1 ;
64- reject ( err ) ;
65- } else {
66- resolve ( { stdout, stderr } ) ;
67- }
68- } ) ;
69- } ) ;
70- }
71-
7258async function execFilePromise ( file : string , args : string [ ] ) : Promise < { stdout : string ; stderr : string } > {
7359 return new Promise ( ( resolve , reject ) => {
7460 childProcess . execFile ( file , args , ( error , stdout , stderr ) => {
@@ -2594,8 +2580,8 @@ mon
25942580
25952581 if ( ! grafanaPassword ) {
25962582 console . log ( "Generating secure Grafana password..." ) ;
2597- const { stdout : password } = await execPromise ( "openssl rand -base64 12 | tr -d '\n'" ) ;
2598- grafanaPassword = password . trim ( ) ;
2583+ const { stdout : password } = await execFilePromise ( "openssl" , [ " rand" , " -base64" , "12" ] ) ;
2584+ grafanaPassword = password . trim ( ) . replace ( / \n / g , "" ) ;
25992585
26002586 let configContent = "" ;
26012587 if ( fs . existsSync ( cfgPath ) ) {
@@ -2634,8 +2620,8 @@ mon
26342620 console . log ( "Generating VictoriaMetrics auth credentials..." ) ;
26352621 vmAuthUsername = vmAuthUsername || "vmauth" ;
26362622 if ( ! vmAuthPassword ) {
2637- const { stdout : vmPass } = await execPromise ( "openssl rand -base64 12 | tr -d '\n'" ) ;
2638- vmAuthPassword = vmPass . trim ( ) ;
2623+ const { stdout : vmPass } = await execFilePromise ( "openssl" , [ " rand" , " -base64" , "12" ] ) ;
2624+ vmAuthPassword = vmPass . trim ( ) . replace ( / \n / g , "" ) ;
26392625 }
26402626
26412627 // Update .env file with VM auth credentials
@@ -2947,16 +2933,16 @@ mon
29472933
29482934 // Fetch latest changes
29492935 console . log ( "Fetching latest changes..." ) ;
2950- await execPromise ( "git fetch origin" ) ;
2936+ await execFilePromise ( "git" , [ " fetch" , " origin"] ) ;
29512937
29522938 // Check current branch
2953- const { stdout : branch } = await execPromise ( "git rev-parse --abbrev-ref HEAD" ) ;
2939+ const { stdout : branch } = await execFilePromise ( "git" , [ " rev-parse" , " --abbrev-ref" , " HEAD"] ) ;
29542940 const currentBranch = branch . trim ( ) ;
29552941 console . log ( `Current branch: ${ currentBranch } ` ) ;
29562942
29572943 // Pull latest changes
29582944 console . log ( "Pulling latest changes..." ) ;
2959- const { stdout : pullOut } = await execPromise ( "git pull origin " + currentBranch ) ;
2945+ const { stdout : pullOut } = await execFilePromise ( "git" , [ " pull" , " origin" , currentBranch ] ) ;
29602946 console . log ( pullOut ) ;
29612947
29622948 // Update Docker images
@@ -3214,7 +3200,8 @@ targets
32143200 // If YAML parsing fails, fall back to simple check
32153201 const isFile = fs . existsSync ( file ) && ! fs . lstatSync ( file ) . isDirectory ( ) ;
32163202 const content = isFile ? fs . readFileSync ( file , "utf8" ) : "" ;
3217- if ( new RegExp ( `^- name: ${ instanceName } $` , "m" ) . test ( content ) ) {
3203+ const escapedName = instanceName . replace ( / [ . * + ? ^ $ { } ( ) | [ \] \\ ] / g, "\\$&" ) ;
3204+ if ( new RegExp ( `^- name: ${ escapedName } $` , "m" ) . test ( content ) ) {
32183205 console . error ( `Monitoring target '${ instanceName } ' already exists` ) ;
32193206 process . exitCode = 1 ;
32203207 return ;
@@ -3658,10 +3645,10 @@ mon
36583645
36593646 try {
36603647 // Generate secure password using openssl
3661- const { stdout : password } = await execPromise (
3662- "openssl rand -base64 12 | tr -d '\n'"
3648+ const { stdout : password } = await execFilePromise (
3649+ "openssl" , [ " rand" , " -base64" , "12" ]
36633650 ) ;
3664- const newPassword = password . trim ( ) ;
3651+ const newPassword = password . trim ( ) . replace ( / \n / g , "" ) ;
36653652
36663653 if ( ! newPassword ) {
36673654 console . error ( "Failed to generate password" ) ;
@@ -4712,7 +4699,7 @@ mcp
47124699 // Get the path to the current pgai executable
47134700 let pgaiPath : string ;
47144701 try {
4715- const execPath = await execPromise ( "which pgai" ) ;
4702+ const execPath = await execFilePromise ( "which" , [ " pgai"] ) ;
47164703 pgaiPath = execPath . stdout . trim ( ) ;
47174704 } catch {
47184705 // Fallback to just "pgai" if which fails
@@ -4724,8 +4711,8 @@ mcp
47244711 console . log ( "Installing PostgresAI MCP server for Claude Code..." ) ;
47254712
47264713 try {
4727- const { stdout, stderr } = await execPromise (
4728- ` claude mcp add -s user postgresai ${ pgaiPath } mcp start`
4714+ const { stdout, stderr } = await execFilePromise (
4715+ " claude" , [ " mcp" , " add" , "-s" , " user" , " postgresai" , pgaiPath , " mcp" , " start" ]
47294716 ) ;
47304717
47314718 if ( stdout ) console . log ( stdout ) ;
0 commit comments