import{createProcessOutputBuffer}from"./process-output.js";import{dirname,join,resolve}from"node:path";import{accessSync,constants,existsSync,statSync}from"node:fs";import{spawn}from"node:child_process";const CONNECT_FEATURE_FLAG_ENV={FF_CONNECT_ENABLED:`1`},VERCEL_NOT_FOUND_MESSAGE=`Vercel CLI not found. Install with: npm i -g vercel@latest`;function buildSpawnEnv(e){return{...process.env,...CONNECT_FEATURE_FLAG_ENV,...e}}function existingDir(e){let n=resolve(e);for(;!existsSync(n);){let e=dirname(n);if(e===n)break;n=e}return n}function armDeadline(e,t,n){if(t===void 0)return()=>{};let r=setTimeout(()=>{n(),e.kill(`SIGTERM`);let t=setTimeout(()=>e.kill(`SIGKILL`),5e3);t.unref(),e.once(`close`,()=>clearTimeout(t))},t);return r.unref(),()=>clearTimeout(r)}function timeoutMessage(e,t){return`vercel ${e.join(` `)} timed out after ${Math.round(t/1e3)}s and was aborted.`}function ancestorDirectories(e){let n=[],i=resolve(e);for(;;){n.push(i);let e=dirname(i);if(e===i)return n;i=e}}function findExecutable(e){try{if(accessSync(e,constants.F_OK|constants.X_OK),statSync(e).isFile())return e}catch{return}}function findLocalVercel(e){for(let t of ancestorDirectories(e)){let e=findExecutable(join(t,`node_modules`,`.bin`,`vercel`));if(e!==void 0)return e}}function resolveVercelInvocation(e){let t=findLocalVercel(e);return t===void 0?{command:`vercel`,commandArgs:[]}:{command:t,commandArgs:[]}}function stdioForRun(e){return e.onOutput?[e.nonInteractive?`ignore`:`inherit`,`pipe`,`pipe`]:e.nonInteractive?[`ignore`,`pipe`,`pipe`]:`inherit`}async function runVercel(t,n){return new Promise(r=>{let i=existingDir(n.cwd),a=resolveVercelInvocation(i),o=n.onOutput&&createProcessOutputBuffer(n.onOutput),s=spawn(a.command,[...a.commandArgs,...t],{cwd:i,stdio:stdioForRun(n),env:buildSpawnEnv(n.extraEnv??{})});s.stdout?.on(`data`,e=>o?.write(`stdout`,e)),s.stderr?.on(`data`,e=>o?.write(`stderr`,e));let c=!1;function settle(e){c||(c=!0,o?.flush(),r(e))}function reportFailure(e){n.onOutput?n.onOutput({stream:`stderr`,text:e}):process.stderr.write(`\n${e}\n`)}let l=armDeadline(s,n.timeoutMs,()=>{reportFailure(timeoutMessage(t,n.timeoutMs??0)),settle(!1)});s.on(`error`,e=>{l(),e.code===`ENOENT`?reportFailure(VERCEL_NOT_FOUND_MESSAGE):reportFailure(`vercel ${t.join(` `)} failed: ${e.message}`),settle(!1)}),s.on(`close`,e=>{l(),!c&&e!==0&&e!==null&&(o?.flush(),reportFailure(`vercel ${t.join(` `)} exited with code ${e}.`)),settle(e===0)})})}async function runVercelCaptureStdout(t,n){return new Promise(r=>{let i=existingDir(n.cwd),a=resolveVercelInvocation(i),o=n.onOutput&&createProcessOutputBuffer(n.onOutput),s=spawn(a.command,[...a.commandArgs,...t],{cwd:i,stdio:[n.nonInteractive?`ignore`:`inherit`,`pipe`,n.onOutput?`pipe`:`inherit`],env:buildSpawnEnv(n.extraEnv??{})}),c=[];s.stdout?.on(`data`,e=>c.push(e.toString(`utf8`))),s.stderr?.on(`data`,e=>o?.write(`stderr`,e));let l=!1;function settle(e){l||(l=!0,o?.flush(),r({ok:e,stdout:c.join(``)}))}function reportFailure(e){n.onOutput?n.onOutput({stream:`stderr`,text:e}):process.stderr.write(`\n${e}\n`)}let u=armDeadline(s,n.timeoutMs,()=>{reportFailure(timeoutMessage(t,n.timeoutMs??0)),settle(!1)});s.on(`error`,e=>{u(),reportFailure(e.code===`ENOENT`?VERCEL_NOT_FOUND_MESSAGE:`vercel ${t.join(` `)} failed: ${e.message}`),settle(!1)}),s.on(`close`,e=>{u(),!l&&e!==0&&e!==null&&reportFailure(`vercel ${t.join(` `)} exited with code ${e}.`),settle(e===0)})})}async function captureVercel(t,n){return new Promise(r=>{let i=existingDir(n.cwd),a=resolveVercelInvocation(i),o=n.onOutput&&createProcessOutputBuffer(n.onOutput),s=spawn(a.command,[...a.commandArgs,...t],{cwd:i,stdio:[`ignore`,`pipe`,`pipe`],env:buildSpawnEnv(n.extraEnv??{})}),c=[],l=[];s.stdout?.on(`data`,e=>c.push(e.toString(`utf8`))),s.stderr?.on(`data`,e=>{l.push(e.toString(`utf8`)),o?.write(`stderr`,e)});let u=!1;function fail(e){u||(u=!0,o?.flush(),n.onOutput?.({stream:`stderr`,text:e.message}),r({ok:!1,failure:e}))}function succeed(){u||(u=!0,o?.flush(),r({ok:!0,stdout:c.join(``)}))}let d=armDeadline(s,n.timeoutMs,()=>{fail({code:null,stdout:c.join(``),stderr:l.join(``),message:timeoutMessage(t,n.timeoutMs??0)})});s.on(`error`,e=>{d(),fail({errno:e.code,stdout:c.join(``),stderr:l.join(``),message:e.code===`ENOENT`?VERCEL_NOT_FOUND_MESSAGE:`vercel ${t.join(` `)} failed: ${e.message}`})}),s.on(`close`,e=>{if(d(),e!==0&&e!==null){fail({code:e,stdout:c.join(``),stderr:l.join(``),message:`vercel ${t.join(` `)} exited with code ${e}.`});return}succeed()})})}export{captureVercel,runVercel,runVercelCaptureStdout};