@amr-m-abdelgawad/devctl 0.1.2-bootstrap.0 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/devctl.js +1 -1
  2. package/package.json +1 -1
package/dist/devctl.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // @bun
3
3
  var Ub=Object.defineProperty;var Kb=(e)=>e;function qb(e,t){this[e]=Kb.bind(null,t)}var ss=(e,t)=>{for(var r in t)Ub(e,r,{get:t[r],enumerable:!0,configurable:!0,set:qb.bind(t,r)})};var T=(e,t)=>()=>(e&&(t=e(e=0)),t);var Vb=import.meta.require;var On=T(()=>{if(process.env.METADATA_SERVER_DETECTION===void 0)process.env.METADATA_SERVER_DETECTION="bios-only";if(process.env.GCE_METADATA_TIMEOUT===void 0)process.env.GCE_METADATA_TIMEOUT="0"});function jp(e,t=""){if(t===Np)return!0;return e.includes(Np)||e.startsWith(Jb)}function as(){if(Hp)return;Hp=!0;let e=process.emitWarning.bind(process);process.emitWarning=(t,...r)=>{let n=zb(r[0]),o=Yb(t);if(jp(o,n))return;e(t,...r)}}function Bp(){let e=process.stderr.write.bind(process.stderr);return process.stderr.write=(t,r,n)=>{let o=Xb(t);if(jp(o)){let i=typeof r==="function"?r:typeof n==="function"?n:void 0;if(typeof i==="function")i();return!0}if(typeof r==="function")return e(t,r);return e(t,r,n)},()=>{process.stderr.write=e}}function Yb(e){if(typeof e==="string")return e;if(e instanceof Error)return e.message;return String(e)}function zb(e){if(typeof e==="string")return e;if(e&&typeof e==="object"&&"type"in e&&typeof e.type==="string")return e.type;return""}function Xb(e){if(typeof e==="string")return e;if(e instanceof Uint8Array)return new TextDecoder().decode(e);return""}var Np="MetadataLookupWarning",Jb="received unexpected error =",Hp=!1;var Hc=T(()=>{On()});function M(e,t){return new Te(e,t)}function ye(e,t,r){let n=r instanceof Error?r:Error(String(r));return new Te(e,t,{cause:n})}function be(e,t,r,n=""){return new Te(e,t,{hint:r,service:n})}function ds(e,t){return e instanceof Te&&e.kind===t}function Up(e){if(e instanceof Te)return e.exitCode();return 1}function Kp(e){if(e instanceof Te)return{error:H(e),kind:e.kind,hint:e.hint,service:e.service};return{error:H(e)}}function qp(e){if(typeof e==="string")return M("general",e);if(e.kind)return new Te(e.kind,e.error.replace(`${e.kind}: `,""),{hint:e.hint,service:e.service});return M("general",e.error)}function H(e){if(e instanceof Te){if(e.hint!=="")return`${Wp(e)} \u2014 ${e.hint}`;return Wp(e)}if(e instanceof Error)return e.message;return String(e)}function Wp(e){let t=`${e.kind}: `;if(e.message.startsWith(t)){let r=e.message.slice(t.length),n=e.causeError?`: ${e.causeError.message}`:"";if(n!==""&&r.endsWith(n))return r.slice(0,r.length-n.length);return r}return e.message}var X="configuration",Kr="configuration_missing",cs="service_not_found",Gp="dependency",bt="process_start",In="authentication",qr="authorization",ir="token",ls="impersonation",jc="iap",_r="proxy",Bc="health_check",nt="general",Te;var _e=T(()=>{Te=class Te extends Error{kind;hint;service;causeError;constructor(e,t,r){super(r?.cause?`${e}: ${t}: ${r.cause.message}`:`${e}: ${t}`);this.name="DevctlError",this.kind=e,this.hint=r?.hint??"",this.service=r?.service??"",this.causeError=r?.cause}exitCode(){switch(this.kind){case"configuration":case"configuration_missing":case"service_not_found":case"dependency":return 2;case"authentication":case"token":case"iap":return 3;case"authorization":case"impersonation":return 4;case"process_start":return 5;case"health_check":return 6;case"proxy":return 7;default:return 1}}}});import{spawnSync as Qb}from"child_process";import{createHash as Zb,randomBytes as Uc}from"crypto";import{copyFileSync as ew,existsSync as Rr,mkdirSync as tw,readdirSync as rw,readFileSync as Kc,renameSync as qc,statSync as nw,unlinkSync as Wc,writeFileSync as ow}from"fs";import{homedir as iw}from"os";import{basename as sw,dirname as Gc,join as st,resolve as aw}from"path";function Lt(){let e=process.env.DEVCTL_HOME;if(e&&e!=="")return e;return st(iw(),".devctl")}function Gt(e){tw(e,{recursive:!0,mode:cw})}function Wo(e){let t=aw(e),r=process.platform==="win32"?t.toLowerCase():t;return Zb("sha256").update(r).digest("hex").slice(0,dw)}function $n(e){let t=st(Lt(),"state",Wo(e)),r=st(Lt(),"sessions",Wo(e));if(!Rr(t)&&Rr(r)){Gt(Gc(t));try{qc(r,t)}catch{Gt(t);for(let n of["state.json","devctl.lock","devctl.sock"]){let o=st(r,n);if(Rr(o))ew(o,st(t,n))}}}return Gt(t),t}function us(){let e=st(Lt(),"logs");return Gt(e),e}function Vr(){let e=st(Lt(),"exports");return Gt(e),e}function It(){let e=st(Lt(),"credentials");return Gt(e),e}function ps(e,t=process.platform){if(t==="win32")return`\\\\.\\pipe\\devctl-${Wo(e)}`;return st($n(e),"devctl.sock")}function uw(e){return st($n(e),"devctl.lock")}function Vp(e){return st($n(e),"state.json")}function Go(e){return st($n(e),"bootstrap.log")}function Yp(e){let t=Go(e);if(!Rr(t))return;let r=$n(e),n=st(r,`${Jp}${Vc()}.log`);try{qc(t,n)}catch{return}fw(r)}function fw(e){let t;try{t=rw(e).filter((n)=>n.startsWith(Jp)&&n.endsWith(".log"))}catch{return}let r=t.map((n)=>{let o=st(e,n);try{return{path:o,mtime:nw(o).mtimeMs}}catch{return}}).filter((n)=>n!==void 0).sort((n,o)=>o.mtime-n.mtime);for(let n=pw;n<r.length;n++)try{Wc(r[n].path)}catch{}}function $t(e,t){Gt(Gc(e));let r=st(Gc(e),`.${sw(e)}.tmp-${process.pid}-${Uc(4).toString("hex")}`);ow(r,t,{mode:lw}),qc(r,e)}function Vc(e=new Date){return`${e.toISOString().slice(0,19).replace(/:/g,"-")+"Z"}-${Uc(3).toString("hex")}`}function fs(e){let t=e.indexOf("Z-"),r=t>=0?e.slice(0,t+1):e,n=r.indexOf("T");if(n<0||!r.endsWith("Z"))return;let o=r.slice(0,n),i=r.slice(n+1,-1).replace(/-/g,":"),s=new Date(`${o}T${i}Z`);return Number.isNaN(s.getTime())?void 0:s}function Uo(e){return Jc(Vp(e))}function Jc(e){if(!Rr(e))return;try{let t=JSON.parse(Kc(e,"utf8"));if(Array.isArray(t.processes)&&typeof t.repo_root==="string")return t;return}catch{return}}function zp(e,t){$t(Vp(e),`${JSON.stringify(t,null,2)}
4
4
  `)}function Xp(e,t){let r=uw(e);if(Rr(r)){let n=gw(r);if(n&&Rt(n.pid))throw Error(`supervisor already running (pid ${n.pid})`);try{Wc(r)}catch{}}return $t(r,JSON.stringify({pid:process.pid,socket:t})),{release:()=>{try{Wc(r)}catch{}}}}function gw(e){if(!Rr(e))return;try{let t=JSON.parse(Kc(e,"utf8"));if(typeof t.pid==="number"&&typeof t.socket==="string")return{pid:t.pid,socket:t.socket}}catch{return}return}function Rt(e){if(e<=0)return!1;if(process.platform==="win32")return mw(e);try{return process.kill(e,0),!0}catch{return!1}}function Yc(e){try{let t=Qb("cmd.exe",["/d","/c",`tasklist /FO CSV /NH /FI "PID eq ${e}"`],{encoding:"buffer",windowsHide:!0,timeout:5000});return hw(t.stdout)}catch{return""}}function mw(e){try{return process.kill(e,0),!0}catch{}let t=Yc(e).toLowerCase();if(t===""||t.includes("no tasks")||t.includes("no matching"))return!1;return t.includes(String(e))}function hw(e){if(!e)return"";if(typeof e==="string")return e;if(e.length>=2&&e[0]===255&&e[1]===254)return e.toString("utf16le");if(e.length>=4&&e[1]===0&&e[3]===0)return e.toString("utf16le");return e.toString("utf8")}function zc(){return Uc(24).toString("hex")}function yw(e){return st($n(e),"mcp-token")}function Qp(e){let t=yw(e);if(Rr(t)){let n=Kc(t,"utf8").trim();if(n!=="")return n}let r=zc();return $t(t,r),r}var cw=448,lw=384,dw=16,pw=5,Jp="bootstrap-";var Ye=()=>{};function ms(){return{args:[],shell:!1}}function Qc(){return{vars:{},required:[],defaults:{}}}function Zc(){return{type:"",url:"",address:"",command:ms(),interval_seconds:0,timeout_seconds:0}}function el(){return{type:"",mode:"",service_account:""}}function Nn(){return{extends:"",description:"",command:ms(),shell:!1,working_dir:"",dependencies:[],ports:[],environment:Qc(),health:Zc(),identity:el(),logs:{stdout:!1,stderr:!1},restart:{policy:"",max_retries:0,backoff_seconds:0},startup:{wait_for_healthy:!1,timeout_seconds:0},capabilities:[],proxy:[]}}function Jr(){return{version:1,project:{name:""},google:{project_id:"",region:""},profiles:{},templates:{},services:{},proxy:{enabled:!1,listen:{host:"127.0.0.1",port:0},token_endpoint:{enabled:!1,host:"",port:0},routes:[]},logs:{max_memory_events:50000,persistence:{enabled:!0,directory:"~/.devctl/logs",retention_days:14,max_session_logs:0}},auth:{refresh_threshold_seconds:300},shutdown:{grace_seconds:10},ui:{theme:"system",keymap:{}},secrets:{extra_markers:[],extra_patterns:[]},doctor:{tools:[]},plugins:[],environment:{sources:[],secrets:{}},repoRoot:"",configPath:""}}function tl(e){return e.args.length===0||e.args.length===1&&(e.args[0]??"").trim()===""}function Ko(e){if(e.type!=="")return e.type;return e.mode}function ar(e){let t=Ko(e).toLowerCase();return t==="service"||t==="service_account"}function rf(e){let t=Ko(e).toLowerCase();return t==="user"||t===""}function nf(e){if(e.policy!==""){if(e.policy==="always"||e.policy==="on_failure"||e.policy==="never")return e.policy;return e.policy}if(e.enabled===!0)return"on_failure";return"never"}function Yr(e){let t=e.host===""?"127.0.0.1":e.host;if(e.port===0)return t;return`${t}:${e.port}`}function hs(e){if(e.refresh_threshold_seconds<=0)return 300;return e.refresh_threshold_seconds}function ys(e){if(e.stop_services_on_exit===void 0)return!0;return e.stop_services_on_exit}function vs(e){if(e.grace_seconds<=0)return 10;return e.grace_seconds}function of(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stdout}function sf(e){if(!e.logs.stdout&&!e.logs.stderr)return!0;return e.logs.stderr}function rl(e,t){return e.find((r)=>r.name===t)}function af(e){return e[0]}var Fn=1,Zp="never",ef="on_failure",tf="always",gs=8080,Xc="127.0.0.1";function G(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function ol(e){return G(e)?new Set(Object.keys(e)):new Set}function q(e){if(typeof e==="string")return e;if(typeof e==="number"||typeof e==="boolean")return String(e);return""}function Ve(e){if(typeof e==="number")return e;if(typeof e==="string"){let t=Number(e);return Number.isNaN(t)?0:t}return 0}function ft(e){return e===!0}function Dt(e){if(!Array.isArray(e))return[];return e.map((t)=>q(t))}function Xr(e){if(!G(e))return{};let t={};for(let[r,n]of Object.entries(e))t[r]=q(n);return t}function qo(e){if(typeof e==="string")return{args:e.split(/\s+/).filter((t)=>t!==""),shell:!1};if(Array.isArray(e))return{args:e.map((t)=>q(t)),shell:!1};return ms()}function il(e){if(e===void 0||e===null)return[];if(typeof e==="string"||typeof e==="number")return[nl(e,"http")];if(Array.isArray(e))return e.map((t,r)=>nl(t,`port_${r}`));if(G(e))return Object.entries(e).map(([t,r])=>nl(r,t));return[]}function nl(e,t){if(typeof e==="string"&&e.toLowerCase()==="auto")return{name:t,value:0,auto:!0};return{name:t,value:Ve(e),auto:!1}}function vw(e){if(!G(e))return Qc();let t={},r=[],n={};for(let[o,i]of Object.entries(e))if(o==="required")r=Dt(i);else if(o==="defaults")n=Xr(i);else t[o]=q(i);return{vars:t,required:r,defaults:n}}function xw(e){if(!G(e))return el();return{type:q(e.type),mode:q(e.mode),service_account:q(e.service_account)}}function bw(e){if(!G(e))return Zc();return{type:q(e.type),url:q(e.url),address:q(e.address),command:qo(e.command),interval_seconds:Ve(e.interval_seconds),timeout_seconds:Ve(e.timeout_seconds)}}function ww(e){if(!G(e))return{policy:"",max_retries:0,backoff_seconds:0};return{enabled:e.enabled===void 0?void 0:ft(e.enabled),policy:q(e.policy),max_retries:Ve(e.max_retries),backoff_seconds:Ve(e.backoff_seconds)}}function Sw(e){if(!G(e))return{wait_for_healthy:!1,timeout_seconds:0};return{wait_for_healthy:ft(e.wait_for_healthy),timeout_seconds:Ve(e.timeout_seconds)}}function Vo(e){if(!G(e))return Nn();let t=G(e.logs)?e.logs:{};return{extends:q(e.extends),description:q(e.description),command:qo(e.command),shell:ft(e.shell),working_dir:q(e.working_dir),dependencies:Dt(e.dependencies),ports:il(e.ports),environment:vw(e.environment),health:bw(e.health),identity:xw(e.identity),logs:{stdout:ft(t.stdout),stderr:ft(t.stderr)},restart:ww(e.restart),startup:Sw(e.startup),capabilities:Dt(e.capabilities),proxy:sl(e.proxy)}}function sl(e){if(e===void 0||e===null)return[];if(Array.isArray(e))return e.map((t)=>zr(t));if(G(e))return[zr(e)];return[]}function xs(e){if(!G(e))return{services:[],environment:{}};return{services:Dt(e.services),environment:Xr(e.environment)}}function kw(e){if(typeof e==="string")return{type:e,service_account:""};if(!G(e))return{type:"",service_account:""};return{type:q(e.type),service_account:q(e.service_account)}}function Cw(e){if(!G(e))return{type:"",identity:{type:"",service_account:""},audience:"",service_account:""};return{type:q(e.type),identity:kw(e.identity),audience:q(e.audience),service_account:q(e.service_account)}}function zr(e){if(!G(e))return{name:"",match:{host:"",path:""},upstream:{url:""},auth:{type:"",identity:{type:"",service_account:""},audience:"",service_account:""}};let t=G(e.match)?e.match:{},r=G(e.upstream)?e.upstream:{};return{name:q(e.name),match:{host:q(t.host),path:q(t.path)},upstream:{url:q(r.url)},auth:Cw(e.auth)}}var al=()=>{};import{existsSync as _w,statSync as lf}from"fs";import{basename as cf,dirname as bs,isAbsolute as Rw,join as ws,resolve as df}from"path";function Pr(e,t){if(t!=="")return Pw(t);let r=e===""?process.cwd():e;r=Rw(r)?r:df(r);for(;;){let n=ws(r,wt,Ft);if(Jo(n))return{repoRoot:r,configPath:n};let o=ws(r,"devctl.yaml");if(Jo(o))return{repoRoot:r,configPath:o};let i=bs(r);if(i===r)break;r=i}throw be(Kr,"no devctl configuration found","run `devctl setup` or create a .devctl/config.yaml in the repository root")}function Pw(e){let t=df(e),r;try{r=lf(t)}catch(o){throw ye(Kr,"config path not found",o)}if(r.isDirectory()){if(cf(t)===wt)return{repoRoot:bs(t),configPath:ws(t,Ft)};return{repoRoot:t,configPath:ws(t,Ft)}}let n=bs(t);if(cf(n)===wt)n=bs(n);return{repoRoot:n,configPath:t}}function Jo(e){return _w(e)&&!lf(e).isDirectory()}var wt=".devctl",Ft="config.yaml";var Yo=T(()=>{_e()});function Cs(){return{services:{},templates:{}}}function Ss(e,t,r){let n=ol(r);if(G(r))for(let i of Ew){let s=r[i];if(G(s))for(let a of Object.keys(s))n.add(`${i}.${a}`)}let o=e[t];e[t]=o?new Set([...o,...n]):n}function uf(e,t,r=Cs()){if(t.version!==void 0)e.version=Ve(t.version);if(G(t.project)&&t.project.name!==void 0)e.project.name=q(t.project.name);if(G(t.google)){if(t.google.project_id!==void 0)e.google.project_id=q(t.google.project_id);if(t.google.region!==void 0)e.google.region=q(t.google.region)}if(G(t.profiles))for(let[n,o]of Object.entries(t.profiles)){let i=e.profiles[n];e.profiles[n]=i?Aw(i,o):xs(o)}if(G(t.templates))for(let[n,o]of Object.entries(t.templates)){let i=e.templates[n];e.templates[n]=i?ks(i,o):Vo(o),Ss(r.templates,n,o)}if(G(t.services))for(let[n,o]of Object.entries(t.services)){let i=e.services[n];e.services[n]=i?ks(i,o):Vo(o),Ss(r.services,n,o)}if(G(t.proxy))Tw(e.proxy,t.proxy);if(G(t.logs)){if(t.logs.max_memory_events!==void 0)e.logs.max_memory_events=Ve(t.logs.max_memory_events);if(G(t.logs.persistence)){let n=t.logs.persistence;if(n.enabled!==void 0)e.logs.persistence.enabled=ft(n.enabled);if(n.directory!==void 0)e.logs.persistence.directory=q(n.directory);if(n.retention_days!==void 0)e.logs.persistence.retention_days=Ve(n.retention_days);if(n.max_session_logs!==void 0)e.logs.persistence.max_session_logs=Ve(n.max_session_logs)}}if(G(t.auth)&&t.auth.refresh_threshold_seconds!==void 0)e.auth.refresh_threshold_seconds=Ve(t.auth.refresh_threshold_seconds);if(G(t.shutdown)){if(t.shutdown.stop_services_on_exit!==void 0)e.shutdown.stop_services_on_exit=ft(t.shutdown.stop_services_on_exit);if(t.shutdown.grace_seconds!==void 0)e.shutdown.grace_seconds=Ve(t.shutdown.grace_seconds)}if(G(t.ui)){if(t.ui.theme!==void 0)e.ui.theme=q(t.ui.theme);if(t.ui.keymap!==void 0)e.ui.keymap=Xr(t.ui.keymap)}if(G(t.secrets)){if(t.secrets.extra_markers!==void 0)e.secrets.extra_markers=Dt(t.secrets.extra_markers);if(t.secrets.extra_patterns!==void 0)e.secrets.extra_patterns=Dt(t.secrets.extra_patterns)}if(G(t.doctor)&&Array.isArray(t.doctor.tools))e.doctor.tools=t.doctor.tools.filter(G).map((n)=>({name:q(n.name),command:q(n.command)}));if(Array.isArray(t.plugins))e.plugins=t.plugins.filter(G).map((n)=>({path:q(n.path)})).filter((n)=>n.path!=="");if(G(t.environment)){if(Array.isArray(t.environment.sources))e.environment.sources=Dt(t.environment.sources);if(G(t.environment.secrets))e.environment.secrets={...e.environment.secrets,...Xr(t.environment.secrets)}}}function Tw(e,t){if(t.enabled!==void 0)e.enabled=ft(t.enabled);if(G(t.listen)){if(t.listen.host!==void 0)e.listen.host=q(t.listen.host);if(t.listen.port!==void 0)e.listen.port=Ve(t.listen.port)}if(G(t.token_endpoint)){let r=t.token_endpoint;if(r.enabled!==void 0)e.token_endpoint.enabled=ft(r.enabled);if(r.host!==void 0)e.token_endpoint.host=q(r.host);if(r.port!==void 0)e.token_endpoint.port=Ve(r.port)}if(Array.isArray(t.routes))e.routes=t.routes.map((r)=>zr(r))}function Aw(e,t){if(!G(t))return e;return{services:t.services!==void 0?Dt(t.services):e.services,environment:t.environment!==void 0?{...e.environment,...Xr(t.environment)}:e.environment}}function ks(e,t){if(!G(t))return e;let r=ol(t),n={...e,environment:Lw(e.environment,t.environment),health:Dw(e.health,t.health),identity:Mw(e.identity,t.identity),logs:Ow(e.logs,t.logs),restart:Iw(e.restart,t.restart),startup:$w(e.startup,t.startup)};if(r.has("extends"))n.extends=q(t.extends);if(r.has("description"))n.description=q(t.description);if(r.has("command"))n.command=qo(t.command);if(r.has("shell"))n.shell=ft(t.shell);if(r.has("working_dir"))n.working_dir=q(t.working_dir);if(r.has("dependencies"))n.dependencies=Dt(t.dependencies);if(r.has("ports"))n.ports=il(t.ports);if(r.has("capabilities"))n.capabilities=Dt(t.capabilities);if(r.has("proxy"))n.proxy=sl(t.proxy);return n}function Lw(e,t){if(!G(t))return e;let r={...e.vars},n={...e.defaults},o=e.required;for(let[i,s]of Object.entries(t))if(i==="required")o=Dt(s);else if(i==="defaults")Object.assign(n,Xr(s));else r[i]=q(s);return{vars:r,required:o,defaults:n}}function Dw(e,t){if(!G(t))return e;return{type:t.type!==void 0?q(t.type):e.type,url:t.url!==void 0?q(t.url):e.url,address:t.address!==void 0?q(t.address):e.address,command:t.command!==void 0?qo(t.command):e.command,interval_seconds:t.interval_seconds!==void 0?Ve(t.interval_seconds):e.interval_seconds,timeout_seconds:t.timeout_seconds!==void 0?Ve(t.timeout_seconds):e.timeout_seconds}}function Mw(e,t){if(!G(t))return e;return{type:t.type!==void 0?q(t.type):e.type,mode:t.mode!==void 0?q(t.mode):e.mode,service_account:t.service_account!==void 0?q(t.service_account):e.service_account}}function Ow(e,t){if(!G(t))return e;return{stdout:t.stdout!==void 0?ft(t.stdout):e.stdout,stderr:t.stderr!==void 0?ft(t.stderr):e.stderr}}function Iw(e,t){if(!G(t))return e;return{enabled:t.enabled!==void 0?ft(t.enabled):e.enabled,policy:t.policy!==void 0?q(t.policy):e.policy,max_retries:t.max_retries!==void 0?Ve(t.max_retries):e.max_retries,backoff_seconds:t.backoff_seconds!==void 0?Ve(t.backoff_seconds):e.backoff_seconds}}function $w(e,t){if(!G(t))return e;return{wait_for_healthy:t.wait_for_healthy!==void 0?ft(t.wait_for_healthy):e.wait_for_healthy,timeout_seconds:t.timeout_seconds!==void 0?Ve(t.timeout_seconds):e.timeout_seconds}}function pf(e){let t=Object.keys(e.services).sort();for(let r of t){let n=e.services[r]?.proxy??[];if(n.length===0)continue;n.forEach((o,i)=>{let s=n.length===1?r:`${r}-${i+1}`;e.proxy.routes.push({name:s,match:o.match,upstream:o.upstream,auth:o.auth})})}}function ff(e,t=Cs()){if(Object.keys(e.templates).length===0)return;let r={};for(let[n,o]of Object.entries(e.services))r[n]=gf(e,o,t.services[n]??new Set,t,{});e.services=r}function gf(e,t,r,n,o){if(t.extends==="")return t;if(o[t.extends])throw Error(`template cycle involving "${t.extends}"`);let i=e.templates[t.extends]??Nn();if(!e.templates[t.extends])throw Error(`service extends unknown template "${t.extends}"`);let s={...o,[t.extends]:!0},a=n.templates[t.extends]??new Set,c=gf(e,i,a,n,s),l=Fw(c,t,r);return l.extends=t.extends,l}function Fw(e,t,r){let n={...e};if(r.has("extends"))n.extends=t.extends;if(r.has("description"))n.description=t.description;if(r.has("command"))n.command=t.command;if(r.has("shell"))n.shell=t.shell;if(r.has("working_dir"))n.working_dir=t.working_dir;if(r.has("dependencies"))n.dependencies=t.dependencies;if(r.has("ports"))n.ports=t.ports;if(r.has("capabilities"))n.capabilities=t.capabilities;if(r.has("proxy"))n.proxy=t.proxy;return n.health={type:r.has("health.type")?t.health.type:e.health.type,url:r.has("health.url")?t.health.url:e.health.url,address:r.has("health.address")?t.health.address:e.health.address,command:r.has("health.command")?t.health.command:e.health.command,interval_seconds:r.has("health.interval_seconds")?t.health.interval_seconds:e.health.interval_seconds,timeout_seconds:r.has("health.timeout_seconds")?t.health.timeout_seconds:e.health.timeout_seconds},n.identity={type:r.has("identity.type")?t.identity.type:e.identity.type,mode:r.has("identity.mode")?t.identity.mode:e.identity.mode,service_account:r.has("identity.service_account")?t.identity.service_account:e.identity.service_account},n.logs={stdout:r.has("logs.stdout")?t.logs.stdout:e.logs.stdout,stderr:r.has("logs.stderr")?t.logs.stderr:e.logs.stderr},n.restart={enabled:r.has("restart.enabled")?t.restart.enabled:e.restart.enabled,policy:r.has("restart.policy")?t.restart.policy:e.restart.policy,max_retries:r.has("restart.max_retries")?t.restart.max_retries:e.restart.max_retries,backoff_seconds:r.has("restart.backoff_seconds")?t.restart.backoff_seconds:e.restart.backoff_seconds},n.startup={wait_for_healthy:r.has("startup.wait_for_healthy")?t.startup.wait_for_healthy:e.startup.wait_for_healthy,timeout_seconds:r.has("startup.timeout_seconds")?t.startup.timeout_seconds:e.startup.timeout_seconds},n.environment={vars:{...e.environment.vars,...t.environment.vars},defaults:{...e.environment.defaults,...t.environment.defaults},required:r.has("environment.required")?t.environment.required:e.environment.required},n}var Ew;var mf=T(()=>{al();Ew=["environment","restart","startup","health","logs","identity"]});function cl(e){if(e.version===0)throw M(X,"version is required");if(e.version===Fn)return e;throw M(X,`unsupported config version ${e.version} (expected ${Fn}); no migration is available`)}var ll=T(()=>{_e()});var hf,yf,vf,xf,bf,wf,Sf,kf,dl,ul,pl,fl,Cf,_f,Rf,Pf,Ef,Tf,Af,Lf,Df,Mf,Of,If,$f,Ff,Nf,Hf,jf,Bf;var gl=T(()=>{hf=["version","project","google","profiles","templates","services","proxy","logs","auth","shutdown","ui","secrets","doctor","plugins","environment"],yf=["extends","description","command","shell","working_dir","dependencies","ports","environment","health","identity","logs","restart","startup","capabilities","proxy"],vf=["type","url","address","command","interval_seconds","timeout_seconds"],xf=["type","mode","service_account"],bf=["enabled","policy","max_retries","backoff_seconds"],wf=["wait_for_healthy","timeout_seconds"],Sf=["enabled","listen","token_endpoint","routes"],kf=["host","port"],dl=["name","match","upstream","auth"],ul=["host","path"],pl=["url"],fl=["type","identity","audience","service_account"],Cf=["max_memory_events","persistence"],_f=["enabled","directory","retention_days","max_session_logs"],Rf=["refresh_threshold_seconds"],Pf=["stop_services_on_exit","grace_seconds"],Ef=["theme","keymap"],Tf=["name"],Af=["project_id","region"],Lf=["services","environment"],Df=["required","defaults"],Mf=["stdout","stderr"],Of=["extra_markers","extra_patterns"],If=["tools"],$f=["name","command"],Ff=["enabled","host","port"],Nf=["path"],Hf=["sources","secrets"],jf=["google","google_api","iap","network","service_identity","local_http"],Bf=["|","||","&&",";",">",">>","<","&"]});function Qr(e,t){if(!qw(e))return[];let r=jw(t),n=[];for(let o of Object.keys(e)){let i=Kw(t,o);if(r.length>0&&!r.includes(o)&&!Hw(t))n.push(i);n.push(...Qr(e[o],i))}return n}function Hw(e){if(e==="services"||e==="profiles"||e==="templates")return!0;if(e.endsWith(".environment")||e.endsWith(".defaults")||e.endsWith(".keymap"))return!0;return e.includes(".environment.")&&!e.endsWith(".environment")}function jw(e){switch(e){case"":return hf;case"project":return Tf;case"google":return Af;case"proxy":return Sf;case"proxy.listen":return kf;case"proxy.token_endpoint":return Ff;case"logs":return Cf;case"logs.persistence":return _f;case"auth":return Rf;case"shutdown":return Pf;case"ui":return Ef;case"secrets":return Of;case"doctor":return If;case"environment":return Hf;default:return Bw(e)}}function Bw(e){if(e==="services"||e==="profiles"||e==="templates")return[];if(e.startsWith("services.")||e.startsWith("templates."))return Ww(e);if(e.startsWith("profiles.")){if(e.split(".").length===2)return Lf}if(e.includes("routes"))return Uw(e);if(e.startsWith("doctor.tools")&&e.split(".").length>=3)return $f;if(e==="plugins")return[];if(e.startsWith("plugins.")&&e.split(".").length===2)return Nf;return[]}function Ww(e){let t=e.split(".");if(t.length===2)return yf;if(t.length>=3)switch(t[2]){case"health":return vf;case"identity":return xf;case"restart":return bf;case"startup":return wf;case"logs":return Mf;case"environment":return Df;case"proxy":return Gw(t);default:return[]}return[]}function Gw(e){let t=e.slice(3),r=t[0]!==void 0&&/^\d+$/.test(t[0])?1:0,n=t[r]??"";if(n==="match")return ul;if(n==="upstream")return pl;if(n==="auth")return fl;return dl}function Uw(e){if(e==="proxy.routes")return[];if(e.endsWith(".match"))return ul;if(e.endsWith(".upstream"))return pl;if(e.endsWith(".auth"))return fl;if(e.includes("proxy.routes")&&e.split(".").length===Nw+1)return dl;return[]}function Kw(e,t){if(e==="")return t;return`${e}.${t}`}function qw(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}function Hn(e){return`unknown fields: ${e.join(", ")}`}var Nw=2;var Wf=T(()=>{gl()});function Gf(e,t,r){let n=e,o="";for(;;){let i=n.indexOf("${");if(i<0)return o+n;o+=n.slice(0,i);let s=n.slice(i).indexOf("}");if(s<0)throw Error(`unclosed environment reference in "${e}"`);let a=n.slice(i+2,i+s);o+=Vw(a,t,r),n=n.slice(i+s+1)}}function Vw(e,t,r){let n=e.split(".");if(n.length<3||n[0]!=="services")throw Error(`unsupported reference \${${e}}`);let o=n[1]??"",i=t.services[o];if(!i)throw Error(`reference \${${e}}: unknown service`);let s=r[o];if(n[2]==="port"){if(s){if(s.http!==void 0)return String(s.http);let c=Object.values(s)[0];if(c!==void 0)return String(c)}let a=af(i.ports);if(a&&!a.auto)return String(a.value)}if(n[2]==="ports"){let a=n[3];if(!a)throw Error(`reference \${${e}}: missing port name`);if(s&&s[a]!==void 0)return String(s[a]);let c=rl(i.ports,a);if(c&&!c.auto)return String(c.value);let l=Number.parseInt(a,10);if(!Number.isNaN(l)&&l>=0&&l<i.ports.length){let d=i.ports[l];if(d&&!d.auto)return String(d.value)}}throw Error(`unresolvable reference \${${e}}`)}function ml(e,t,r){let n={};for(let[o,i]of Object.entries(e))n[o]=Gf(i,t,r);return n}function Uf(e){let t=[],r=e;for(;;){let n=r.indexOf("${");if(n<0)return t;let o=r.slice(n).indexOf("}");if(o<0)return t;t.push(r.slice(n+2,n+o)),r=r.slice(n+o+1)}}function Kf(e,t){let r=e.split(".");if(r.length<2)return!1;if(r[0]!=="services"||r.length<3)return!1;let n=t.services[r[1]??""];if(!n)return!1;if(r[2]==="port"||r[2]==="ports"){if(r.length===3)return n.ports.length>0;if(r.length>=4){let o=r[3]??"";if(!Number.isNaN(Number.parseInt(o,10)))return!0;return rl(n.ports,o)!==void 0}}return!0}var hl=()=>{};function xl(e){let t=[];for(let[r,n]of Object.entries(e.services)){let o=n.health.type;if(o!==""&&!Jf.includes(o.toLowerCase()))t.push({service:r,type:o})}return t}function Ut(e){let t=[];if(e.version===0)t.push("version is required");else if(e.version!==Fn)t.push(`unsupported config version ${e.version} (expected ${Fn}); no migration is available`);if(Object.keys(e.services).length===0)t.push("at least one service must be defined");if(t.push(...Yw(e)),t.push(...Zw(e)),t.push(...tS(e)),t.push(...rS(e)),e.logs.max_memory_events<0)t.push("logs.max_memory_events must be >= 0");return t}function Yw(e){let t=[],r={};for(let[n,o]of Object.entries(e.services)){let i=`services.${n}`;if(tl(o.command))t.push(`${i}.command is required`);t.push(...oS(i,o.command,o.shell)),t.push(...iS(i,o.capabilities));for(let c of o.dependencies){if(!e.services[c])t.push(`${i}.dependencies: unknown service "${c}"`);if(c===n)t.push(`${i}.dependencies: service cannot depend on itself`)}if(o.extends!==""&&!e.templates[o.extends])t.push(`${i}.extends: unknown template "${o.extends}"`);for(let c of o.ports.filter((l)=>!l.auto))if(c.value<vl||c.value>yl)t.push(`${i}.ports.${c.name}: invalid port ${c.value}`);else if(r[c.value])t.push(`duplicate port ${c.value} used by ${r[c.value]} and ${n}`);else r[c.value]=n;let s=Qw(`${i}.identity`,o.identity,e.plugins.length>0);if(s!=="")t.push(s);t.push(...zw(i,o,e.plugins.length>0));let a=nf(o.restart);if(a!==Zp&&a!==ef&&a!==tf)t.push(`${i}.restart.policy must be never, on_failure, or always`);t.push(...eS(`${i}.environment`,o.environment,e))}return t}function zw(e,t,r){let n=[];if(t.health.type==="")return n;let o=t.health.type.toLowerCase();if(!Jf.includes(o)&&!r)n.push(`${e}.health.type must be http, tcp, process, or command`);if(o==="http"&&t.health.url==="")n.push(`${e}.health.url is required for http health checks`);if(o==="tcp"&&t.health.address===""&&t.ports.length===0)n.push(`${e}.health.address is required for tcp health checks without ports`);if(o==="command"&&tl({args:t.health.command.args,shell:!1}))n.push(`${e}.health.command is required for command health checks`);return n}function Qw(e,t,r){let n=Ko(t).toLowerCase();if(n===""||n==="user")return"";if(n==="service"||n==="service_account"){if(t.service_account==="")return`${e}.service_account is required for service identity`;if(!t.service_account.includes("@"))return`${e}.service_account must be an email`;return""}if(r)return"";return`${e}.type must be user or service_account`}function bl(e){let t=[];for(let[r,n]of Object.entries(e.services)){let o=Ko(n.identity).toLowerCase();if(!Xw.includes(o))t.push({service:r,type:o})}return t}function Zw(e){let t={},r=[],n=[],o=(i)=>{let s=t[i]??Jw;if(s===Vf)return;if(s===qf){r.push(`dependency cycle: ${[...n,i].join(" \u2192 ")}`);return}t[i]=qf,n.push(i);let a=e.services[i];if(a){for(let c of a.dependencies)if(e.services[c])o(c)}n.pop(),t[i]=Vf};for(let i of Object.keys(e.services))o(i);return r}function eS(e,t,r){let n=[],o=(i,s)=>{for(let a of Uf(s))if(!Kf(a,r))n.push(`${e}.${i}: unresolvable reference \${${a}}`)};for(let[i,s]of Object.entries(t.vars))o(i,s);for(let[i,s]of Object.entries(t.defaults))o(i,s);return n}function tS(e){let t=[];for(let[r,n]of Object.entries(e.profiles))for(let o of n.services)if(!e.services[o])t.push(`profiles.${r} references unknown service "${o}"`);return t}function rS(e){let t=[];if(e.proxy.listen.host!==""&&!sS(e.proxy.listen.host))t.push("proxy.listen.host must be an IP address or localhost");if(e.proxy.enabled&&e.proxy.listen.port===0)t.push("proxy.listen.port is required when proxy.enabled is true");if(e.proxy.listen.port!==0&&(e.proxy.listen.port<vl||e.proxy.listen.port>yl))t.push("proxy.listen.port is invalid");let r={};return e.proxy.routes.forEach((n,o)=>{let i=`proxy.routes[${o}]`;if(n.name==="")t.push(`${i}.name is required`);else if(r[n.name])t.push(`${i}: duplicate route name ${n.name}`);if(r[n.name]=!0,n.upstream.url==="")t.push(`${i}.upstream.url is required`);if(n.auth.type.toLowerCase()==="iap"){if(n.auth.audience.trim()==="")t.push(`${i}.auth.audience is required when auth.type is iap`);if(n.auth.identity.type.trim()==="")t.push(`${i}.auth.identity.type is required when auth.type is iap`)}let s=n.auth.identity.type.toLowerCase();if(s==="service"||s==="service_account"||ar({type:s,mode:"",service_account:""})){if((n.auth.identity.service_account||n.auth.service_account)==="")t.push(`${i}.auth.identity.service_account is required`)}}),t.push(...nS(e)),t}function nS(e){let t=[],r=e.proxy.token_endpoint;if(!r.enabled)return t;let n=r.host||Xc;if(n==="0.0.0.0")t.push("proxy.token_endpoint.host must be a loopback address");else if(n!==""&&n!==Xc&&n!=="localhost"&&!n.startsWith("127."))t.push("proxy.token_endpoint.host must be a loopback address");if(r.port!==0&&(r.port<vl||r.port>yl))t.push("proxy.token_endpoint.port is invalid");return t}function oS(e,t,r){if(t.shell||r)return[];for(let n of t.args)if(Bf.includes(n)||n.includes("|")||n.includes(";")||n.includes("&&"))return[`${e}.command contains shell metacharacters; set shell: true to run via a shell`];return[]}function iS(e,t){let r=[];for(let n of t)if(!jf.includes(n))r.push(`${e}.capabilities: unknown capability "${n}"`);return r}function sS(e){if(e==="localhost")return!0;return aS(e)}function aS(e){if(/^(\d{1,3}\.){3}\d{1,3}$/.test(e))return e.split(".").every((r)=>{let n=Number(r);return n>=0&&n<=255});return e.includes(":")}var yl=65535,vl=1,Jf,Jw=0,qf=1,Vf=2,Xw;var _s=T(()=>{gl();hl();Jf=["http","tcp","process","command"];Xw=["","user","service","service_account"]});import{readdirSync as cS,readFileSync as lS}from"fs";import{basename as zf,dirname as dS,extname as uS,join as Zr,resolve as pS}from"path";import{parse as fS}from"yaml";function jn(e,t,r){try{return Xo(e,t,{candidateText:r}),[]}catch(n){if(n instanceof Te){let o=`${n.kind}: `;return[n.message.startsWith(o)?n.message.slice(o.length):n.message]}return[n instanceof Error?n.message:String(n)]}}function gt(e,t){let{repoRoot:r,configPath:n}=Pr(e,t);return Xo(r,n)}function zo(e,t){try{return gt(e,t)}catch(r){if(!ds(r,Kr))throw r;let n=e===""?process.cwd():pS(e),o=Jr();return o.repoRoot=n,o.configPath=Zr(n,wt,Ft),o}}function Xo(e,t,r){let n=Jr(),o=Cs();Xf(t,n,o,r?.candidateText),n.repoRoot=e,n.configPath=t;let i=dS(t);if(zf(i)===wt)mS(i,n,o);n=gS(n,e,t,o),n=cl(n);try{ff(n,o)}catch(a){throw ye(X,"template merge failed",a)}pf(n);let s=Ut(n);if(s.length>0)throw M(X,s.join(`
5
- `));return n}function gS(e,t,r,n){let o=Zr(Lt(),"config.local.yaml"),i=Zr(t,wt,"config.local.yaml");for(let s of[o,i]){if(s===r||!Jo(s))continue;Xf(s,e,n)}return e}function Xf(e,t,r,n){let o=n!==void 0?Qf(n,e):wl(e),i=Qr(o,"");if(i.length>0)throw M(X,Hn(i));uf(t,o,r)}function mS(e,t,r){Yf(Zr(e,"services"),(o,i)=>{let s=Qr(i,`services.${o}`);if(s.length>0)throw M(X,Hn(s));let a=t.services[o];t.services[o]=a?ks(a,i):Vo(i),Ss(r.services,o,i)}),Yf(Zr(e,"profiles"),(o,i)=>{let s=Qr(i,`profiles.${o}`);if(s.length>0)throw M(X,Hn(s));t.profiles[o]=xs(i)});let n=Zr(e,"proxy","routes.yaml");if(Jo(n))hS(n,t)}function hS(e,t){let r=wl(e);if(G(r.proxy)){let n=Qr({proxy:r.proxy},"");if(n.length>0)throw M(X,Hn(n))}if(Array.isArray(r.routes))r.routes.forEach((n,o)=>{let i=Qr(n,`proxy.routes.${o}`);if(i.length>0)throw M(X,Hn(i))});if(G(r.proxy)){if(Array.isArray(r.proxy.routes))t.proxy.routes.push(...r.proxy.routes.map((n)=>zr(n)));if(G(r.proxy.listen)){if(typeof r.proxy.listen.host==="string"&&r.proxy.listen.host!=="")t.proxy.listen.host=r.proxy.listen.host;if(typeof r.proxy.listen.port==="number"&&r.proxy.listen.port!==0)t.proxy.listen.port=r.proxy.listen.port}}if(Array.isArray(r.routes))t.proxy.routes.push(...r.routes.map((n)=>zr(n)))}function Yf(e,t){let r;try{r=cS(e)}catch(n){if(yS(n))return;throw n}for(let n of r){let o=uS(n);if(o!==".yaml"&&o!==".yml")continue;let i=Zr(e,n),s=wl(i);t(zf(n,o),s)}}function wl(e){let t;try{t=lS(e,"utf8")}catch(r){throw ye(X,"unable to read config",r)}return Qf(t,e)}function Qf(e,t){let r;try{r=fS(e)}catch(n){throw ye(X,`invalid YAML in ${t}`,n)}if(r===null||r===void 0)return{};if(!G(r))throw M(X,`unable to decode config: ${t} is not a mapping`);return r}function yS(e){return typeof e==="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var Zf=T(()=>{_e();Ye();al();Yo();mf();ll();Wf();_s();Yo();_s()});var St=T(()=>{Zf();Yo();_s();ll();hl()});import{readdirSync as vS}from"fs";import{join as eg,resolve as Sl,sep as kl}from"path";function xS(e){let t=eg(Lt(),"state"),r;try{r=vS(t)}catch{return}let n=tg(Sl(e)),o;for(let i of r){let s=Jc(eg(t,i,"state.json"));if(!s)continue;let a=tg(Sl(s.repo_root));if(!bS(a,n))continue;if(!o||a.length>o.length)o=a}return o}function Rs(e,t,r=""){if(t!=="")return{repoRoot:Sl(t),source:"explicit"};let n=e===""?process.cwd():e;try{let{repoRoot:i}=Pr(n,r);return{repoRoot:i,source:"config"}}catch{if(r!=="")return}let o=xS(n);return o?{repoRoot:o,source:"state-scan"}:void 0}function tg(e){let t=e.length>1&&e.endsWith(kl)?e.slice(0,-1):e;return process.platform==="win32"?t.toLowerCase():t}function bS(e,t){return t===e||t.startsWith(e.endsWith(kl)?e:`${e}${kl}`)}var rg=T(()=>{Yo();Ye()});import{existsSync as og,readFileSync as ig}from"fs";import{isAbsolute as wS,join as _l}from"path";import{parse as SS}from"dotenv";function _S(){return{name:"dotenv",load:(e)=>{let t=ng(e.repoRoot,e.profile);if(e.workDir!=="")Object.assign(t,ng(e.workDir,e.profile));return t}}}function Rl(e){return async(t)=>{let r=t.includes("/versions/")?t:`${t}/versions/latest`,n=await e(),o=await fetch(`https://secretmanager.googleapis.com/v1/${r}:access`,{headers:{Authorization:`Bearer ${n}`}});if(!o.ok)throw M(X,`secret manager request failed for ${t}: HTTP ${o.status}`);let i=await o.json();if(!i.payload?.data)throw M(X,`secret manager response for ${t} had no payload`);return Buffer.from(i.payload.data,"base64").toString("utf8")}}function RS(e){let t=e?.environment.sources??[];if(t.length===0)return[...Cl];let r=new Set([...CS,...t]),n=new Set(Cl),o=t.filter((s)=>!n.has(s)),i=[];for(let s of Cl){if(s==="defaults")i.push(...o);if(r.has(s))i.push(s)}return i}async function Pl(e,t){let r={},n=t.serviceCfg.working_dir;if(n!==""&&!wS(n))n=_l(e,n);let o={repoRoot:e,profile:t.profile,service:t.service,serviceCfg:t.serviceCfg,workDir:n,cfg:t.cfg},i=PS(t),s={process:t.clientEnv??Ps(),profile:Qo(t.profileEnv,t.cfg,i),dotenv:Qo(await _S().load(o),t.cfg,i),generated:{},keychain:t.sourceValues?.keychain??ES(o),secret_manager:t.sourceValues?.secret_manager??await TS(o,t.fetchSecret),defaults:Qo(t.serviceCfg.environment.defaults,t.cfg,i),vars:Qo(t.serviceCfg.environment.vars,t.cfg,i),runtime:t.runtime};for(let a of RS(t.cfg)){if(s[a]!==void 0){Object.assign(r,s[a]);continue}let c=t.pluginSources?.find((l)=>l.name===a);if(c)Object.assign(r,Qo(await c.load(o),t.cfg,i))}for(let a of t.serviceCfg.environment.required)if((r[a]??"").trim()==="")throw M(X,`service ${t.service} missing required environment variable ${a}`);return r}function PS(e){let t={};if(e.cfg)for(let[r,n]of Object.entries(e.cfg.services)){let o={};for(let i of n.ports)if(!i.auto)o[i.name]=i.value;t[r]=o}if(e.assignedPorts)t[e.service]=e.assignedPorts;return t}function Qo(e,t,r){if(!t||Object.keys(e).length===0)return e;return ml(e,t,r)}function ES(e){let t=e.cfg?.environment.sources??[];if(t.length>0&&!t.includes("keychain"))return{};let r={},n=new Set([...Object.keys(e.serviceCfg.environment.defaults),...Object.keys(e.serviceCfg.environment.vars),...e.serviceCfg.environment.required]);for(let o of n){let i=_l(It(),"env",o);if(!og(i))continue;try{r[o]=ig(i,"utf8").replace(/\n$/,"")}catch(s){throw ye(X,`unable to read keychain env ${o}`,s)}}return r}async function TS(e,t){if(!(e.cfg?.environment.sources??[]).includes("secret_manager"))return{};let n=e.cfg?.environment.secrets??{},o={};for(let[i,s]of Object.entries(n)){if(!kS.test(s))throw M(X,`environment.secrets.${i} is not a Secret Manager resource`);if(!t)throw M(X,"environment source secret_manager is not configured \u2014 set credentials or remove it from environment.sources");o[i]=await t(s)}return o}function ng(e,t){let r={},n=[".env",".env.development",".env.local"];if(t!=="")n.push(`.env.${t}`);for(let o of n){let i=_l(e,o);if(!og(i))continue;try{let s=SS(ig(i));Object.assign(r,s)}catch(s){throw ye(X,`unable to read ${i}`,s)}}return r}function Ps(){let e={};for(let[t,r]of Object.entries(process.env))if(r!==void 0)e[t]=r;return e}function El(e,t,r,n,o){let i={DEVCTL_SERVICE_NAME:e,DEVCTL_ENVIRONMENT:o,SERVICE_HOST:t};if(n!=="")i.DEVCTL_PROXY_URL=n;if(r.http!==void 0)i.SERVICE_PORT=String(r.http);else{let s=Object.values(r)[0];if(s!==void 0)i.SERVICE_PORT=String(s)}for(let[s,a]of Object.entries(r))i[`${s.toUpperCase()}_PORT`]=String(a);return i}function Zo(e){return{...process.env,...e}}var Cl,kS,CS;var Tl=T(()=>{St();_e();Ye();Cl=["process","profile","dotenv","generated","keychain","secret_manager","defaults","vars","runtime"],kS=/^projects\/[^/]+\/secrets\/[^/]+(?:\/versions\/[^/]+)?$/,CS=["process","defaults","vars","runtime"]});function Pt(){return"devctl 0.1.2-bootstrap.0"}var at="0.1.2-bootstrap.0",ei=1;import{createConnection as AS}from"net";var{spawn:LS}=globalThis.Bun;function $S(e){if(e.legacy)return"attached daemon predates the client/daemon compatibility handshake";return`attached daemon speaks RPC protocol ${e.daemonProtocol??"unknown"}; this client speaks ${ei}`}function FS(e){if(e.compatible&&e.daemonVersion!==void 0&&e.daemonVersion!==at)return`attached daemon is devctl ${e.daemonVersion}; this client is ${at} (run \`devctl down\` then start again to update it)`;return}function Al(e,t){if(!e.compat.compatible&&!IS.has(t))throw be(nt,$S(e.compat),"run `devctl down` to stop it, then start again")}class ag{socket;buf="";pending=new Map;listeners=[];nextID=0;compat={compatible:!0,legacy:!1};session="";constructor(e){this.socket=e,e.on("data",(t)=>{this.buf+=t.toString("utf8");let r=this.buf.split(`
5
+ `));return n}function gS(e,t,r,n){let o=Zr(Lt(),"config.local.yaml"),i=Zr(t,wt,"config.local.yaml");for(let s of[o,i]){if(s===r||!Jo(s))continue;Xf(s,e,n)}return e}function Xf(e,t,r,n){let o=n!==void 0?Qf(n,e):wl(e),i=Qr(o,"");if(i.length>0)throw M(X,Hn(i));uf(t,o,r)}function mS(e,t,r){Yf(Zr(e,"services"),(o,i)=>{let s=Qr(i,`services.${o}`);if(s.length>0)throw M(X,Hn(s));let a=t.services[o];t.services[o]=a?ks(a,i):Vo(i),Ss(r.services,o,i)}),Yf(Zr(e,"profiles"),(o,i)=>{let s=Qr(i,`profiles.${o}`);if(s.length>0)throw M(X,Hn(s));t.profiles[o]=xs(i)});let n=Zr(e,"proxy","routes.yaml");if(Jo(n))hS(n,t)}function hS(e,t){let r=wl(e);if(G(r.proxy)){let n=Qr({proxy:r.proxy},"");if(n.length>0)throw M(X,Hn(n))}if(Array.isArray(r.routes))r.routes.forEach((n,o)=>{let i=Qr(n,`proxy.routes.${o}`);if(i.length>0)throw M(X,Hn(i))});if(G(r.proxy)){if(Array.isArray(r.proxy.routes))t.proxy.routes.push(...r.proxy.routes.map((n)=>zr(n)));if(G(r.proxy.listen)){if(typeof r.proxy.listen.host==="string"&&r.proxy.listen.host!=="")t.proxy.listen.host=r.proxy.listen.host;if(typeof r.proxy.listen.port==="number"&&r.proxy.listen.port!==0)t.proxy.listen.port=r.proxy.listen.port}}if(Array.isArray(r.routes))t.proxy.routes.push(...r.routes.map((n)=>zr(n)))}function Yf(e,t){let r;try{r=cS(e)}catch(n){if(yS(n))return;throw n}for(let n of r){let o=uS(n);if(o!==".yaml"&&o!==".yml")continue;let i=Zr(e,n),s=wl(i);t(zf(n,o),s)}}function wl(e){let t;try{t=lS(e,"utf8")}catch(r){throw ye(X,"unable to read config",r)}return Qf(t,e)}function Qf(e,t){let r;try{r=fS(e)}catch(n){throw ye(X,`invalid YAML in ${t}`,n)}if(r===null||r===void 0)return{};if(!G(r))throw M(X,`unable to decode config: ${t} is not a mapping`);return r}function yS(e){return typeof e==="object"&&e!==null&&"code"in e&&e.code==="ENOENT"}var Zf=T(()=>{_e();Ye();al();Yo();mf();ll();Wf();_s();Yo();_s()});var St=T(()=>{Zf();Yo();_s();ll();hl()});import{readdirSync as vS}from"fs";import{join as eg,resolve as Sl,sep as kl}from"path";function xS(e){let t=eg(Lt(),"state"),r;try{r=vS(t)}catch{return}let n=tg(Sl(e)),o;for(let i of r){let s=Jc(eg(t,i,"state.json"));if(!s)continue;let a=tg(Sl(s.repo_root));if(!bS(a,n))continue;if(!o||a.length>o.length)o=a}return o}function Rs(e,t,r=""){if(t!=="")return{repoRoot:Sl(t),source:"explicit"};let n=e===""?process.cwd():e;try{let{repoRoot:i}=Pr(n,r);return{repoRoot:i,source:"config"}}catch{if(r!=="")return}let o=xS(n);return o?{repoRoot:o,source:"state-scan"}:void 0}function tg(e){let t=e.length>1&&e.endsWith(kl)?e.slice(0,-1):e;return process.platform==="win32"?t.toLowerCase():t}function bS(e,t){return t===e||t.startsWith(e.endsWith(kl)?e:`${e}${kl}`)}var rg=T(()=>{Yo();Ye()});import{existsSync as og,readFileSync as ig}from"fs";import{isAbsolute as wS,join as _l}from"path";import{parse as SS}from"dotenv";function _S(){return{name:"dotenv",load:(e)=>{let t=ng(e.repoRoot,e.profile);if(e.workDir!=="")Object.assign(t,ng(e.workDir,e.profile));return t}}}function Rl(e){return async(t)=>{let r=t.includes("/versions/")?t:`${t}/versions/latest`,n=await e(),o=await fetch(`https://secretmanager.googleapis.com/v1/${r}:access`,{headers:{Authorization:`Bearer ${n}`}});if(!o.ok)throw M(X,`secret manager request failed for ${t}: HTTP ${o.status}`);let i=await o.json();if(!i.payload?.data)throw M(X,`secret manager response for ${t} had no payload`);return Buffer.from(i.payload.data,"base64").toString("utf8")}}function RS(e){let t=e?.environment.sources??[];if(t.length===0)return[...Cl];let r=new Set([...CS,...t]),n=new Set(Cl),o=t.filter((s)=>!n.has(s)),i=[];for(let s of Cl){if(s==="defaults")i.push(...o);if(r.has(s))i.push(s)}return i}async function Pl(e,t){let r={},n=t.serviceCfg.working_dir;if(n!==""&&!wS(n))n=_l(e,n);let o={repoRoot:e,profile:t.profile,service:t.service,serviceCfg:t.serviceCfg,workDir:n,cfg:t.cfg},i=PS(t),s={process:t.clientEnv??Ps(),profile:Qo(t.profileEnv,t.cfg,i),dotenv:Qo(await _S().load(o),t.cfg,i),generated:{},keychain:t.sourceValues?.keychain??ES(o),secret_manager:t.sourceValues?.secret_manager??await TS(o,t.fetchSecret),defaults:Qo(t.serviceCfg.environment.defaults,t.cfg,i),vars:Qo(t.serviceCfg.environment.vars,t.cfg,i),runtime:t.runtime};for(let a of RS(t.cfg)){if(s[a]!==void 0){Object.assign(r,s[a]);continue}let c=t.pluginSources?.find((l)=>l.name===a);if(c)Object.assign(r,Qo(await c.load(o),t.cfg,i))}for(let a of t.serviceCfg.environment.required)if((r[a]??"").trim()==="")throw M(X,`service ${t.service} missing required environment variable ${a}`);return r}function PS(e){let t={};if(e.cfg)for(let[r,n]of Object.entries(e.cfg.services)){let o={};for(let i of n.ports)if(!i.auto)o[i.name]=i.value;t[r]=o}if(e.assignedPorts)t[e.service]=e.assignedPorts;return t}function Qo(e,t,r){if(!t||Object.keys(e).length===0)return e;return ml(e,t,r)}function ES(e){let t=e.cfg?.environment.sources??[];if(t.length>0&&!t.includes("keychain"))return{};let r={},n=new Set([...Object.keys(e.serviceCfg.environment.defaults),...Object.keys(e.serviceCfg.environment.vars),...e.serviceCfg.environment.required]);for(let o of n){let i=_l(It(),"env",o);if(!og(i))continue;try{r[o]=ig(i,"utf8").replace(/\n$/,"")}catch(s){throw ye(X,`unable to read keychain env ${o}`,s)}}return r}async function TS(e,t){if(!(e.cfg?.environment.sources??[]).includes("secret_manager"))return{};let n=e.cfg?.environment.secrets??{},o={};for(let[i,s]of Object.entries(n)){if(!kS.test(s))throw M(X,`environment.secrets.${i} is not a Secret Manager resource`);if(!t)throw M(X,"environment source secret_manager is not configured \u2014 set credentials or remove it from environment.sources");o[i]=await t(s)}return o}function ng(e,t){let r={},n=[".env",".env.development",".env.local"];if(t!=="")n.push(`.env.${t}`);for(let o of n){let i=_l(e,o);if(!og(i))continue;try{let s=SS(ig(i));Object.assign(r,s)}catch(s){throw ye(X,`unable to read ${i}`,s)}}return r}function Ps(){let e={};for(let[t,r]of Object.entries(process.env))if(r!==void 0)e[t]=r;return e}function El(e,t,r,n,o){let i={DEVCTL_SERVICE_NAME:e,DEVCTL_ENVIRONMENT:o,SERVICE_HOST:t};if(n!=="")i.DEVCTL_PROXY_URL=n;if(r.http!==void 0)i.SERVICE_PORT=String(r.http);else{let s=Object.values(r)[0];if(s!==void 0)i.SERVICE_PORT=String(s)}for(let[s,a]of Object.entries(r))i[`${s.toUpperCase()}_PORT`]=String(a);return i}function Zo(e){return{...process.env,...e}}var Cl,kS,CS;var Tl=T(()=>{St();_e();Ye();Cl=["process","profile","dotenv","generated","keychain","secret_manager","defaults","vars","runtime"],kS=/^projects\/[^/]+\/secrets\/[^/]+(?:\/versions\/[^/]+)?$/,CS=["process","defaults","vars","runtime"]});function Pt(){return"devctl 0.1.4"}var at="0.1.4",ei=1;import{createConnection as AS}from"net";var{spawn:LS}=globalThis.Bun;function $S(e){if(e.legacy)return"attached daemon predates the client/daemon compatibility handshake";return`attached daemon speaks RPC protocol ${e.daemonProtocol??"unknown"}; this client speaks ${ei}`}function FS(e){if(e.compatible&&e.daemonVersion!==void 0&&e.daemonVersion!==at)return`attached daemon is devctl ${e.daemonVersion}; this client is ${at} (run \`devctl down\` then start again to update it)`;return}function Al(e,t){if(!e.compat.compatible&&!IS.has(t))throw be(nt,$S(e.compat),"run `devctl down` to stop it, then start again")}class ag{socket;buf="";pending=new Map;listeners=[];nextID=0;compat={compatible:!0,legacy:!1};session="";constructor(e){this.socket=e,e.on("data",(t)=>{this.buf+=t.toString("utf8");let r=this.buf.split(`
6
6
  `);this.buf=r.pop()??"";for(let n of r){if(n.trim()==="")continue;this.onLine(n)}}),e.on("error",(t)=>this.rejectPending(t instanceof Error?t:Error(String(t)))),e.on("close",()=>this.rejectPending(Error("supervisor connection closed")))}onLine(e){let t;try{t=JSON.parse(e)}catch{return}if(t.event){for(let n of this.listeners)n(t.event);return}let r=t.id?this.pending.get(t.id):void 0;if(!r)return;if(this.pending.delete(t.id??""),clearTimeout(r.timer),t.error){r.reject(qp({error:t.error,kind:t.kind,hint:t.hint,service:t.service}));return}r.resolve(t.result)}onEvent(e){return this.listeners.push(e),()=>{let t=this.listeners.indexOf(e);if(t>=0)this.listeners.splice(t,1)}}call(e,t,r=OS){this.nextID+=1;let n=String(this.nextID);return new Promise((o,i)=>{let s=setTimeout(()=>{this.pending.delete(n),i(Error(`${e} timed out after ${r}ms`))},r);this.pending.set(n,{resolve:o,reject:i,timer:s}),this.socket.write(JSON.stringify({id:n,method:e,params:t})+`
7
7
  `)})}close(){this.rejectPending(Error("supervisor connection closed")),this.socket.destroy()}rejectPending(e){for(let t of this.pending.values())clearTimeout(t.timer),t.reject(e);this.pending.clear()}}function cg(e,t){let r=ps(e),n=Date.now()+t;return new Promise((o,i)=>{let s=()=>{let a=AS(r);a.once("connect",()=>{let c=new ag(a);NS(c).finally(()=>o(c))}),a.once("error",(c)=>{if(a.destroy(),Date.now()>=n){i(be(nt,"supervisor is not running","run `devctl start` or `devctl attach` after starting services"));return}setTimeout(s,DS)})};s()})}async function NS(e){let t;try{t=await e.call("ping",null,sg)}catch{return}let r=HS(t)?t:{};if(typeof r.session==="string")e.session=r.session;let n=typeof r.protocol==="number"?r.protocol:void 0,o=typeof r.version==="string"?r.version:void 0;if(n===void 0){e.compat={compatible:!1,legacy:!0,daemonVersion:o};return}e.compat={compatible:n===ei,legacy:!1,daemonVersion:o,daemonProtocol:n}}function HS(e){return typeof e==="object"&&e!==null&&!Array.isArray(e)}async function en(e){try{return await cg(e,MS)}catch{return}}function jS(e,t,r,n){return r?[e,...n]:[e,t,...n]}async function lg(e,t){let r=await en(e);if(r)return r;Yp(e);let n=Go(e),o=jS(process.execPath,process.argv[1]??"",Bun.isStandaloneExecutable===!0,["--config",t,"_supervisor","--repo",e]);LS({cmd:o,env:process.env,stdout:"ignore",stderr:Bun.file(n),stdin:"ignore",detached:!0}).unref();try{return await cg(e,sg)}catch{throw be(nt,"supervisor failed to start",`see ${n} for details`)}}class Es{cfg;client;constructor(e){this.cfg=e}async start(e){return await this.call("start",{...e,client_env:Ps()})}async stop(e){await this.call("stop",{services:e})}async restart(e,t){await this.call("restart",{services:e,cascade:t===!0,client_env:Ps()})}async status(){return await this.call("status",null)}async refreshAuth(){return await this.call("auth_refresh",null)}async configSnapshot(){return await this.call("config_snapshot",null)}async logs(e){return(await this.call("logs",e)).events??[]}async logsPage(e){return await this.call("logs_page",e)}async logsStats(e){return await this.call("logs_stats",e)}async proxyStart(){await this.call("proxy_start",null)}async proxyStop(){await this.call("proxy_stop",null)}async mcpStart(e){await this.call("mcp_start",e??null)}async mcpStop(){await this.call("mcp_stop",null)}async mcpSetTools(e){return(await this.call("mcp_set_tools",{disabled:[...e]})).disabled_tools??[]}async reload(){return await this.call("reload",null)}async invalidateAuth(){await this.call("auth_invalidate",null)}onEvent(e){if(this.client)return this.client.onEvent(e);return()=>{return}}async close(e){if(!this.client)return;try{if(e?.shutdownSupervisor===!0&&e.detach!==!0){let t=Math.max(5000,this.cfg.shutdown.grace_seconds*1000+2000);await this.client.call("shutdown",{stop_services:!0},t)}}finally{this.client.close()}}async call(e,t){if(!this.client)throw ye(nt,"supervisor is not running",Error("no client"));return Al(this.client,e),this.client.call(e,t)}}function ti(e){let t=e&&FS(e.compat);if(t)process.stderr.write(`warning: ${t}
8
8
  `)}async function Ll(e,t,r=""){let n=Rs(e,t,r);if(!n)throw be(nt,"no devctl configuration found","run `devctl setup`, create a .devctl/config.yaml in the repository root, or pass --repo");let o=await en(n.repoRoot);return ti(o),{repoRoot:n.repoRoot,client:o}}async function Mt(e,t,r,n){let o=n?.allowMissingConfig===!0?zo(e,t):gt(e,t),i=new Es(o);if(!r)return i.client=await en(o.repoRoot),ti(i.client),i;return i.client=await lg(o.repoRoot,o.configPath),ti(i.client),i}async function dg(e){let t=new Es(Jr());return t.client=e,ti(t.client),t.cfg=await t.configSnapshot(),t}async function ug(e,t){let r=Rs(e,"",t),n=r?await en(r.repoRoot):void 0;if(!n)throw be(nt,"supervisor is not running","run `devctl start` before `devctl attach`");return dg(n)}async function pg(e,t){let r=Rs(e,"",t),n=r?await en(r.repoRoot):void 0;if(n)return dg(n);let o=gt(e,t),i=new Es(o);return i.client=await lg(o.repoRoot,o.configPath),ti(i.client),i.cfg=await i.configSnapshot(),i}var DS=50,sg=8000,MS=200,OS=30000,IS;var Dl=T(()=>{St();rg();Tl();_e();Ye();IS=new Set(["logs","logs_page","logs_stats"])});function As(e){if(ar(e))return Nt({kind:tn,serviceAccount:e.service_account});if(rf(e)&&(e.type!==""||e.mode!==""))return Nt({kind:Ts});return Nt({kind:Bn})}function Wn(e){if(e.type.toLowerCase()==="none")return Nt({kind:Bn});let t=e.identity.type.toLowerCase(),r=e.identity.service_account||e.service_account;if(t==="service"||t==="service_account"||e.type==="service_account")return Nt({kind:tn,serviceAccount:r});if(e.type.toLowerCase()==="iap"&&t==="")return Nt({kind:Bn});if(e.type===""&&t==="")return Nt({kind:Bn});return Nt({kind:Ts})}function Ls(e){return e.kind===Ts||e.kind===tn}function ri(e){if(e.kind===tn)return`sa:${e.serviceAccount}`;if(e.email!=="")return`user:${e.email}`;return"user"}function Nt(e={}){return{kind:Bn,email:"",serviceAccount:"",project:"",projectSource:"",adcAvailable:!1,...e}}function Ml(e){let t=new Map,r=(n,o)=>{if(n!=="")t.set(n,(t.get(n)??!1)||o)};for(let n of Object.values(e.services))if(ar(n.identity)&&n.identity.service_account!=="")r(n.identity.service_account,!0);for(let n of e.proxy.routes){let o=n.auth.type.toLowerCase(),i=n.auth.identity.type.toLowerCase(),s=n.auth.identity.service_account||n.auth.service_account;if(i==="service"||i==="service_account"||o==="service_account")r(s,o!=="none")}return[...t.entries()].map(([n,o])=>({email:n,active:o})).sort((n,o)=>n.email.localeCompare(o.email))}function Er(e){return Ml(e).filter((t)=>t.active).map((t)=>t.email)}function fg(e,t,r){let n=[];for(let o of t){let i=e.services[o];if(!i)continue;let s=As(i.identity);if(ar(i.identity)&&i.identity.service_account===""){n.push({name:o,message:"service account identity is not configured"});continue}if((Ls(s)||i.capabilities.some((c)=>c==="google_api"||c==="iap"||c==="service_identity"))&&!r)n.push({name:o,message:"ADC unavailable"})}return n}function ni(e){if(Er(e).length>0)return!0;if(e.proxy.routes.some((t)=>t.auth.type.toLowerCase()==="iap"))return!0;return Object.values(e.services).some((t)=>{if(Ls(As(t.identity)))return!0;return t.capabilities.some((r)=>r==="google_api"||r==="iap"||r==="service_identity")})}function Ol(){return{name:"user",accepts:(e)=>!ar(e),resolve:async(e,t)=>{if(e.type===""&&e.mode==="")return Nt({kind:Bn});return{...await t(),kind:Ts}}}}function Il(){return{name:"service_account",accepts:(e)=>ar(e),resolve:async(e,t)=>{if(e.service_account==="")throw M(ls,"service account identity is not configured");return{...await t(),kind:tn,serviceAccount:e.service_account}}}}async function gg(e,t,r){if(r)for(let n=r.length-1;n>=0;n-=1){let o=r[n];if(o?.accepts(e))return o.resolve(e,t)}if(ar(e))return Il().resolve(e,t);return Ol().resolve(e,t)}var Ts="user",tn="service_account",Bn="none";var rn=T(()=>{St();_e()});import{existsSync as Ds,readFileSync as BS}from"fs";import{homedir as hg}from"os";import{join as $l}from"path";var{spawn:Fl}=globalThis.Bun;function Un(){let e=globalThis;if(e.window&&typeof e.window.fetch!=="function")e.window.fetch=fetch}function Nl(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS||$l(hg(),".config","gcloud","application_default_credentials.json");if(!Ds(e))return"";try{let t=JSON.parse(BS(e,"utf8"));return typeof t.quota_project_id==="string"?t.quota_project_id:""}catch{return""}}async function Ht(e){let t={gcloudInstalled:await Hl("gcloud"),adcAvailable:!1,userEmail:"",projectID:"",projectSource:""};if(e!=="")t.projectID=e,t.projectSource="configuration";else{let r=JS("GOOGLE_CLOUD_PROJECT","GCLOUD_PROJECT","GOOGLE_PROJECT");if(r!=="")t.projectID=r,t.projectSource="environment variable";else if(t.gcloudInstalled){let n=await mg("core/project");if(n!=="")t.projectID=n,t.projectSource="gcloud configuration"}}if(oi())try{await wg(US(t),GS)}catch(r){t.adcAvailable=!1,t.error=Kn(r)}if(t.userEmail===""&&t.gcloudInstalled)t.userEmail=await mg("core/account");return t}async function US(e){Un();let{GoogleAuth:t}=await import("google-auth-library"),r=new t({scopes:[WS]});await r.getClient(),e.adcAvailable=!0;let n=await r.getProjectId().catch(()=>"");if(e.projectID===""&&n)e.projectID=n,e.projectSource="application default credentials";let o=await KS(r);if(o!=="")e.userEmail=o}async function KS(e){try{let t=await e.getCredentials();if(t.client_email)return t.client_email}catch{}try{let t=await e.getClient(),r=typeof t.credentials?.id_token==="string"?t.credentials.id_token:"";if(r!==""){let n=qS(r);if(n!=="")return n}}catch{return""}return""}function qS(e){let t=e.split(".");if(t.length<2||!t[1])return"";try{let r=JSON.parse(Buffer.from(t[1],"base64url").toString("utf8"));return typeof r.email==="string"?r.email:""}catch{return""}}async function vg(e){let t=await Ht(e);return Nt({kind:"user",email:t.userEmail,project:t.projectID,projectSource:t.projectSource,adcAvailable:t.adcAvailable})}async function Ms(){if(await Fl({cmd:["gcloud","auth","application-default","login"],stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited!==0)throw be(In,"application-default login failed","run `gcloud auth application-default login`")}async function xg(){if(await Fl({cmd:["gcloud","auth","application-default","revoke","--quiet"],stdout:"ignore",stderr:"pipe"}).exited!==0)throw be(In,"failed to revoke application-default credentials","run `gcloud auth application-default revoke`")}function Kn(e){let t=VS(e).toLowerCase();if(Gn(t,["unauth","invalid_grant","token has been expired","expired"]))return be(In,"credential expired or invalid","run `devctl auth login` or `gcloud auth application-default login`");if(Gn(t,["api has not been used","has not been enabled","access not configured","service_disabled"]))return be(qr,"required Google API is not enabled","enable the API in the target service account project; devctl will not enable APIs automatically");if(Gn(t,["permission","forbidden","iam"])){if(Gn(t,["serviceaccounttoken","iamcredentials","token creator","getaccesstoken"]))return be(ls,"cannot impersonate service account","ask an administrator to grant roles/iam.serviceAccountTokenCreator on the target service account");return be(qr,"authorization failure","verify IAM permissions for the current user on this project")}if(t.includes("audience"))return be(jc,"IAP audience is incorrect","set auth.audience on the proxy route to the IAP OAuth client ID");if(t.includes("iap"))return ye(jc,"IAP authentication failure",e);if(t.includes("project"))return be(X,"wrong or missing Google project","set google.project_id in .devctl/config.yaml");if(Gn(t,["timeout","network","connection refused","no such host"]))return ye(nt,"network problem reaching Google Cloud",e);if(Gn(t,["adc","default credentials","could not find"]))return be(In,"application default credentials unavailable","run `gcloud auth application-default login`");return ye(In,"Google authentication failed",e)}function VS(e){let t=[],r=new Set,n=(o,i)=>{if(o===null||o===void 0||i>8||r.has(o))return;if(typeof o==="string"){t.push(o);return}if(typeof o!=="object")return;r.add(o);let s=o;for(let a of["message","reason","status","code","error_description","permission","service"])n(s[a],i+1);for(let a of["error","errors","details","response","data","cause","metadata"]){let c=s[a];if(Array.isArray(c))c.forEach((l)=>n(l,i+1));else n(c,i+1)}};return n(e,0),t.length>0?t.join(" "):String(e)}function Gn(e,t){return t.some((r)=>e.includes(r))}function JS(...e){for(let t of e){let r=process.env[t];if(r)return r}return""}async function Hl(e){try{return(await bg(process.platform==="win32"?["where",e]:["which",e],yg)).code===0}catch{return!1}}function oi(){let e=process.env.GOOGLE_APPLICATION_CREDENTIALS;if(e&&Ds(e))return!0;if(Ds($l(hg(),".config","gcloud","application_default_credentials.json")))return!0;let t=process.env.APPDATA;return Boolean(t&&Ds($l(t,"gcloud","application_default_credentials.json")))}async function mg(e){try{let t=await bg(["gcloud","config","get-value",e],yg);if(t.code!==0)return"";let r=t.stdout.trim();if(r===""||r==="(unset)")return"";return r}catch{return""}}async function bg(e,t){let r=Fl({cmd:e,stdout:"pipe",stderr:"ignore",env:{...process.env,CLOUDSDK_CORE_DISABLE_PROMPTS:"1",CLOUDSDK_CORE_DISABLE_USAGE_REPORTING:"true"}}),n=r.stdout?new Response(r.stdout).text():Promise.resolve("");try{let[o,i]=await wg(Promise.all([n,r.exited]),t);return{code:i??1,stdout:o}}catch{return r.kill(),{code:1,stdout:""}}}function wg(e,t){return new Promise((r,n)=>{let o=setTimeout(()=>n(Error("timeout")),t);e.then((i)=>{clearTimeout(o),r(i)},(i)=>{clearTimeout(o),n(i)})})}var WS="https://www.googleapis.com/auth/cloud-platform",yg=1500,GS=2000;var nn=T(()=>{On();_e();rn()});var{spawn:jl}=globalThis.Bun;import{createServer as Sg}from"net";async function kg(e,t,r={}){let n={};for(let[i,s]of Object.entries(r))for(let a of Object.values(s))n[a]=i;let o={};for(let[i,s]of Object.entries(e.services)){if(t.length>0&&!t.includes(i))continue;let a={};for(let c of s.ports){let l=r[i]?.[c.name],d=l&&l>=Bl?l:c.value;if(l===void 0&&c.auto)d=await zS();if(d<Bl||d>YS)throw new Te(X,`invalid port ${d} on service ${i}`,{service:i});if(n[d]&&n[d]!==i)throw new Te(X,`duplicate port ${d} used by ${n[d]} and ${i}`,{service:i});if(l!==d&&!c.auto&&!await qn(d))throw await XS(i,c.name,d);n[d]=i,a[c.name]=d}o[i]=a}return o}function zS(){return new Promise((e,t)=>{let r=Sg();r.listen(0,"127.0.0.1",()=>{let n=r.address();r.close(()=>{if(n&&typeof n==="object")e(n.port);else t(ye(X,"unable to allocate dynamic port",Error("no address")))})}),r.on("error",(n)=>t(ye(X,"unable to allocate dynamic port",n)))})}async function Os(e){let t=e.ports.filter((n)=>!n.auto&&n.value>=Bl);if(t.length===0)return;let r={};for(let n of t){if(await qn(n.value))return;r[n.name]=n.value}return r}function qn(e){return new Promise((t)=>{let r=Sg();r.listen(e,"127.0.0.1",()=>{r.close(()=>t(!0))}),r.on("error",()=>t(!1))})}async function XS(e,t,r){let n=await Vn(r);return QS(e,t,r,n)}function QS(e,t,r,n){let o=t===""?`${e} port`:`${e} ports.${t}`;if(n&&n.pid===process.pid)return be(bt,`${e} blocked: this TUI already holds port ${r}`,`Stop the proxy from the Proxy screen, or change ${o} in .devctl.`,e);if(n)return be(bt,`${e} blocked: ${n.command} (pid ${n.pid}) is using port ${r}`,`Open Doctor and press enter to free port ${r}, or change ${o} in .devctl.`,e);return be(bt,`${e} blocked: port ${r} is already in use`,`Something is listening on ${r}. Open Doctor to free it, or change ${o} in .devctl.`,e)}function ZS(e,t){let r=e.split(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@amr-m-abdelgawad/devctl",
3
- "version": "0.1.2-bootstrap.0",
3
+ "version": "0.1.4",
4
4
  "description": "Local development orchestrator",
5
5
  "license": "MIT",
6
6
  "type": "module",