denvig 0.4.1 → 0.4.3

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.
package/dist/cli.cjs CHANGED
@@ -1,53 +1,68 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Mn=Object.create;var Ge=Object.defineProperty;var _n=Object.getOwnPropertyDescriptor;var Jn=Object.getOwnPropertyNames;var Gn=Object.getPrototypeOf,qn=Object.prototype.hasOwnProperty;var h=(s,e)=>()=>(s&&(e=s(s=0)),e);var C=(s,e)=>{for(var t in e)Ge(s,t,{get:e[t],enumerable:!0})},Un=(s,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Jn(e))!qn.call(s,r)&&r!==t&&Ge(s,r,{get:()=>e[r],enumerable:!(n=_n(e,r))||n.enumerable});return s};var F=(s,e,t)=>(t=s!=null?Mn(Gn(s)):{},Un(e||!s||!s.__esModule?Ge(t,"default",{value:s,enumerable:!0}):t,s));var $,Hn,qe,Ce,Ue=h(()=>{"use strict";$=require("zod"),Hn=["build","check-types","dev","install","lint","outdated","test"],qe=$.z.object({codeRootDir:$.z.string().optional().default("~/src").describe("The base directory where projects are stored"),quickActions:$.z.array($.z.string()).default(Hn).optional().describe("Quick actions that are available for all projects")}),Ce=$.z.object({name:$.z.string().describe("Unique identifier for the project"),actions:$.z.record($.z.string().describe("Name of the action"),$.z.object({command:$.z.string().describe("Shell command to run for the action")})).optional().describe("Actions that can be run against the project"),quickActions:$.z.array($.z.string()).optional().describe("Actions that are available on the CLI root for quick access"),services:$.z.record($.z.string(),$.z.object({cwd:$.z.string().optional().describe("Working directory for the service (relative to project root)"),command:$.z.string().describe("Shell command to execute"),http:$.z.object({port:$.z.number().optional().describe("Port number the service listens on"),domain:$.z.string().optional().describe("Domain to use for the service URL"),secure:$.z.boolean().optional().describe("Use HTTPS instead of HTTP")}).strict().optional().describe("HTTP configuration for the service URL"),envFile:$.z.string().optional().describe("Path to .env file (relative to project root)"),env:$.z.record($.z.string(),$.z.string()).optional().describe("Environment variables"),keepAlive:$.z.boolean().optional().describe("Restart service if it exits")}).strict()).optional().describe("Service that can be managed for this project")}).strict()});var ht,zn,me,He=h(()=>{"use strict";ht=require("fs"),zn=require("fs/promises"),me=s=>{try{return(0,ht.readFileSync)(s,"utf8").trim()||null}catch(e){if(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")return null;throw e}}});var Z,ze,Oe,Bn,yt,W,vt,ge=h(()=>{"use strict";Z=require("path"),ze=require("yaml");Ue();He();Oe=(0,Z.resolve)(process.env.DENVIG_GLOBAL_CONFIG_PATH||`${process.env.HOME}/.denvig/config.yml`),Bn=(0,Z.resolve)(process.env.DENVIG_CODE_ROOT_DIR||`${process.env.HOME}/src`),yt={codeRootDir:Bn,quickActions:void 0},W=()=>{let s=me(Oe);if(s){let e=(0,ze.parse)(s)||{};try{if(e.codeRootDir?.startsWith(".")){let t=(0,Z.dirname)(Oe);e.codeRootDir=(0,Z.resolve)(`${t}/${e.codeRootDir}`)}return{...qe.parse({...yt,...e}),$sources:[Oe]}}catch(t){console.error(`Error parsing global config at ${Oe}:`,t),process.exit(1)}}return{...qe.parse(yt),$sources:[]}},vt=s=>{let e=W(),t={name:s,actions:{}},n=`${e.codeRootDir}/${s}/.denvig.yml`,r=me(n);if(r)try{return{...t,...Ce.parse((0,ze.parse)(r)),$sources:[n]}}catch(c){console.warn(`Error parsing project config for ${s} at ${n}.`),c instanceof Error?console.warn(c.message):console.warn("Unknown error:",c)}return{...t,$sources:[]}}});var Re,Be=h(()=>{"use strict";Re=(s,e)=>{for(let[t,n]of Object.entries(e))s[t]||(s[t]=[]),s[t].push(...n);return s}});var Ye,_,fe=h(()=>{"use strict";Ye=F(require("fs"),1),_=s=>{let e=`${s.path}/package.json`;if(!Ye.default.existsSync(e))return null;let t=Ye.default.readFileSync(e,"utf-8");return JSON.parse(t)}});var R,B=h(()=>{"use strict";R=s=>s});var J,Yn,bt,Dt=h(()=>{"use strict";J=F(require("fs"),1);Be();fe();B();Yn=R({name:"deno",actions:async s=>{let e=J.default.readdirSync(s.path);if(!(e.includes("deno.json")||e.includes("deno.jsonc")))return{};let r=_(s)?.scripts||{},c={...Object.entries(r).map(([i,o])=>[i,`deno ${o}`]).reduce((i,[o,p])=>(i[o]=[p],i),{}),install:["deno install"],outdated:["deno outdated"]},l=((0,J.existsSync)(`${s.path}/deno.json`)?JSON.parse((0,J.readFileSync)(`${s.path}/deno.json`,"utf8")):(0,J.existsSync)(`${s.path}/deno.jsonc`)?JSON.parse((0,J.readFileSync)(`${s.path}/deno.jsonc`,"utf8")):{}).tasks||{};return c=Re(c,{test:[l?.test?"deno task test":"deno test"],lint:[l?.lint?"deno task lint":"deno lint"],"check-types":[l?.checkTypes?"deno task check-types":"deno check"],...Object.entries(l).reduce((i,[o,p])=>(i[o]=[p.startsWith("deno")?p:`deno task ${o}`],i),{}),install:["deno install"],outdated:["deno outdated"]}),c}}),bt=Yn});var Pt,Kn,St,jt=h(()=>{"use strict";Pt=F(require("fs"),1);fe();B();Kn=R({name:"npm",actions:async s=>{let e=Pt.default.readdirSync(s.path),t=e.includes("package.json"),n=e.includes("package-lock.json");if(!(t&&n))return{};let a=_(s)?.scripts||{};return{...Object.entries(a).map(([i,o])=>[i,`npm run ${i}`]).reduce((i,[o,p])=>(i[o]=[p],i),{}),install:["npm install"],outdated:["npm outdated"]}}}),St=Kn});var N,$t,Zn,Qn,Xn,wt,er,tr,sr,kt,xt=h(()=>{"use strict";N=require("fs"),$t=require("os"),Zn=1800*1e3,Qn=()=>{let s=`${(0,$t.homedir)()}/.cache/denvig/dependencies/npm`;return(0,N.existsSync)(s)||(0,N.mkdirSync)(s,{recursive:!0}),s},Xn=s=>{let e=s.replace(/@/g,"_at_").replace(/\//g,"__");return e=e.replace(/[^a-zA-Z0-9\-_.]/g,"_"),e=e.replace(/\.{2,}/g,"_"),e=e.replace(/^\.+/,"_"),e.length===0&&(e="_empty_"),e.length>200&&(e=e.slice(0,200)),e},wt=s=>{let e=Xn(s);return`${Qn()}/${e}.json`},er=s=>{try{let e=(0,N.statSync)(s);return Date.now()-e.mtimeMs<Zn}catch{return!1}},tr=s=>{let e=wt(s);if(!(0,N.existsSync)(e)||!er(e))return null;try{let t=(0,N.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},sr=(s,e)=>{try{let t=wt(s);(0,N.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},kt=async(s,e=!1)=>{if(!e){let t=tr(s);if(t)return t}try{let t=await fetch(`https://registry.npmjs.com/${encodeURIComponent(s)}`,{headers:{Accept:"application/json"}});if(!t.ok)return null;let n=await t.json(),r=Object.keys(n.versions),c=n["dist-tags"]?.latest||r[r.length-1],a={versions:r,latest:c};return sr(s,a),a}catch{return null}}});var Q,Ne,nr,rr,or,Le,Ke=h(()=>{"use strict";xt();Q=s=>{let e=s.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);return e?{major:Number.parseInt(e[1],10),minor:Number.parseInt(e[2],10),patch:Number.parseInt(e[3],10),prerelease:e[4]||""}:null},Ne=(s,e)=>{let t=Q(s),n=Q(e);return!t||!n?0:t.major!==n.major?t.major-n.major:t.minor!==n.minor?t.minor-n.minor:t.patch!==n.patch?t.patch-n.patch:t.prerelease&&!n.prerelease?-1:!t.prerelease&&n.prerelease?1:0},nr=(s,e)=>{let t=Q(s);if(!t||t.prerelease)return!1;if(e.startsWith("^")){let r=Q(e.slice(1));return r?r.major===0?t.major===0&&t.minor===r.minor&&t.patch>=r.patch:t.major===r.major&&Ne(s,e.slice(1))>=0:!1}if(e.startsWith("~")){let r=Q(e.slice(1));return r?t.major===r.major&&t.minor===r.minor&&t.patch>=r.patch:!1}if(e.startsWith(">="))return Ne(s,e.slice(2))>=0;if(e.startsWith(">")&&!e.startsWith(">="))return Ne(s,e.slice(1))>0;let n=Q(e);return n?t.major===n.major&&t.minor===n.minor&&t.patch===n.patch:!1},rr=(s,e)=>{let t=s.filter(n=>nr(n,e)).sort(Ne);return t.length>0?t[t.length-1]:null},or=s=>{if(s.versions.length===0)return null;let e=s.versions[0],t=e.source.includes("#devDependencies");return{current:e.resolved,specifier:e.specifier,isDevDependency:t}},Le=async(s,e={})=>{let t=e.cache??!0,n=[],c=s.filter(a=>a.versions.some(l=>l.source.includes("#dependencies")||l.source.includes("#devDependencies"))).map(async a=>{let l=or(a);if(!l)return;let i=await kt(a.name,!t);if(!i)return;let o=rr(i.versions,l.specifier),p=i.latest,u=o&&o!==l.current,m=p&&p!==l.current;(u||m)&&n.push({...a,wanted:o||l.current,latest:p,specifier:l.specifier,isDevDependency:l.isDevDependency})});return await Promise.all(c),n}});var he,Ot,Ct,Ze,Rt,Nt,Lt=h(()=>{"use strict";he=require("fs"),Ot=require("yaml");Ke();fe();B();Ct=new Map,Ze=s=>{let e=s.indexOf("(");return e===-1?s:s.slice(0,e)},Rt=R({name:"pnpm",actions:async s=>{if(!s.rootFiles.includes("pnpm-lock.yaml"))return{};let r=_(s)?.scripts||{},c=s.rootFiles.includes("pnpm-workspace.yaml");return{...Object.entries(r).map(([l,i])=>[l,`pnpm run ${l}`]).reduce((l,[i,o])=>(l[i]=[o],l),{}),install:["pnpm install"],outdated:[c?"pnpm outdated -r":"pnpm outdated"]}},dependencies:async s=>{if(!(0,he.existsSync)(`${s.path}/pnpm-lock.yaml`))return[];let e=Ct.get(s.path);if(e)return e;let t=new Map,n=new Set,r=(o,p,u,m,d,g)=>{let f=t.get(o);f?f.versions.push({resolved:m,specifier:g,source:d}):t.set(o,{id:o,name:p,ecosystem:u,versions:[{resolved:m,specifier:g,source:d}]})};t.set("npm:pnpm",{id:"npm:pnpm",name:"pnpm",ecosystem:"system",versions:[]});let c=`${s.path}/pnpm-lock.yaml`,a=(0,he.readFileSync)(c,"utf-8"),l=(0,Ot.parse)(a);if(l?.importers)for(let[o,p]of Object.entries(l.importers)){let u=o==="."?".":o;if(p.dependencies)for(let[m,d]of Object.entries(p.dependencies))d?.specifier&&d?.version&&(n.add(m),r(`npm:${m}`,m,"npm",Ze(d.version),`${u}#dependencies`,d.specifier));if(p.devDependencies)for(let[m,d]of Object.entries(p.devDependencies))d?.specifier&&d?.version&&(n.add(m),r(`npm:${m}`,m,"npm",Ze(d.version),`${u}#devDependencies`,d.specifier))}if(l?.snapshots)for(let[o,p]of Object.entries(l.snapshots)){let u={...p.dependencies};for(let[m,d]of Object.entries(u))if(!n.has(m)){let g=Ze(d),f=`pnpm-lock.yaml:${o}`;r(`npm:${m}`,m,"npm",g,f,g)}}let i=Array.from(t.values()).sort((o,p)=>o.name.localeCompare(p.name));return Ct.set(s.path,i),i},outdatedDependencies:async(s,e)=>{if(!(0,he.existsSync)(`${s.path}/pnpm-lock.yaml`))return[];let t=await Rt.dependencies?.(s);return t?Le(t,e):[]}}),Nt=Rt});var L,Tt,ir,cr,ar,It,lr,pr,dr,At,Ft=h(()=>{"use strict";L=require("fs"),Tt=require("os"),ir=1800*1e3,cr=()=>{let s=`${(0,Tt.homedir)()}/.cache/denvig/dependencies/rubygems`;return(0,L.existsSync)(s)||(0,L.mkdirSync)(s,{recursive:!0}),s},ar=s=>{let e=s.replace(/[^a-zA-Z0-9\-_.]/g,"_");return e=e.replace(/\.{2,}/g,"_"),e=e.replace(/^\.+/,"_"),e.length===0&&(e="_empty_"),e.length>200&&(e=e.slice(0,200)),e},It=s=>{let e=ar(s);return`${cr()}/${e}.json`},lr=s=>{try{let e=(0,L.statSync)(s);return Date.now()-e.mtimeMs<ir}catch{return!1}},pr=s=>{let e=It(s);if(!(0,L.existsSync)(e)||!lr(e))return null;try{let t=(0,L.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},dr=(s,e)=>{try{let t=It(s);(0,L.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},At=async(s,e=!1)=>{if(!e){let t=pr(s);if(t)return t}try{let t=await fetch(`https://rubygems.org/api/v1/versions/${encodeURIComponent(s)}.json`,{headers:{Accept:"application/json"}});if(!t.ok)return null;let n=await t.json(),r=n.map(i=>i.number),a=n.filter(i=>!i.prerelease).map(i=>i.number)[0]||r[0],l={versions:r,latest:a};return dr(s,l),l}catch{return null}}});var ee,X,ur,mr,gr,Et,Vt=h(()=>{"use strict";Ft();ee=s=>{let e=s.match(/^(\d+)\.(\d+)(?:\.(\d+))?(?:-(.+)|\.(.+))?$/);return e?{major:Number.parseInt(e[1],10),minor:Number.parseInt(e[2],10),patch:e[3]?Number.parseInt(e[3],10):0,prerelease:e[4]||e[5]||""}:null},X=(s,e)=>{let t=ee(s),n=ee(e);return!t||!n?0:t.major!==n.major?t.major-n.major:t.minor!==n.minor?t.minor-n.minor:t.patch!==n.patch?t.patch-n.patch:t.prerelease&&!n.prerelease?-1:!t.prerelease&&n.prerelease?1:0},ur=(s,e)=>{let t=ee(s);if(!t||t.prerelease)return!1;if(e==="*")return!0;let n=e.trim();if(n.startsWith("~>")){let c=n.slice(2).trim(),a=ee(c);return a?c.split(".").length>=3?t.major===a.major&&t.minor===a.minor&&t.patch>=a.patch:t.major===a.major&&t.minor>=a.minor&&X(s,`${a.major}.${a.minor}.0`)>=0:!1}if(n.startsWith(">="))return X(s,n.slice(2).trim())>=0;if(n.startsWith(">")&&!n.startsWith(">="))return X(s,n.slice(1).trim())>0;if(n.startsWith("<="))return X(s,n.slice(2).trim())<=0;if(n.startsWith("<")&&!n.startsWith("<="))return X(s,n.slice(1).trim())<0;if(n.startsWith("=")){let c=n.slice(1).trim(),a=ee(c);return a?t.major===a.major&&t.minor===a.minor&&t.patch===a.patch:!1}let r=ee(n);return r?t.major===r.major&&t.minor===r.minor&&t.patch===r.patch:!1},mr=(s,e)=>{let t=s.filter(n=>ur(n,e)).sort(X);return t.length>0?t[t.length-1]:null},gr=s=>{if(s.versions.length===0)return null;let e=s.versions[0],t=e.source.includes("#devDependencies");return{current:e.resolved,specifier:e.specifier,isDevDependency:t}},Et=async(s,e={})=>{let t=e.cache??!0,n=[],c=s.filter(a=>a.versions.some(l=>l.source.includes("#dependencies")||l.source.includes("#devDependencies"))).map(async a=>{let l=gr(a);if(!l)return;let i=await At(a.name,!t);if(!i)return;let o=mr(i.versions,l.specifier),p=i.latest,u=o&&o!==l.current,m=p&&p!==l.current;(u||m)&&n.push({...a,wanted:o||l.current,latest:p,specifier:l.specifier,isDevDependency:l.isDevDependency})});return await Promise.all(c),n}});var te,fr,hr,Wt,Mt=h(()=>{"use strict";te=require("fs"),fr=s=>{let e=[],t=s.split(`
3
- `),n="dependencies",r=0;for(let c of t){let a=c.trim();if(a.startsWith("#")||a==="")continue;if(a.startsWith("group ")){(a.includes(":development")||a.includes(":test"))&&(n="devDependencies"),a.includes(" do")&&r++;continue}if(a==="end"){r--,r<=0&&(n="dependencies",r=0);continue}let l=a.match(/^gem\s+['"]([^'"]+)['"](?:\s*,\s*['"]([^'"]+)['"])?/);if(l){let i=l[1],o=l[2]||"*";e.push({name:i,specifier:o,group:n})}}return e},hr=s=>{let e={},t={},n=s.split(`
4
- `),r="none",c=null,a=null;for(let l of n){let i=l.trimEnd();if(i==="GEM"){r="gem";continue}if(i==="PLATFORMS"){r="platforms";continue}if(i==="DEPENDENCIES"){r="dependencies";continue}if(i==="BUNDLED WITH"){r="none";continue}if(r==="gem"&&i===" specs:"){r="specs";continue}if(r==="specs"){if(i==="")continue;let o=l.match(/^(\s*)/),p=o?o[1].length:0,u=l.trim();if(p===4){let m=u.match(/^([^\s(]+)\s+\(([^)]+)\)/);if(m){let d=m[2],g=d.match(/^[\d.]+/),f=g?g[0]:d;c=m[1],a=f,e[c]||(e[c]={version:f,dependencies:{}})}}else if(p===6&&c&&a){let m=u.match(/^([^\s(]+)(?:\s+\(([^)]+)\))?/);if(m){let d=m[1],g=m[2]||"*";e[c].dependencies[d]=g}}}if(r==="dependencies"){if(i===""||i.startsWith(" ")===!1)continue;let o=i.match(/^\s+([^\s(!]+)(?:\s+\(([^)]+)\))?/);if(o){let u=o[1].replace(/!$/,""),m=o[2]||"*";t[u]=m}}}return{specs:e,dependencies:t}},Wt=async s=>{let e=`${s.path}/Gemfile`,t=`${s.path}/Gemfile.lock`;if(!(0,te.existsSync)(e))return[];let n=new Map,r=new Set,c=(0,te.readFileSync)(e,"utf-8"),a=fr(c),l=(i,o,p,u,m,d)=>{let g=n.get(i);g?g.versions.push({resolved:u,specifier:d,source:m}):n.set(i,{id:i,name:o,ecosystem:p,versions:[{resolved:u,specifier:d,source:m}]})};n.set("rubygems:bundler",{id:"rubygems:bundler",name:"bundler",ecosystem:"system",versions:[]});for(let i of a)r.add(i.name);if((0,te.existsSync)(t)){let i=(0,te.readFileSync)(t,"utf-8"),o=hr(i);for(let p of a){let u=o.specs[p.name];u&&l(`rubygems:${p.name}`,p.name,"rubygems",u.version,`.#${p.group}`,p.specifier)}for(let[p,u]of Object.entries(o.specs))if(!r.has(p)){for(let[m,d]of Object.entries(o.specs))if(d.dependencies[p]){let g=`Gemfile.lock:${m}@${d.version}`,f=d.dependencies[p];l(`rubygems:${p}`,p,"rubygems",u.version,g,f)}}}else for(let i of a)l(`rubygems:${i.name}`,i.name,"rubygems",i.specifier,`.#${i.group}`,i.specifier);return Array.from(n.values()).sort((i,o)=>i.name.localeCompare(o.name))}});var Qe,_t,Jt,Gt,qt=h(()=>{"use strict";Qe=F(require("fs"),1);B();Vt();Mt();_t=new Map,Jt=R({name:"ruby",actions:async s=>{let e=Qe.default.readdirSync(s.path),t=e.includes("Gemfile"),n=e.includes("Rakefile"),r=e.includes("config.ru"),c=Qe.default.existsSync(`${s.path}/config/application.rb`);if(!(t||n))return{};let l={install:["bundle install"],update:["bundle update"],outdated:["bundle outdated"]};return c&&(l.dev=["bundle exec rails server"],l.repl=["bundle exec rails console"]),r&&!c&&(l.dev=["bundle exec rackup"]),l},dependencies:async s=>{if(!s.rootFiles.includes("Gemfile"))return[];let t=_t.get(s.path);if(t)return t;let n=await Wt(s);return _t.set(s.path,n),n},outdatedDependencies:async(s,e)=>{if(!s.rootFiles.includes("Gemfile"))return[];let n=await Jt.dependencies?.(s);return n?Et(n,e):[]}}),Gt=Jt});var T,Ut,yr,vr,br,Ht,Dr,Pr,Sr,zt,Bt=h(()=>{"use strict";T=require("fs"),Ut=require("os"),yr=1800*1e3,vr=()=>{let s=`${(0,Ut.homedir)()}/.cache/denvig/dependencies/pypi`;return(0,T.existsSync)(s)||(0,T.mkdirSync)(s,{recursive:!0}),s},br=s=>{let e=s.toLowerCase().replace(/[-_.]+/g,"-");return e=e.replace(/[^a-zA-Z0-9-]/g,"_"),e=e.replace(/\.{2,}/g,"_"),e=e.replace(/^\.+/,"_"),e.length===0&&(e="_empty_"),e.length>200&&(e=e.slice(0,200)),e},Ht=s=>{let e=br(s);return`${vr()}/${e}.json`},Dr=s=>{try{let e=(0,T.statSync)(s);return Date.now()-e.mtimeMs<yr}catch{return!1}},Pr=s=>{let e=Ht(s);if(!(0,T.existsSync)(e)||!Dr(e))return null;try{let t=(0,T.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},Sr=(s,e)=>{try{let t=Ht(s);(0,T.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},zt=async(s,e=!1)=>{let t=s.toLowerCase().replace(/_/g,"-");if(!e){let n=Pr(t);if(n)return n}try{let n=await fetch(`https://pypi.org/pypi/${encodeURIComponent(t)}/json`,{headers:{Accept:"application/json"}});if(!n.ok)return null;let r=await n.json(),c=Object.entries(r.releases).filter(([,i])=>i.length>0).map(([i])=>i),a=r.info?.version||c[c.length-1],l={versions:c,latest:a};return Sr(t,l),l}catch{return null}}});var ne,se,jr,$r,wr,kr,Yt,Kt=h(()=>{"use strict";Bt();ne=s=>{let e=s.match(/^(\d+)\.(\d+)(?:\.(\d+))?(?:\.(\d+))?(.*)$/);return e?{major:Number.parseInt(e[1],10),minor:Number.parseInt(e[2],10),patch:e[3]?Number.parseInt(e[3],10):0,prerelease:e[5]||""}:null},se=(s,e)=>{let t=ne(s),n=ne(e);return!t||!n?0:t.major!==n.major?t.major-n.major:t.minor!==n.minor?t.minor-n.minor:t.patch!==n.patch?t.patch-n.patch:t.prerelease&&!n.prerelease?-1:!t.prerelease&&n.prerelease?1:0},jr=s=>/[a-zA-Z]/.test(s),$r=(s,e)=>{let t=ne(s);if(!t||jr(s))return!1;if(e==="*")return!0;if(e.startsWith("~=")){let r=e.slice(2).trim(),c=ne(r);return c?r.split(".").length>=3?t.major===c.major&&t.minor===c.minor&&t.patch>=c.patch:t.major===c.major&&t.minor>=c.minor:!1}if(e.startsWith(">="))return se(s,e.slice(2).trim())>=0;if(e.startsWith(">")&&!e.startsWith(">="))return se(s,e.slice(1).trim())>0;if(e.startsWith("<="))return se(s,e.slice(2).trim())<=0;if(e.startsWith("<")&&!e.startsWith("<="))return se(s,e.slice(1).trim())<0;if(e.startsWith("!="))return se(s,e.slice(2).trim())!==0;if(e.startsWith("==")){let r=e.slice(2).trim();if(r.endsWith(".*")){let a=r.slice(0,-2);return s.startsWith(a)}let c=ne(r);return c?t.major===c.major&&t.minor===c.minor&&t.patch===c.patch:!1}let n=ne(e);return n?t.major===n.major&&t.minor===n.minor&&t.patch===n.patch:!1},wr=(s,e)=>{let t=s.filter(n=>$r(n,e)).sort(se);return t.length>0?t[t.length-1]:null},kr=s=>{if(s.versions.length===0)return null;let e=s.versions[0],t=e.source.includes("#devDependencies");return{current:e.resolved,specifier:e.specifier,isDevDependency:t}},Yt=async(s,e={})=>{let t=e.cache??!0,n=[],c=s.filter(a=>a.versions.some(l=>l.source.includes("#dependencies")||l.source.includes("#devDependencies"))).map(async a=>{let l=kr(a);if(!l)return;let i=await zt(a.name,!t);if(!i)return;let o=wr(i.versions,l.specifier),p=i.latest,u=o&&o!==l.current,m=p&&p!==l.current;(u||m)&&n.push({...a,wanted:o||l.current,latest:p,specifier:l.specifier,isDevDependency:l.isDevDependency})});return await Promise.all(c),n}});var xr,Xe,et,Ie,Zt,Te,tt,Qt=h(()=>{"use strict";xr=s=>{let e=s.trim();return e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e},Xe=s=>{let e=s.trim();return e==="true"?!0:e==="false"?!1:/^-?\d+$/.test(e)?Number.parseInt(e,10):/^-?\d+\.\d+$/.test(e)?Number.parseFloat(e):xr(e)},et=s=>{let e={},t=s.slice(1,-1).trim();if(!t)return e;let n=[],r="",c=0,a=!1,l="";for(let i=0;i<t.length;i++){let o=t[i];if(!a&&(o==='"'||o==="'")?(a=!0,l=o):a&&o===l&&t[i-1]!=="\\"&&(a=!1),!a){if(o==="{"||o==="[")c++;else if(o==="}"||o==="]")c--;else if(o===","&&c===0){n.push(r.trim()),r="";continue}}r+=o}r.trim()&&n.push(r.trim());for(let i of n){let o=i.indexOf("=");if(o===-1)continue;let p=i.slice(0,o).trim(),u=i.slice(o+1).trim();u.startsWith("{")?e[p]=et(u):u.startsWith("[")?e[p]=Ie(u):e[p]=Xe(u)}return e},Ie=s=>{let e=[],t=s.slice(1,-1).trim();if(!t)return e;let n=[],r="",c=0,a=!1,l="";for(let i=0;i<t.length;i++){let o=t[i];if(!a&&(o==='"'||o==="'")?(a=!0,l=o):a&&o===l&&t[i-1]!=="\\"&&(a=!1),!a){if(o==="{"||o==="[")c++;else if(o==="}"||o==="]")c--;else if(o===","&&c===0){n.push(r.trim()),r="";continue}}r+=o}r.trim()&&n.push(r.trim());for(let i of n){let o=i.trim();o.startsWith("{")?e.push(et(o)):o.startsWith("[")?e.push(Ie(o)):e.push(Xe(o))}return e},Zt=(s,e,t)=>{let n=s;for(let r=0;r<e.length-1;r++){let c=e[r];(!(c in n)||typeof n[c]!="object")&&(n[c]={}),n=n[c]}n[e[e.length-1]]=t},Te=(s,e)=>{let t=s;for(let n of e)(!(n in t)||typeof t[n]!="object")&&(t[n]={}),t=t[n];return t},tt=s=>{let e={},t=s.split(`
5
- `),n=[],r=null,c=null,a=null,l=null;for(let i=0;i<t.length;i++){let o=t[i];if(a!==null&&l!==null){if(a+=o,o.includes("]")){let f=0,y=-1;for(let v=0;v<a.length;v++)if(a[v]==="[")f++;else if(a[v]==="]"&&(f--,f===0)){y=v;break}if(y!==-1){let v=a.slice(0,y+1),D=Ie(v);if(c)c[l]=D;else{let S=[...n,l];Zt(e,S,D)}a=null,l=null}}continue}let p=o.indexOf("#");if(p!==-1){let f=!1,y="";for(let v=0;v<p;v++){let D=o[v];!f&&(D==='"'||D==="'")?(f=!0,y=D):f&&D===y&&o[v-1]!=="\\"&&(f=!1)}f||(o=o.slice(0,p))}if(o=o.trim(),!o)continue;if(o.startsWith("[[")&&o.endsWith("]]")){if(c&&r){let f=Te(e,r.slice(0,-1)),y=r[r.length-1];Array.isArray(f[y])||(f[y]=[]),f[y].push(c)}r=o.slice(2,-2).split("."),c={},n=[];continue}if(o.startsWith("[")&&o.endsWith("]")){if(c&&r){let f=Te(e,r.slice(0,-1)),y=r[r.length-1];Array.isArray(f[y])||(f[y]=[]),f[y].push(c),c=null,r=null}n=o.slice(1,-1).split("."),Te(e,n);continue}let u=o.indexOf("=");if(u===-1)continue;let m=o.slice(0,u).trim(),d=o.slice(u+1).trim();if(d.startsWith("[")&&!d.endsWith("]")){a=d,l=m;continue}let g;if(d.startsWith("{")?g=et(d):d.startsWith("[")?g=Ie(d):g=Xe(d),c)c[m]=g;else{let f=[...n,m];Zt(e,f,g)}}if(c&&r){let i=Te(e,r.slice(0,-1)),o=r[r.length-1];Array.isArray(i[o])||(i[o]=[]),i[o].push(c)}return e}});var re,ye,st,Cr,Or,Xt,es=h(()=>{"use strict";re=require("fs");Qt();ye=s=>s.toLowerCase().replace(/_/g,"-"),st=s=>{let e=s.match(/^([a-zA-Z0-9_-]+(?:\[[^\]]+\])?)(.*)$/);if(e){let t=e[1].replace(/\[.*\]$/,""),n=e[2].trim()||"*";return{name:t,specifier:n}}return{name:s,specifier:"*"}},Cr=s=>{let e=[];try{let t=tt(s);if(t.project?.dependencies)for(let n of t.project.dependencies){let{name:r,specifier:c}=st(n);e.push({name:r,specifier:c,group:"dependencies"})}if(t.tool?.uv?.["dev-dependencies"])for(let n of t.tool.uv["dev-dependencies"]){let{name:r,specifier:c}=st(n);e.push({name:r,specifier:c,group:"devDependencies"})}if(t.project?.["optional-dependencies"])for(let n of Object.values(t.project["optional-dependencies"]))for(let r of n){let{name:c,specifier:a}=st(r);e.push({name:c,specifier:a,group:"devDependencies"})}}catch{}return e},Or=s=>{let e={},t=null;try{let n=tt(s);if(n.package)for(let r of n.package){let c=ye(r.name);r.source?.virtual&&(t=c);let a=r.dependencies?.map(l=>ye(l.name))||[];e[c]={name:r.name,version:r.version,dependencies:a}}}catch{}return{packages:e,projectName:t}},Xt=async s=>{let e=`${s.path}/pyproject.toml`,t=`${s.path}/uv.lock`;if(!(0,re.existsSync)(e))return[];let n=new Map,r=new Set,c=(i,o,p,u,m,d)=>{let g=n.get(i);g?g.versions.push({resolved:u,specifier:d,source:m}):n.set(i,{id:i,name:o,ecosystem:p,versions:[{resolved:u,specifier:d,source:m}]})};n.set("pypi:uv",{id:"pypi:uv",name:"uv",ecosystem:"system",versions:[]});let a=(0,re.readFileSync)(e,"utf-8"),l=Cr(a);for(let i of l)r.add(ye(i.name));if((0,re.existsSync)(t)){let i=(0,re.readFileSync)(t,"utf-8"),o=Or(i);for(let p of l){let u=ye(p.name),m=o.packages[u];m&&c(`pypi:${u}`,m.name,"pypi",m.version,`.#${p.group}`,p.specifier)}for(let[p,u]of Object.entries(o.packages))if(!(p===o.projectName||r.has(p))){for(let[,m]of Object.entries(o.packages))if(m.dependencies.includes(p)){let d=`uv.lock:${m.name}@${m.version}`;c(`pypi:${p}`,u.name,"pypi",u.version,d,"*")}}}else for(let i of l){let o=ye(i.name);c(`pypi:${o}`,i.name,"pypi",i.specifier,`.#${i.group}`,i.specifier)}return Array.from(n.values()).sort((i,o)=>i.name.localeCompare(o.name))}});var ss,ts,ns,rs,os=h(()=>{"use strict";ss=F(require("fs"),1);B();Kt();es();ts=new Map,ns=R({name:"uv",actions:async s=>{let e=ss.default.readdirSync(s.path),t=e.includes("pyproject.toml");return e.includes("uv.lock")||t?{install:["uv sync"]}:{}},dependencies:async s=>{let e=s.rootFiles.includes("pyproject.toml"),t=s.rootFiles.includes("uv.lock");if(!e&&!t)return[];let n=ts.get(s.path);if(n)return n;let r=await Xt(s);return ts.set(s.path,r),r},outdatedDependencies:async(s,e)=>{if(!s.rootFiles.includes("pyproject.toml"))return[];let n=await ns.dependencies?.(s);return n?Yt(n,e):[]}}),rs=ns});var Rr,is,cs=h(()=>{"use strict";Rr=s=>{let e=s.split(`
2
+ "use strict";var gr=Object.create;var Ke=Object.defineProperty;var fr=Object.getOwnPropertyDescriptor;var hr=Object.getOwnPropertyNames;var vr=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty;var h=(s,e)=>()=>(s&&(e=s(s=0)),e);var x=(s,e)=>{for(var t in e)Ke(s,t,{get:e[t],enumerable:!0})},br=(s,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of hr(e))!yr.call(s,r)&&r!==t&&Ke(s,r,{get:()=>e[r],enumerable:!(n=fr(e,r))||n.enumerable});return s};var L=(s,e,t)=>(t=s!=null?gr(vr(s)):{},br(e||!s||!s.__esModule?Ke(t,"default",{value:s,enumerable:!0}):t,s));var w,Sr,Ze,Ie,Qe=h(()=>{"use strict";w=require("zod"),Sr=["build","check-types","dev","install","lint","outdated","test"],Ze=w.z.object({codeRootDir:w.z.string().optional().default("~/src").describe("The base directory where projects are stored"),quickActions:w.z.array(w.z.string()).default(Sr).optional().describe("Quick actions that are available for all projects")}),Ie=w.z.object({name:w.z.string().describe("Unique identifier for the project"),actions:w.z.record(w.z.string().describe("Name of the action"),w.z.object({command:w.z.string().describe("Shell command to run for the action")})).optional().describe("Actions that can be run against the project"),quickActions:w.z.array(w.z.string()).optional().describe("Actions that are available on the CLI root for quick access"),services:w.z.record(w.z.string(),w.z.object({cwd:w.z.string().optional().describe("Working directory for the service (relative to project root)"),command:w.z.string().describe("Shell command to execute"),http:w.z.object({port:w.z.number().optional().describe("Port number the service listens on"),domain:w.z.string().optional().describe("Domain to use for the service URL"),secure:w.z.boolean().optional().describe("Use HTTPS instead of HTTP")}).strict().optional().describe("HTTP configuration for the service URL"),envFile:w.z.string().optional().describe("Path to .env file (relative to project root)"),env:w.z.record(w.z.string(),w.z.string()).optional().describe("Environment variables"),keepAlive:w.z.boolean().optional().describe("Restart service if it exits"),startOnBoot:w.z.boolean().optional().describe("Start service automatically when system boots")}).strict()).optional().describe("Service that can be managed for this project")}).strict()});var is,jr,be,Xe=h(()=>{"use strict";is=require("fs"),jr=require("fs/promises"),be=s=>{try{return(0,is.readFileSync)(s,"utf8").trim()||null}catch(e){if(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")return null;throw e}}});var Z,et,Ae,Dr,cs,J,as,Se=h(()=>{"use strict";Z=require("path"),et=require("yaml");Qe();Xe();Ae=(0,Z.resolve)(process.env.DENVIG_GLOBAL_CONFIG_PATH||`${process.env.HOME}/.denvig/config.yml`),Dr=(0,Z.resolve)(process.env.DENVIG_CODE_ROOT_DIR||`${process.env.HOME}/src`),cs={codeRootDir:Dr,quickActions:void 0},J=()=>{let s=be(Ae);if(s){let e=(0,et.parse)(s)||{};try{if(e.codeRootDir?.startsWith(".")){let t=(0,Z.dirname)(Ae);e.codeRootDir=(0,Z.resolve)(`${t}/${e.codeRootDir}`)}return{...Ze.parse({...cs,...e}),$sources:[Ae]}}catch(t){console.error(`Error parsing global config at ${Ae}:`,t),process.exit(1)}}return{...Ze.parse(cs),$sources:[]}},as=s=>{let e=J(),t={name:s,actions:{}},n=`${e.codeRootDir}/${s}/.denvig.yml`,r=be(n);if(r)try{return{...t,...Ie.parse((0,et.parse)(r)),$sources:[n]}}catch{}return{...t,$sources:[]}}});var Fe,tt=h(()=>{"use strict";Fe=(s,e)=>{for(let[t,n]of Object.entries(e))s[t]||(s[t]=[]),s[t].push(...n);return s}});var st,z,je=h(()=>{"use strict";st=L(require("fs"),1),z=s=>{let e=`${s.path}/package.json`;if(!st.default.existsSync(e))return null;let t=st.default.readFileSync(e,"utf-8");return JSON.parse(t)}});var I,Y=h(()=>{"use strict";I=s=>s});var q,Pr,ls,ps=h(()=>{"use strict";q=L(require("fs"),1);tt();je();Y();Pr=I({name:"deno",actions:async s=>{let e=q.default.readdirSync(s.path);if(!(e.includes("deno.json")||e.includes("deno.jsonc")))return{};let r=z(s)?.scripts||{},i={...Object.entries(r).map(([a,o])=>[a,`deno ${o}`]).reduce((a,[o,p])=>(a[o]=[p],a),{}),install:["deno install"],outdated:["deno outdated"]},c=((0,q.existsSync)(`${s.path}/deno.json`)?JSON.parse((0,q.readFileSync)(`${s.path}/deno.json`,"utf8")):(0,q.existsSync)(`${s.path}/deno.jsonc`)?JSON.parse((0,q.readFileSync)(`${s.path}/deno.jsonc`,"utf8")):{}).tasks||{};return i=Fe(i,{test:[c?.test?"deno task test":"deno test"],lint:[c?.lint?"deno task lint":"deno lint"],"check-types":[c?.checkTypes?"deno task check-types":"deno check"],...Object.entries(c).reduce((a,[o,p])=>(a[o]=[p.startsWith("deno")?p:`deno task ${o}`],a),{}),install:["deno install"],outdated:["deno outdated"]}),i}}),ls=Pr});var ms,wr,ds,us=h(()=>{"use strict";ms=L(require("fs"),1);je();Y();wr=I({name:"npm",actions:async s=>{let e=ms.default.readdirSync(s.path),t=e.includes("package.json"),n=e.includes("package-lock.json");if(!(t&&n))return{};let l=z(s)?.scripts||{};return{...Object.entries(l).map(([a,o])=>[a,`npm run ${a}`]).reduce((a,[o,p])=>(a[o]=[p],a),{}),install:["npm install"],outdated:["npm outdated"]}}}),ds=wr});var _,gs,$r,Cr,kr,fs,xr,Or,Rr,hs,vs=h(()=>{"use strict";_=require("fs"),gs=require("os"),$r=1800*1e3,Cr=()=>{let s=`${(0,gs.homedir)()}/.cache/denvig/dependencies/npm`;return(0,_.existsSync)(s)||(0,_.mkdirSync)(s,{recursive:!0}),s},kr=s=>{let e=s.replace(/@/g,"_at_").replace(/\//g,"__");return e=e.replace(/[^a-zA-Z0-9\-_.]/g,"_"),e=e.replace(/\.{2,}/g,"_"),e=e.replace(/^\.+/,"_"),e.length===0&&(e="_empty_"),e.length>200&&(e=e.slice(0,200)),e},fs=s=>{let e=kr(s);return`${Cr()}/${e}.json`},xr=s=>{try{let e=(0,_.statSync)(s);return Date.now()-e.mtimeMs<$r}catch{return!1}},Or=s=>{let e=fs(s);if(!(0,_.existsSync)(e)||!xr(e))return null;try{let t=(0,_.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},Rr=(s,e)=>{try{let t=fs(s);(0,_.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},hs=async(s,e=!1)=>{if(!e){let t=Or(s);if(t)return t}try{let t=await fetch(`https://registry.npmjs.com/${encodeURIComponent(s)}`,{headers:{Accept:"application/json"}});if(!t.ok)return null;let n=await t.json(),r=Object.keys(n.versions),i=n["dist-tags"]?.latest||r[r.length-1],l={versions:r,latest:i};return Rr(s,l),l}catch{return null}}});var Q,_e,Nr,Lr,Tr,Ee,nt=h(()=>{"use strict";vs();Q=s=>{let e=s.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);return e?{major:Number.parseInt(e[1],10),minor:Number.parseInt(e[2],10),patch:Number.parseInt(e[3],10),prerelease:e[4]||""}:null},_e=(s,e)=>{let t=Q(s),n=Q(e);return!t||!n?0:t.major!==n.major?t.major-n.major:t.minor!==n.minor?t.minor-n.minor:t.patch!==n.patch?t.patch-n.patch:t.prerelease&&!n.prerelease?-1:!t.prerelease&&n.prerelease?1:0},Nr=(s,e)=>{let t=Q(s);if(!t||t.prerelease)return!1;if(e.startsWith("^")){let r=Q(e.slice(1));return r?r.major===0?t.major===0&&t.minor===r.minor&&t.patch>=r.patch:t.major===r.major&&_e(s,e.slice(1))>=0:!1}if(e.startsWith("~")){let r=Q(e.slice(1));return r?t.major===r.major&&t.minor===r.minor&&t.patch>=r.patch:!1}if(e.startsWith(">="))return _e(s,e.slice(2))>=0;if(e.startsWith(">")&&!e.startsWith(">="))return _e(s,e.slice(1))>0;let n=Q(e);return n?t.major===n.major&&t.minor===n.minor&&t.patch===n.patch:!1},Lr=(s,e)=>{let t=s.filter(n=>Nr(n,e)).sort(_e);return t.length>0?t[t.length-1]:null},Tr=s=>{if(s.versions.length===0)return null;let e=s.versions[0],t=e.source.includes("#devDependencies");return{current:e.resolved,specifier:e.specifier,isDevDependency:t}},Ee=async(s,e={})=>{let t=e.cache??!0,n=[],i=s.filter(l=>l.versions.some(c=>c.source.includes("#dependencies")||c.source.includes("#devDependencies"))).map(async l=>{let c=Tr(l);if(!c)return;let a=await hs(l.name,!t);if(!a)return;let o=Lr(a.versions,c.specifier),p=a.latest,m=o&&o!==c.current,u=p&&p!==c.current;(m||u)&&n.push({...l,wanted:o||c.current,latest:p,specifier:c.specifier,isDevDependency:c.isDevDependency})});return await Promise.all(i),n}});var De,bs,ys,rt,Ss,js,Ds=h(()=>{"use strict";De=require("fs"),bs=require("yaml");nt();je();Y();ys=new Map,rt=s=>{let e=s.indexOf("(");return e===-1?s:s.slice(0,e)},Ss=I({name:"pnpm",actions:async s=>{if(!s.rootFiles.includes("pnpm-lock.yaml"))return{};let r=z(s)?.scripts||{},i=s.rootFiles.includes("pnpm-workspace.yaml");return{...Object.entries(r).map(([c,a])=>[c,`pnpm run ${c}`]).reduce((c,[a,o])=>(c[a]=[o],c),{}),install:["pnpm install"],outdated:[i?"pnpm outdated -r":"pnpm outdated"]}},dependencies:async s=>{if(!(0,De.existsSync)(`${s.path}/pnpm-lock.yaml`))return[];let e=ys.get(s.path);if(e)return e;let t=new Map,n=new Set,r=(o,p,m,u,d,g)=>{let f=t.get(o);f?f.versions.push({resolved:u,specifier:g,source:d}):t.set(o,{id:o,name:p,ecosystem:m,versions:[{resolved:u,specifier:g,source:d}]})};t.set("npm:pnpm",{id:"npm:pnpm",name:"pnpm",ecosystem:"system",versions:[]});let i=`${s.path}/pnpm-lock.yaml`,l=(0,De.readFileSync)(i,"utf-8"),c=(0,bs.parse)(l);if(c?.importers)for(let[o,p]of Object.entries(c.importers)){let m=o==="."?".":o;if(p.dependencies)for(let[u,d]of Object.entries(p.dependencies))d?.specifier&&d?.version&&(n.add(u),r(`npm:${u}`,u,"npm",rt(d.version),`${m}#dependencies`,d.specifier));if(p.devDependencies)for(let[u,d]of Object.entries(p.devDependencies))d?.specifier&&d?.version&&(n.add(u),r(`npm:${u}`,u,"npm",rt(d.version),`${m}#devDependencies`,d.specifier))}if(c?.snapshots)for(let[o,p]of Object.entries(c.snapshots)){let m={...p.dependencies};for(let[u,d]of Object.entries(m))if(!n.has(u)){let g=rt(d),f=`pnpm-lock.yaml:${o}`;r(`npm:${u}`,u,"npm",g,f,g)}}let a=Array.from(t.values()).sort((o,p)=>o.name.localeCompare(p.name));return ys.set(s.path,a),a},outdatedDependencies:async(s,e)=>{if(!(0,De.existsSync)(`${s.path}/pnpm-lock.yaml`))return[];let t=await Ss.dependencies?.(s);return t?Ee(t,e):[]}}),js=Ss});var E,Ps,Ir,Ar,Fr,ws,_r,Er,Mr,$s,Cs=h(()=>{"use strict";E=require("fs"),Ps=require("os"),Ir=1800*1e3,Ar=()=>{let s=`${(0,Ps.homedir)()}/.cache/denvig/dependencies/rubygems`;return(0,E.existsSync)(s)||(0,E.mkdirSync)(s,{recursive:!0}),s},Fr=s=>{let e=s.replace(/[^a-zA-Z0-9\-_.]/g,"_");return e=e.replace(/\.{2,}/g,"_"),e=e.replace(/^\.+/,"_"),e.length===0&&(e="_empty_"),e.length>200&&(e=e.slice(0,200)),e},ws=s=>{let e=Fr(s);return`${Ar()}/${e}.json`},_r=s=>{try{let e=(0,E.statSync)(s);return Date.now()-e.mtimeMs<Ir}catch{return!1}},Er=s=>{let e=ws(s);if(!(0,E.existsSync)(e)||!_r(e))return null;try{let t=(0,E.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},Mr=(s,e)=>{try{let t=ws(s);(0,E.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},$s=async(s,e=!1)=>{if(!e){let t=Er(s);if(t)return t}try{let t=await fetch(`https://rubygems.org/api/v1/versions/${encodeURIComponent(s)}.json`,{headers:{Accept:"application/json"}});if(!t.ok)return null;let n=await t.json(),r=n.map(a=>a.number),l=n.filter(a=>!a.prerelease).map(a=>a.number)[0]||r[0],c={versions:r,latest:l};return Mr(s,c),c}catch{return null}}});var ee,X,Wr,Vr,Jr,ks,xs=h(()=>{"use strict";Cs();ee=s=>{let e=s.match(/^(\d+)\.(\d+)(?:\.(\d+))?(?:-(.+)|\.(.+))?$/);return e?{major:Number.parseInt(e[1],10),minor:Number.parseInt(e[2],10),patch:e[3]?Number.parseInt(e[3],10):0,prerelease:e[4]||e[5]||""}:null},X=(s,e)=>{let t=ee(s),n=ee(e);return!t||!n?0:t.major!==n.major?t.major-n.major:t.minor!==n.minor?t.minor-n.minor:t.patch!==n.patch?t.patch-n.patch:t.prerelease&&!n.prerelease?-1:!t.prerelease&&n.prerelease?1:0},Wr=(s,e)=>{let t=ee(s);if(!t||t.prerelease)return!1;if(e==="*")return!0;let n=e.trim();if(n.startsWith("~>")){let i=n.slice(2).trim(),l=ee(i);return l?i.split(".").length>=3?t.major===l.major&&t.minor===l.minor&&t.patch>=l.patch:t.major===l.major&&t.minor>=l.minor&&X(s,`${l.major}.${l.minor}.0`)>=0:!1}if(n.startsWith(">="))return X(s,n.slice(2).trim())>=0;if(n.startsWith(">")&&!n.startsWith(">="))return X(s,n.slice(1).trim())>0;if(n.startsWith("<="))return X(s,n.slice(2).trim())<=0;if(n.startsWith("<")&&!n.startsWith("<="))return X(s,n.slice(1).trim())<0;if(n.startsWith("=")){let i=n.slice(1).trim(),l=ee(i);return l?t.major===l.major&&t.minor===l.minor&&t.patch===l.patch:!1}let r=ee(n);return r?t.major===r.major&&t.minor===r.minor&&t.patch===r.patch:!1},Vr=(s,e)=>{let t=s.filter(n=>Wr(n,e)).sort(X);return t.length>0?t[t.length-1]:null},Jr=s=>{if(s.versions.length===0)return null;let e=s.versions[0],t=e.source.includes("#devDependencies");return{current:e.resolved,specifier:e.specifier,isDevDependency:t}},ks=async(s,e={})=>{let t=e.cache??!0,n=[],i=s.filter(l=>l.versions.some(c=>c.source.includes("#dependencies")||c.source.includes("#devDependencies"))).map(async l=>{let c=Jr(l);if(!c)return;let a=await $s(l.name,!t);if(!a)return;let o=Vr(a.versions,c.specifier),p=a.latest,m=o&&o!==c.current,u=p&&p!==c.current;(m||u)&&n.push({...l,wanted:o||c.current,latest:p,specifier:c.specifier,isDevDependency:c.isDevDependency})});return await Promise.all(i),n}});var te,Gr,zr,Os,Rs=h(()=>{"use strict";te=require("fs"),Gr=s=>{let e=[],t=s.split(`
3
+ `),n="dependencies",r=0;for(let i of t){let l=i.trim();if(l.startsWith("#")||l==="")continue;if(l.startsWith("group ")){(l.includes(":development")||l.includes(":test"))&&(n="devDependencies"),l.includes(" do")&&r++;continue}if(l==="end"){r--,r<=0&&(n="dependencies",r=0);continue}let c=l.match(/^gem\s+['"]([^'"]+)['"](?:\s*,\s*['"]([^'"]+)['"])?/);if(c){let a=c[1],o=c[2]||"*";e.push({name:a,specifier:o,group:n})}}return e},zr=s=>{let e={},t={},n=s.split(`
4
+ `),r="none",i=null,l=null;for(let c of n){let a=c.trimEnd();if(a==="GEM"){r="gem";continue}if(a==="PLATFORMS"){r="platforms";continue}if(a==="DEPENDENCIES"){r="dependencies";continue}if(a==="BUNDLED WITH"){r="none";continue}if(r==="gem"&&a===" specs:"){r="specs";continue}if(r==="specs"){if(a==="")continue;let o=c.match(/^(\s*)/),p=o?o[1].length:0,m=c.trim();if(p===4){let u=m.match(/^([^\s(]+)\s+\(([^)]+)\)/);if(u){let d=u[2],g=d.match(/^[\d.]+/),f=g?g[0]:d;i=u[1],l=f,e[i]||(e[i]={version:f,dependencies:{}})}}else if(p===6&&i&&l){let u=m.match(/^([^\s(]+)(?:\s+\(([^)]+)\))?/);if(u){let d=u[1],g=u[2]||"*";e[i].dependencies[d]=g}}}if(r==="dependencies"){if(a===""||a.startsWith(" ")===!1)continue;let o=a.match(/^\s+([^\s(!]+)(?:\s+\(([^)]+)\))?/);if(o){let m=o[1].replace(/!$/,""),u=o[2]||"*";t[m]=u}}}return{specs:e,dependencies:t}},Os=async s=>{let e=`${s.path}/Gemfile`,t=`${s.path}/Gemfile.lock`;if(!(0,te.existsSync)(e))return[];let n=new Map,r=new Set,i=(0,te.readFileSync)(e,"utf-8"),l=Gr(i),c=(a,o,p,m,u,d)=>{let g=n.get(a);g?g.versions.push({resolved:m,specifier:d,source:u}):n.set(a,{id:a,name:o,ecosystem:p,versions:[{resolved:m,specifier:d,source:u}]})};n.set("rubygems:bundler",{id:"rubygems:bundler",name:"bundler",ecosystem:"system",versions:[]});for(let a of l)r.add(a.name);if((0,te.existsSync)(t)){let a=(0,te.readFileSync)(t,"utf-8"),o=zr(a);for(let p of l){let m=o.specs[p.name];m&&c(`rubygems:${p.name}`,p.name,"rubygems",m.version,`.#${p.group}`,p.specifier)}for(let[p,m]of Object.entries(o.specs))if(!r.has(p)){for(let[u,d]of Object.entries(o.specs))if(d.dependencies[p]){let g=`Gemfile.lock:${u}@${d.version}`,f=d.dependencies[p];c(`rubygems:${p}`,p,"rubygems",m.version,g,f)}}}else for(let a of l)c(`rubygems:${a.name}`,a.name,"rubygems",a.specifier,`.#${a.group}`,a.specifier);return Array.from(n.values()).sort((a,o)=>a.name.localeCompare(o.name))}});var ot,Ns,Ls,Ts,Is=h(()=>{"use strict";ot=L(require("fs"),1);Y();xs();Rs();Ns=new Map,Ls=I({name:"ruby",actions:async s=>{let e=ot.default.readdirSync(s.path),t=e.includes("Gemfile"),n=e.includes("Rakefile"),r=e.includes("config.ru"),i=ot.default.existsSync(`${s.path}/config/application.rb`);if(!(t||n))return{};let c={install:["bundle install"],update:["bundle update"],outdated:["bundle outdated"]};return i&&(c.dev=["bundle exec rails server"],c.repl=["bundle exec rails console"]),r&&!i&&(c.dev=["bundle exec rackup"]),c},dependencies:async s=>{if(!s.rootFiles.includes("Gemfile"))return[];let t=Ns.get(s.path);if(t)return t;let n=await Os(s);return Ns.set(s.path,n),n},outdatedDependencies:async(s,e)=>{if(!s.rootFiles.includes("Gemfile"))return[];let n=await Ls.dependencies?.(s);return n?ks(n,e):[]}}),Ts=Ls});var M,As,qr,Ur,Hr,Fs,Br,Yr,Kr,_s,Es=h(()=>{"use strict";M=require("fs"),As=require("os"),qr=1800*1e3,Ur=()=>{let s=`${(0,As.homedir)()}/.cache/denvig/dependencies/pypi`;return(0,M.existsSync)(s)||(0,M.mkdirSync)(s,{recursive:!0}),s},Hr=s=>{let e=s.toLowerCase().replace(/[-_.]+/g,"-");return e=e.replace(/[^a-zA-Z0-9-]/g,"_"),e=e.replace(/\.{2,}/g,"_"),e=e.replace(/^\.+/,"_"),e.length===0&&(e="_empty_"),e.length>200&&(e=e.slice(0,200)),e},Fs=s=>{let e=Hr(s);return`${Ur()}/${e}.json`},Br=s=>{try{let e=(0,M.statSync)(s);return Date.now()-e.mtimeMs<qr}catch{return!1}},Yr=s=>{let e=Fs(s);if(!(0,M.existsSync)(e)||!Br(e))return null;try{let t=(0,M.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},Kr=(s,e)=>{try{let t=Fs(s);(0,M.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},_s=async(s,e=!1)=>{let t=s.toLowerCase().replace(/_/g,"-");if(!e){let n=Yr(t);if(n)return n}try{let n=await fetch(`https://pypi.org/pypi/${encodeURIComponent(t)}/json`,{headers:{Accept:"application/json"}});if(!n.ok)return null;let r=await n.json(),i=Object.entries(r.releases).filter(([,a])=>a.length>0).map(([a])=>a),l=r.info?.version||i[i.length-1],c={versions:i,latest:l};return Kr(t,c),c}catch{return null}}});var ne,se,Zr,Qr,Xr,eo,Ms,Ws=h(()=>{"use strict";Es();ne=s=>{let e=s.match(/^(\d+)\.(\d+)(?:\.(\d+))?(?:\.(\d+))?(.*)$/);return e?{major:Number.parseInt(e[1],10),minor:Number.parseInt(e[2],10),patch:e[3]?Number.parseInt(e[3],10):0,prerelease:e[5]||""}:null},se=(s,e)=>{let t=ne(s),n=ne(e);return!t||!n?0:t.major!==n.major?t.major-n.major:t.minor!==n.minor?t.minor-n.minor:t.patch!==n.patch?t.patch-n.patch:t.prerelease&&!n.prerelease?-1:!t.prerelease&&n.prerelease?1:0},Zr=s=>/[a-zA-Z]/.test(s),Qr=(s,e)=>{let t=ne(s);if(!t||Zr(s))return!1;if(e==="*")return!0;if(e.startsWith("~=")){let r=e.slice(2).trim(),i=ne(r);return i?r.split(".").length>=3?t.major===i.major&&t.minor===i.minor&&t.patch>=i.patch:t.major===i.major&&t.minor>=i.minor:!1}if(e.startsWith(">="))return se(s,e.slice(2).trim())>=0;if(e.startsWith(">")&&!e.startsWith(">="))return se(s,e.slice(1).trim())>0;if(e.startsWith("<="))return se(s,e.slice(2).trim())<=0;if(e.startsWith("<")&&!e.startsWith("<="))return se(s,e.slice(1).trim())<0;if(e.startsWith("!="))return se(s,e.slice(2).trim())!==0;if(e.startsWith("==")){let r=e.slice(2).trim();if(r.endsWith(".*")){let l=r.slice(0,-2);return s.startsWith(l)}let i=ne(r);return i?t.major===i.major&&t.minor===i.minor&&t.patch===i.patch:!1}let n=ne(e);return n?t.major===n.major&&t.minor===n.minor&&t.patch===n.patch:!1},Xr=(s,e)=>{let t=s.filter(n=>Qr(n,e)).sort(se);return t.length>0?t[t.length-1]:null},eo=s=>{if(s.versions.length===0)return null;let e=s.versions[0],t=e.source.includes("#devDependencies");return{current:e.resolved,specifier:e.specifier,isDevDependency:t}},Ms=async(s,e={})=>{let t=e.cache??!0,n=[],i=s.filter(l=>l.versions.some(c=>c.source.includes("#dependencies")||c.source.includes("#devDependencies"))).map(async l=>{let c=eo(l);if(!c)return;let a=await _s(l.name,!t);if(!a)return;let o=Xr(a.versions,c.specifier),p=a.latest,m=o&&o!==c.current,u=p&&p!==c.current;(m||u)&&n.push({...l,wanted:o||c.current,latest:p,specifier:c.specifier,isDevDependency:c.isDevDependency})});return await Promise.all(i),n}});var to,it,ct,We,Vs,Me,at,Js=h(()=>{"use strict";to=s=>{let e=s.trim();return e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e},it=s=>{let e=s.trim();return e==="true"?!0:e==="false"?!1:/^-?\d+$/.test(e)?Number.parseInt(e,10):/^-?\d+\.\d+$/.test(e)?Number.parseFloat(e):to(e)},ct=s=>{let e={},t=s.slice(1,-1).trim();if(!t)return e;let n=[],r="",i=0,l=!1,c="";for(let a=0;a<t.length;a++){let o=t[a];if(!l&&(o==='"'||o==="'")?(l=!0,c=o):l&&o===c&&t[a-1]!=="\\"&&(l=!1),!l){if(o==="{"||o==="[")i++;else if(o==="}"||o==="]")i--;else if(o===","&&i===0){n.push(r.trim()),r="";continue}}r+=o}r.trim()&&n.push(r.trim());for(let a of n){let o=a.indexOf("=");if(o===-1)continue;let p=a.slice(0,o).trim(),m=a.slice(o+1).trim();m.startsWith("{")?e[p]=ct(m):m.startsWith("[")?e[p]=We(m):e[p]=it(m)}return e},We=s=>{let e=[],t=s.slice(1,-1).trim();if(!t)return e;let n=[],r="",i=0,l=!1,c="";for(let a=0;a<t.length;a++){let o=t[a];if(!l&&(o==='"'||o==="'")?(l=!0,c=o):l&&o===c&&t[a-1]!=="\\"&&(l=!1),!l){if(o==="{"||o==="[")i++;else if(o==="}"||o==="]")i--;else if(o===","&&i===0){n.push(r.trim()),r="";continue}}r+=o}r.trim()&&n.push(r.trim());for(let a of n){let o=a.trim();o.startsWith("{")?e.push(ct(o)):o.startsWith("[")?e.push(We(o)):e.push(it(o))}return e},Vs=(s,e,t)=>{let n=s;for(let r=0;r<e.length-1;r++){let i=e[r];(!(i in n)||typeof n[i]!="object")&&(n[i]={}),n=n[i]}n[e[e.length-1]]=t},Me=(s,e)=>{let t=s;for(let n of e)(!(n in t)||typeof t[n]!="object")&&(t[n]={}),t=t[n];return t},at=s=>{let e={},t=s.split(`
5
+ `),n=[],r=null,i=null,l=null,c=null;for(let a=0;a<t.length;a++){let o=t[a];if(l!==null&&c!==null){if(l+=o,o.includes("]")){let f=0,v=-1;for(let y=0;y<l.length;y++)if(l[y]==="[")f++;else if(l[y]==="]"&&(f--,f===0)){v=y;break}if(v!==-1){let y=l.slice(0,v+1),j=We(y);if(i)i[c]=j;else{let D=[...n,c];Vs(e,D,j)}l=null,c=null}}continue}let p=o.indexOf("#");if(p!==-1){let f=!1,v="";for(let y=0;y<p;y++){let j=o[y];!f&&(j==='"'||j==="'")?(f=!0,v=j):f&&j===v&&o[y-1]!=="\\"&&(f=!1)}f||(o=o.slice(0,p))}if(o=o.trim(),!o)continue;if(o.startsWith("[[")&&o.endsWith("]]")){if(i&&r){let f=Me(e,r.slice(0,-1)),v=r[r.length-1];Array.isArray(f[v])||(f[v]=[]),f[v].push(i)}r=o.slice(2,-2).split("."),i={},n=[];continue}if(o.startsWith("[")&&o.endsWith("]")){if(i&&r){let f=Me(e,r.slice(0,-1)),v=r[r.length-1];Array.isArray(f[v])||(f[v]=[]),f[v].push(i),i=null,r=null}n=o.slice(1,-1).split("."),Me(e,n);continue}let m=o.indexOf("=");if(m===-1)continue;let u=o.slice(0,m).trim(),d=o.slice(m+1).trim();if(d.startsWith("[")&&!d.endsWith("]")){l=d,c=u;continue}let g;if(d.startsWith("{")?g=ct(d):d.startsWith("[")?g=We(d):g=it(d),i)i[u]=g;else{let f=[...n,u];Vs(e,f,g)}}if(i&&r){let a=Me(e,r.slice(0,-1)),o=r[r.length-1];Array.isArray(a[o])||(a[o]=[]),a[o].push(i)}return e}});var re,Pe,lt,so,no,Gs,zs=h(()=>{"use strict";re=require("fs");Js();Pe=s=>s.toLowerCase().replace(/_/g,"-"),lt=s=>{let e=s.match(/^([a-zA-Z0-9_-]+(?:\[[^\]]+\])?)(.*)$/);if(e){let t=e[1].replace(/\[.*\]$/,""),n=e[2].trim()||"*";return{name:t,specifier:n}}return{name:s,specifier:"*"}},so=s=>{let e=[];try{let t=at(s);if(t.project?.dependencies)for(let n of t.project.dependencies){let{name:r,specifier:i}=lt(n);e.push({name:r,specifier:i,group:"dependencies"})}if(t.tool?.uv?.["dev-dependencies"])for(let n of t.tool.uv["dev-dependencies"]){let{name:r,specifier:i}=lt(n);e.push({name:r,specifier:i,group:"devDependencies"})}if(t.project?.["optional-dependencies"])for(let n of Object.values(t.project["optional-dependencies"]))for(let r of n){let{name:i,specifier:l}=lt(r);e.push({name:i,specifier:l,group:"devDependencies"})}}catch{}return e},no=s=>{let e={},t=null;try{let n=at(s);if(n.package)for(let r of n.package){let i=Pe(r.name);r.source?.virtual&&(t=i);let l=r.dependencies?.map(c=>Pe(c.name))||[];e[i]={name:r.name,version:r.version,dependencies:l}}}catch{}return{packages:e,projectName:t}},Gs=async s=>{let e=`${s.path}/pyproject.toml`,t=`${s.path}/uv.lock`;if(!(0,re.existsSync)(e))return[];let n=new Map,r=new Set,i=(a,o,p,m,u,d)=>{let g=n.get(a);g?g.versions.push({resolved:m,specifier:d,source:u}):n.set(a,{id:a,name:o,ecosystem:p,versions:[{resolved:m,specifier:d,source:u}]})};n.set("pypi:uv",{id:"pypi:uv",name:"uv",ecosystem:"system",versions:[]});let l=(0,re.readFileSync)(e,"utf-8"),c=so(l);for(let a of c)r.add(Pe(a.name));if((0,re.existsSync)(t)){let a=(0,re.readFileSync)(t,"utf-8"),o=no(a);for(let p of c){let m=Pe(p.name),u=o.packages[m];u&&i(`pypi:${m}`,u.name,"pypi",u.version,`.#${p.group}`,p.specifier)}for(let[p,m]of Object.entries(o.packages))if(!(p===o.projectName||r.has(p))){for(let[,u]of Object.entries(o.packages))if(u.dependencies.includes(p)){let d=`uv.lock:${u.name}@${u.version}`;i(`pypi:${p}`,m.name,"pypi",m.version,d,"*")}}}else for(let a of c){let o=Pe(a.name);i(`pypi:${o}`,a.name,"pypi",a.specifier,`.#${a.group}`,a.specifier)}return Array.from(n.values()).sort((a,o)=>a.name.localeCompare(o.name))}});var Us,qs,Hs,Bs,Ys=h(()=>{"use strict";Us=L(require("fs"),1);Y();Ws();zs();qs=new Map,Hs=I({name:"uv",actions:async s=>{let e=Us.default.readdirSync(s.path),t=e.includes("pyproject.toml");return e.includes("uv.lock")||t?{install:["uv sync"]}:{}},dependencies:async s=>{let e=s.rootFiles.includes("pyproject.toml"),t=s.rootFiles.includes("uv.lock");if(!e&&!t)return[];let n=qs.get(s.path);if(n)return n;let r=await Gs(s);return qs.set(s.path,r),r},outdatedDependencies:async(s,e)=>{if(!s.rootFiles.includes("pyproject.toml"))return[];let n=await Hs.dependencies?.(s);return n?Ms(n,e):[]}}),Bs=Hs});var ro,Ks,Zs=h(()=>{"use strict";ro=s=>{let e=s.split(`
6
6
 
7
7
  `),t={};for(let n of e){let r=n.split(`
8
- `);if(r.length<3)continue;let c=r[0].split(",").map(p=>p.trim().replace(/"|:/g,"")),a=r[1]?.match(/version "(.+)"/)?.[1],l=r[2]?.match(/resolved "(.+)"/)?.[1];if(!a||!l)continue;let i={},o=!1;for(let p=3;p<r.length;p++){let u=r[p];if(u.trim()==="dependencies:"){o=!0;continue}if(o&&u.startsWith(" ")){let m=u.trim().match(/^"?([^"\s]+)"?\s+"?([^"]+)"?$/);m&&(i[m[1]]=m[2])}else o&&!u.startsWith(" ")&&(o=!1)}for(let p of c)p&&(t[p]={version:a,resolved:l,dependencies:Object.keys(i).length>0?i:void 0})}return{type:"success",object:t}},is=s=>{let e={},t=Rr(s),n=new Map;for(let[r,c]of Object.entries(t.object)){let a=/^(@?.+)@(.+)$/,[,l,i]=r.match(a)||[];l&&(n.has(l)||n.set(l,[]),n.get(l)?.push({version:c.version,specifier:i,deps:c.dependencies}))}for(let[r,c]of n.entries()){e[r]||(e[r]={versions:{}});for(let a of c)e[r].versions[a.version]||(e[r].versions[a.version]={}),e[r].versions[a.version]["yarn.lock"]=a.specifier;e[r].versions=Object.fromEntries(Object.entries(e[r].versions).sort((a,l)=>a[0].localeCompare(l[0],void 0,{numeric:!0})))}for(let[r,c]of n.entries())for(let a of c){if(!a.deps)continue;let l=`${r}@${a.version}`;for(let[i,o]of Object.entries(a.deps)){e[i]||(e[i]={versions:{}});let p=n.get(i);if(!p)continue;let m=p.find(d=>d.specifier===o)?.version||p[0]?.version;if(m){e[i].versions[m]||(e[i].versions[m]={});let d=`yarn.lock:${l}`;e[i].versions[m][d]=o}}}return{dependencies:e}}});function Nr(s){return s.includes("__metadata:")}function Lr(s){let e=s.match(/^(.+)@npm:/);if(e)return e[1];let t=s.lastIndexOf("@");return t>0?s.slice(0,t):s}var Y,ls,as,ps,ds,us=h(()=>{"use strict";Y=require("fs"),ls=require("yaml");Ke();fe();cs();B();as=new Map;ps=R({name:"yarn",actions:async s=>{let e=s.rootFiles.includes("package.json"),t=s.rootFiles.includes("yarn.lock");if(!(e&&t))return{};let c=_(s)?.scripts||{};return{...Object.entries(c).map(([l,i])=>[l,`yarn run ${l}`]).reduce((l,[i,o])=>(l[i]=[o],l),{}),install:["yarn install"],outdated:["yarn outdated"]}},dependencies:async s=>{let e=`${s.path}/yarn.lock`,t=`${s.path}/package.json`;if(!(0,Y.existsSync)(e)||!(0,Y.existsSync)(t))return[];let n=as.get(s.path);if(n)return n;let r=new Map,c=new Set,a=(f,y,v,D,S,k)=>{let A=r.get(f);A?A.versions.push({resolved:D,specifier:k,source:S}):r.set(f,{id:f,name:y,ecosystem:v,versions:[{resolved:D,specifier:k,source:S}]})};r.set("npm:yarn",{id:"npm:yarn",name:"yarn",ecosystem:"system",versions:[]});let l=(0,Y.readFileSync)(e,"utf-8"),i=Nr(l),o=new Map,p=new Map,u=null;if(i){let f=(0,ls.parse)(l);for(let[y,v]of Object.entries(f)){if(y==="__metadata"||!v?.version||typeof v.version!="string")continue;let D=Lr(y),S=v;o.has(D)||o.set(D,new Map);let k=y.match(/@npm:(.+)$/);k&&o.get(D)?.set(k[1],v.version),S.dependencies&&p.set(`${D}@${S.version}`,S.dependencies)}}else{u=is(l);for(let[f,y]of Object.entries(u.dependencies)){o.has(f)||o.set(f,new Map);for(let[v,D]of Object.entries(y.versions)){let S=D["yarn.lock"];S&&o.get(f)?.set(S,v)}}}let m=[t],d=s.findFilesByName("package.json");m.push(...d);for(let f of m)try{let y=(0,Y.readFileSync)(f,"utf-8"),v=JSON.parse(y),D=".";f!==t&&(D=f.replace(`${s.path}/`,"").replace("/package.json",""));let S=(k,A)=>{if(k)for(let[V,M]of Object.entries(k)){c.add(V);let K=o.get(V),pe=M;if(K){let Se=K.get(M);if(Se)pe=Se;else{let je=K.values().next().value;je&&(pe=je)}}a(`npm:${V}`,V,"npm",pe,`${D}#${A}`,M)}};S(v.dependencies,"dependencies"),S(v.devDependencies,"devDependencies")}catch{}if(i){for(let[f,y]of p.entries())for(let[v,D]of Object.entries(y))if(!c.has(v)){let S=o.get(v),k=D;if(S){let V=S.get(D);if(V)k=V;else{let M=S.values().next().value;M&&(k=M)}}let A=`yarn.lock:${f}`;a(`npm:${v}`,v,"npm",k,A,D)}}else if(u){for(let[f,y]of Object.entries(u.dependencies))if(!c.has(f))for(let[v,D]of Object.entries(y.versions))for(let[S,k]of Object.entries(D))S.startsWith("yarn.lock:")&&a(`npm:${f}`,f,"npm",v,S,k)}let g=Array.from(r.values()).sort((f,y)=>f.name.localeCompare(y.name));return as.set(s.path,g),g},outdatedDependencies:async(s,e)=>{if(!(0,Y.existsSync)(`${s.path}/yarn.lock`))return[];let t=await ps.dependencies?.(s);return t?Le(t,e):[]}}),ds=ps});var G,ve=h(()=>{"use strict";Dt();jt();Lt();qt();os();us();G={deno:bt,npm:St,pnpm:Nt,ruby:Gt,uv:rs,yarn:ds}});var ms,gs=h(()=>{"use strict";ve();Be();ms=async s=>{let e={};s.config.actions&&(e={...Object.entries(s.config.actions).reduce((t,[n,r])=>(t[n]=[r.command],t),{})});for(let[t,n]of Object.entries(G)){let r=await n.actions(s);e=Re(e,r)}return e}});var O,Tr,Ir,yi,Ar,fs,hs=h(()=>{"use strict";O=require("zod");ve();Tr=O.z.object({resolved:O.z.string().describe("The resolved version of the dependency"),specifier:O.z.string().describe("The version constraint/specifier used"),source:O.z.string().describe("The source file/path of the dependency"),wanted:O.z.string().describe("The wanted version based on semver rules").optional(),latest:O.z.string().describe("The latest available version of the dependency").optional()}),Ir=O.z.object({id:O.z.string().describe("Unique identifier for the ecosystem / dependency"),name:O.z.string().describe("Name of the dependency"),versions:O.z.array(Tr).describe("Map of resolved versions to sources. Each source maps a package path to its version specifier."),ecosystem:O.z.string().describe("Ecosystem of the dependency (e.g., npm, rubygems, pip)")}),yi=Ir.extend({wanted:O.z.string().describe("Latest version compatible with the specifier (semver)"),latest:O.z.string().describe("Absolute latest version available"),specifier:O.z.string().describe("The version specifier from package manifest"),isDevDependency:O.z.boolean().describe("Whether this is a dev dependency")}),Ar=s=>{let e=new Map;for(let t of s){let n=e.get(t.id);n?e.set(t.id,{...n,versions:[...n.versions,...t.versions]}):e.set(t.id,t)}return Array.from(e.values())},fs=async s=>{let t=(await Promise.all(Object.values(G).map(n=>n.dependencies?n.dependencies(s):Promise.resolve([])))).flat();return Ar(t)}});var nt,q,Ae=h(()=>{"use strict";nt=F(require("fs"),1);gs();ge();hs();ve();q=class{slug;config;_rootFilesCache=null;constructor(e){this.slug=e,this.config=vt(e)}get name(){return this.config.name}get path(){return`${W().codeRootDir}/${this.slug}`}get packageManagers(){let e=this.rootFiles,t=[];return e.includes("pnpm-lock.yaml")?t.push("pnpm"):e.includes("package-lock.json")?t.push("npm"):e.includes("yarn.lock")&&t.push("yarn"),(e.includes("deno.json")||e.includes("deno.jsonc"))&&t.push("deno"),e.includes("pyproject.toml")&&t.push("uv"),t}get primaryPackageManager(){return this.packageManagers[0]||null}async dependencies(){return await fs(this)}async outdatedDependencies(e){return(await Promise.all(Object.values(G).map(n=>n.outdatedDependencies?n.outdatedDependencies(this,e):Promise.resolve([])))).flat()}get actions(){return ms(this)}get rootFiles(){return this._rootFilesCache===null&&(this._rootFilesCache=nt.default.readdirSync(this.path)),this._rootFilesCache}findFilesByName(e){let t=[],n=r=>{let c=nt.default.readdirSync(r,{withFileTypes:!0});for(let a of c)a.isDirectory()?a.name!=="node_modules"&&n(`${r}/${a.name}`):a.name===e&&t.push(`${r}/${a.name}`)};return n(this.path),t}}});var vs,ys=h(()=>{vs={name:"denvig",version:"0.4.1",license:"MIT",description:"A CLI tool to consistently manage cross-discipline projects",bin:{denvig:"./dist/cli.cjs"},type:"module",main:"./dist/sdk.cjs",module:"./dist/sdk.js",types:"./dist/sdk.d.ts",exports:{".":{import:{types:"./dist/sdk.d.ts",default:"./dist/sdk.js"},require:{types:"./dist/sdk.d.ts",default:"./dist/sdk.cjs"}}},files:["dist/","LICENSE","README.md"],scripts:{build:"rm -rf dist && tsup","check-types":"tsc --noEmit",codegen:"bin/codegen",prepublishOnly:"npm run build",lint:"biome check","lint:fix":"biome check --fix",test:"node --test --test-skip-pattern='node_modules' src/**/*.test.ts","test:ci":"node --test --test-skip-pattern='node_modules' src/**/*.test.ts --reporter=default",dev:"tsc --watch"},dependencies:{minimist:"^1.2.8",semver:"^7.7.3",yaml:"^2.8.2",zod:"^4.3.5"},devDependencies:{"@biomejs/biome":"^2.3.11","@types/minimist":"^1.2.5","@types/node":"^24","@types/semver":"^7.7.1",tsup:"^8.5.1",typescript:"^5.9.3"},engines:{node:">=22"},repository:{type:"git",url:"git+https://github.com/marcqualie/denvig.git"},keywords:["cli","node","developer-tools","productivity","typescript"]}});function oe(){return vs.version}var Fe=h(()=>{"use strict";ys()});var b,x=h(()=>{"use strict";b=class{name;description;usage;example;args;flags;handler;constructor(e){this.name=e.name,this.description=e.description||"",this.usage=e.usage,this.example=e.example,this.args=e.args,this.flags=e.flags,this.handler=e.handler}async run(e,t,n,r){try{return await this.handler({project:e,args:t,flags:n,extraArgs:r})}catch(c){return console.error(`Error executing command "${this.name}":`,c),{success:!1,message:"fail"}}}}});var Ds={};C(Ds,{runCommand:()=>Er});var bs,Er,Ps=h(()=>{"use strict";bs=require("child_process");x();Fe();Er=new b({name:"run",description:"Run an action from the project. If no action is specified, lists available actions.",usage:"run [action]",example:"run build",args:[{name:"action",description:"The action to run (e.g. build, test, deploy)",required:!1,type:"string"}],flags:[],handler:async({project:s,args:e,extraArgs:t=[]})=>{let n=await s.actions;if(!e.action){console.log(`Denvig v${oe()}`),console.log(""),console.log("Usage: denvig run [action] [...actionArgs]"),console.log(""),console.log("Available actions:");for(let a in n){if(!n[a])continue;let l=n[a];for(let i of l){let o=i.split(`
9
- `),p=o[0],u=o.slice(1);console.log(` ${a}: ${p}`);for(let m of u)m.trim()&&console.log(`${" ".repeat(a.length+4)}${m}`)}}return{success:!0,message:"No action specified."}}let r=n[e.action];if(!r)return console.error(`Action "${e.action}" not found in project ${s.name}.`),{success:!1,message:`Action "${e.action}" not found.`};let c={success:!0};for(let a of r){let l=`${a} ${t.join(" ")}`.trim();console.log(`$ ${l}`);let i={...process.env,DENVIG_PROJECT:s.slug},o=process.stdout.isTTY&&process.stdin.isTTY,p,u;o?process.platform==="darwin"?(p="script",u=["-q","/dev/null","sh","-c",l]):(p="script",u=["-q","-c",l,"/dev/null"]):(p="sh",u=["-c",l]);let m=(0,bs.spawn)(p,u,{cwd:s.path,env:i,stdio:"inherit"}),d=await new Promise(g=>{m.on("close",f=>{g({success:f===0})})});d.success||(c=d)}return c}})});var Ee,Ss=h(()=>{"use strict";Ee=s=>s.replace(process.env.HOME||"/root","~")});var ws={};C(ws,{configCommand:()=>Vr});var $s,js,Vr,ks=h(()=>{"use strict";$s=require("yaml");x();ge();Ss();js=s=>{let e=Object.fromEntries(Object.entries({...s,$sources:void 0}).filter(([t,n])=>n!==void 0));(0,$s.stringify)(e,{indent:2,lineWidth:80}).trim().split(`
10
- `).map(t=>console.log(` ${Ee(t)}`))},Vr=new b({name:"config",description:"Display the current global and project configuration.",usage:"config",example:"config",args:[],flags:[],handler:({project:s})=>{let e=W(),t=s.config;return console.log("Denvig Config"),console.log(""),console.log(`Global: ${e.$sources.map(n=>Ee(n)).join(", ")||"default"}`),js(e),console.log(""),console.log(`Project: ${s.config.$sources.map(n=>Ee(n)).join(", ")||"default"}`),console.log(` slug: ${s.slug}`),js(t),{success:!0,message:"Configuration displayed."}}})});var xs={};C(xs,{pluginsCommand:()=>Wr});var Wr,Cs=h(()=>{"use strict";x();ve();Wr=new b({name:"plugins",description:"Show a list of available plugins and their actions",usage:"plugins",example:"denvig plugins",args:[],flags:[],handler:async({project:s})=>{for(let[e,t]of Object.entries(G)){let n=await t.actions(s),r=Object.keys(n);console.log(`${t.name}: ${r.length} actions`);for(let c of r)console.log(` - ${c}: ${n[c].join(" && ")}`)}return{success:!0}}})});var Os={};C(Os,{versionCommand:()=>Mr});var Mr,Rs=h(()=>{"use strict";x();Fe();Mr=new b({name:"version",description:"Show the current version of Denvig",usage:"version",example:"denvig version",args:[],flags:[],handler:()=>(console.log(`v${oe()}`),{success:!0})})});var Ns={};C(Ns,{infoCommand:()=>_r});var _r,Ls=h(()=>{"use strict";x();_r=new b({name:"info",description:"Show information about the current project",usage:"info",example:"denvig info",args:[],flags:[],handler:async({project:s})=>{let e=null;try{let r=`${s.path}/package.json`,c=await import("fs");if(c.existsSync(r)){let a=JSON.parse(c.readFileSync(r,"utf-8"));a.repository?.url&&(e=a.repository.url.replace("git+","").replace(".git",""))}}catch{}let t=await s.actions,n={name:s.name,primaryPackageManager:s.primaryPackageManager,allPackageManagers:s.packageManagers,numberOfActions:Object.keys(t).length,githubRepository:e};return console.log(`Project: ${n.name}`),console.log(`Primary Package Manager: ${n.primaryPackageManager||"None detected"}`),console.log(`All Package Managers: ${n.allPackageManagers.join(", ")||"None detected"}`),console.log(`Available Actions: ${n.numberOfActions}`),n.githubRepository&&console.log(`GitHub Repository: ${n.githubRepository}`),{success:!0}}})});var w,ie,Ts,ce,be=h(()=>{"use strict";w={reset:"\x1B[0m",white:"\x1B[37m",grey:"\x1B[90m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",bold:"\x1B[1m"},ie=s=>s.replace(/\x1b\[[0-9;]*m/g,""),Ts=s=>{if(s.depth===0)return"";let e="";for(let t=0;t<s.parentPath.length-1;t++)e+=s.parentPath[t]?" ":"\u2502 ";return s.hasChildren?e+=s.isLast?"\u2514\u2500\u252C ":"\u251C\u2500\u252C ":e+=s.isLast?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",e},ce=s=>{let{columns:e,data:t,tree:n}=s,r=e.filter(o=>o.visible!==!1);if(t.length===0||r.length===0)return[];let c=r.map((o,p)=>{let u=o.header.length,m=Math.max(...t.map(d=>{let g=o.accessor(d);if(n&&p===0){let f={depth:n.getDepth(d),isLast:n.getIsLast(d),hasChildren:n.getHasChildren(d),parentPath:n.getParentPath(d)};g=Ts(f)+ie(g)}return ie(g).length}));return Math.max(u,m)}),a=[],l=r.map((o,p)=>o.header.padEnd(c[p]));a.push(l.join(" "));let i=c.reduce((o,p)=>o+p,0)+(r.length-1)*2;a.push("-".repeat(i));for(let o of t){let u=(n?n.getDepth(o):0)>0,m=r.map((d,g)=>{let f=d.accessor(o),y=c[g];if(n&&g===0){let S={depth:n.getDepth(o),isLast:n.getIsLast(o),hasChildren:n.getHasChildren(o),parentPath:n.getParentPath(o)},k=Ts(S),A=u?`${w.grey}${ie(f)}${w.reset}`:f;f=k+A}else if(u&&!d.format){let S=ie(f);S.trim()&&(f=`${w.grey}${S}${w.reset}`)}let v=ie(f).length,D=y-v;if(d.format){let k=ie(f).padEnd(y);return d.format(k,o)}return f+" ".repeat(Math.max(0,D))});a.push(m.join(" "))}return a}});var De,Is,As=h(()=>{"use strict";De=F(require("fs"),1);ge();Is=()=>{let e=W().codeRootDir,t=[];if(!De.default.existsSync(e))return t;let n=De.default.readdirSync(e,{withFileTypes:!0});for(let r of n){if(!r.isDirectory()||r.name.startsWith("."))continue;let c=`${e}/${r.name}`,a=De.default.readdirSync(c,{withFileTypes:!0});for(let l of a){if(!l.isDirectory()||l.name.startsWith("."))continue;let o=`${`${c}/${l.name}`}/.denvig.yml`;De.default.existsSync(o)&&t.push(`${r.name}/${l.name}`)}}return t.sort()}});function Ve(){return`gui/${process.getuid?.()??501}`}async function Jr(s){try{let e=Ve(),{stdout:t,stderr:n}=await ae(`launchctl bootstrap ${e} "${s}"`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||"Unknown error"}}}async function Gr(s){try{let e=Ve(),{stdout:t,stderr:n}=await ae(`launchctl bootout ${e}/${s}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||"Unknown error"}}}async function qr(s){try{let{stdout:e,stderr:t}=await ae(`launchctl start ${s}`);return{success:!0,output:e||t}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||"Unknown error"}}}async function Ur(s){try{let{stdout:e,stderr:t}=await ae(`launchctl stop ${s}`);return{success:!0,output:e||t}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||"Unknown error"}}}async function Hr(s){try{let e=Ve(),{stdout:t}=await ae(`launchctl print ${e}/${s}`),n=t.match(/pid\s*=\s*(\d+)/),r=t.match(/state\s*=\s*(\w+)/),c=t.match(/last exit code\s*=\s*(\d+)/);return{label:s,pid:n?parseInt(n[1],10):void 0,state:r?r[1]:"unknown",status:r?r[1]:"unknown",lastExitCode:c?parseInt(c[1],10):void 0}}catch{return null}}async function zr(s){try{let{stdout:e}=await ae("launchctl list"),n=e.trim().split(`
11
- `).slice(1).map(r=>{let c=r.trim().split(/\s+/);return c.length<3?null:{pid:c[0]==="-"?"-":parseInt(c[0],10),status:parseInt(c[1],10),label:c[2]}}).filter(r=>r!==null);return s?n.filter(r=>r.label.includes(s)):n}catch{return[]}}var Fs,Es,ae,E,rt=h(()=>{"use strict";Fs=require("child_process"),Es=require("util"),ae=(0,Es.promisify)(Fs.exec);E={bootstrap:Jr,bootout:Gr,start:qr,stop:Ur,print:Hr,list:zr,getUserDomain:Ve}});function Br(s){let e={},t=s.split(`
12
- `);for(let n=0;n<t.length;n++){let r=t[n].trim();if(!r||r.startsWith("#"))continue;let c=r.indexOf("=");if(c===-1)continue;let a=r.slice(0,c).trim(),l=r.slice(c+1).trim();(l.startsWith('"')&&l.endsWith('"')||l.startsWith("'")&&l.endsWith("'"))&&(l=l.slice(1,-1)),a&&(e[a]=l)}return e}async function Ws(s){try{let e=await(0,Vs.readFile)(s,"utf-8");return Br(e)}catch(e){let t=e;throw t.code==="ENOENT"?new Error(`Environment file not found: ${s}`):new Error(`Failed to read environment file: ${t.message||"Unknown error"}`)}}var Vs,Ms=h(()=>{"use strict";Vs=require("fs/promises")});function le(s){return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function Yr(s){return`{ ${s.trim()}; } 2>&1 | while IFS= read -r line; do printf '[%s] %s\\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$line"; done`}function _s(s){let{label:e,command:t,workingDirectory:n,environmentVariables:r={},standardOutPath:c,keepAlive:a}=s,l=Yr(t),i=Object.entries(r).map(([o,p])=>` <key>${le(o)}</key>
13
- <string>${le(p)}</string>`).join(`
8
+ `);if(r.length<3)continue;let i=r[0].split(",").map(p=>p.trim().replace(/"|:/g,"")),l=r[1]?.match(/version "(.+)"/)?.[1],c=r[2]?.match(/resolved "(.+)"/)?.[1];if(!l||!c)continue;let a={},o=!1;for(let p=3;p<r.length;p++){let m=r[p];if(m.trim()==="dependencies:"){o=!0;continue}if(o&&m.startsWith(" ")){let u=m.trim().match(/^"?([^"\s]+)"?\s+"?([^"]+)"?$/);u&&(a[u[1]]=u[2])}else o&&!m.startsWith(" ")&&(o=!1)}for(let p of i)p&&(t[p]={version:l,resolved:c,dependencies:Object.keys(a).length>0?a:void 0})}return{type:"success",object:t}},Ks=s=>{let e={},t=ro(s),n=new Map;for(let[r,i]of Object.entries(t.object)){let l=/^(@?.+)@(.+)$/,[,c,a]=r.match(l)||[];c&&(n.has(c)||n.set(c,[]),n.get(c)?.push({version:i.version,specifier:a,deps:i.dependencies}))}for(let[r,i]of n.entries()){e[r]||(e[r]={versions:{}});for(let l of i)e[r].versions[l.version]||(e[r].versions[l.version]={}),e[r].versions[l.version]["yarn.lock"]=l.specifier;e[r].versions=Object.fromEntries(Object.entries(e[r].versions).sort((l,c)=>l[0].localeCompare(c[0],void 0,{numeric:!0})))}for(let[r,i]of n.entries())for(let l of i){if(!l.deps)continue;let c=`${r}@${l.version}`;for(let[a,o]of Object.entries(l.deps)){e[a]||(e[a]={versions:{}});let p=n.get(a);if(!p)continue;let u=p.find(d=>d.specifier===o)?.version||p[0]?.version;if(u){e[a].versions[u]||(e[a].versions[u]={});let d=`yarn.lock:${c}`;e[a].versions[u][d]=o}}}return{dependencies:e}}});function oo(s){return s.includes("__metadata:")}function io(s){let e=s.match(/^(.+)@npm:/);if(e)return e[1];let t=s.lastIndexOf("@");return t>0?s.slice(0,t):s}var K,Xs,Qs,en,tn,sn=h(()=>{"use strict";K=require("fs"),Xs=require("yaml");nt();je();Zs();Y();Qs=new Map;en=I({name:"yarn",actions:async s=>{let e=s.rootFiles.includes("package.json"),t=s.rootFiles.includes("yarn.lock");if(!(e&&t))return{};let i=z(s)?.scripts||{};return{...Object.entries(i).map(([c,a])=>[c,`yarn run ${c}`]).reduce((c,[a,o])=>(c[a]=[o],c),{}),install:["yarn install"],outdated:["yarn outdated"]}},dependencies:async s=>{let e=`${s.path}/yarn.lock`,t=`${s.path}/package.json`;if(!(0,K.existsSync)(e)||!(0,K.existsSync)(t))return[];let n=Qs.get(s.path);if(n)return n;let r=new Map,i=new Set,l=(f,v,y,j,D,C)=>{let F=r.get(f);F?F.versions.push({resolved:j,specifier:C,source:D}):r.set(f,{id:f,name:v,ecosystem:y,versions:[{resolved:j,specifier:C,source:D}]})};r.set("npm:yarn",{id:"npm:yarn",name:"yarn",ecosystem:"system",versions:[]});let c=(0,K.readFileSync)(e,"utf-8"),a=oo(c),o=new Map,p=new Map,m=null;if(a){let f=(0,Xs.parse)(c);for(let[v,y]of Object.entries(f)){if(v==="__metadata"||!y?.version||typeof y.version!="string")continue;let j=io(v),D=y;o.has(j)||o.set(j,new Map);let C=v.match(/@npm:(.+)$/);C&&o.get(j)?.set(C[1],y.version),D.dependencies&&p.set(`${j}@${D.version}`,D.dependencies)}}else{m=Ks(c);for(let[f,v]of Object.entries(m.dependencies)){o.has(f)||o.set(f,new Map);for(let[y,j]of Object.entries(v.versions)){let D=j["yarn.lock"];D&&o.get(f)?.set(D,y)}}}let u=[t],d=s.findFilesByName("package.json");u.push(...d);for(let f of u)try{let v=(0,K.readFileSync)(f,"utf-8"),y=JSON.parse(v),j=".";f!==t&&(j=f.replace(`${s.path}/`,"").replace("/package.json",""));let D=(C,F)=>{if(C)for(let[V,G]of Object.entries(C)){i.add(V);let ge=o.get(V),fe=G;if(ge){let Oe=ge.get(G);if(Oe)fe=Oe;else{let he=ge.values().next().value;he&&(fe=he)}}l(`npm:${V}`,V,"npm",fe,`${j}#${F}`,G)}};D(y.dependencies,"dependencies"),D(y.devDependencies,"devDependencies")}catch{}if(a){for(let[f,v]of p.entries())for(let[y,j]of Object.entries(v))if(!i.has(y)){let D=o.get(y),C=j;if(D){let V=D.get(j);if(V)C=V;else{let G=D.values().next().value;G&&(C=G)}}let F=`yarn.lock:${f}`;l(`npm:${y}`,y,"npm",C,F,j)}}else if(m){for(let[f,v]of Object.entries(m.dependencies))if(!i.has(f))for(let[y,j]of Object.entries(v.versions))for(let[D,C]of Object.entries(j))D.startsWith("yarn.lock:")&&l(`npm:${f}`,f,"npm",y,D,C)}let g=Array.from(r.values()).sort((f,v)=>f.name.localeCompare(v.name));return Qs.set(s.path,g),g},outdatedDependencies:async(s,e)=>{if(!(0,K.existsSync)(`${s.path}/yarn.lock`))return[];let t=await en.dependencies?.(s);return t?Ee(t,e):[]}}),tn=en});var U,we=h(()=>{"use strict";ps();us();Ds();Is();Ys();sn();U={deno:ls,npm:ds,pnpm:js,ruby:Ts,uv:Bs,yarn:tn}});var nn,rn=h(()=>{"use strict";we();tt();nn=async s=>{let e={};s.config.actions&&(e={...Object.entries(s.config.actions).reduce((t,[n,r])=>(t[n]=[r.command],t),{})});for(let[t,n]of Object.entries(U)){let r=await n.actions(s);e=Fe(e,r)}return e}});var R,co,ao,Zi,lo,on,cn=h(()=>{"use strict";R=require("zod");we();co=R.z.object({resolved:R.z.string().describe("The resolved version of the dependency"),specifier:R.z.string().describe("The version constraint/specifier used"),source:R.z.string().describe("The source file/path of the dependency"),wanted:R.z.string().describe("The wanted version based on semver rules").optional(),latest:R.z.string().describe("The latest available version of the dependency").optional()}),ao=R.z.object({id:R.z.string().describe("Unique identifier for the ecosystem / dependency"),name:R.z.string().describe("Name of the dependency"),versions:R.z.array(co).describe("Map of resolved versions to sources. Each source maps a package path to its version specifier."),ecosystem:R.z.string().describe("Ecosystem of the dependency (e.g., npm, rubygems, pip)")}),Zi=ao.extend({wanted:R.z.string().describe("Latest version compatible with the specifier (semver)"),latest:R.z.string().describe("Absolute latest version available"),specifier:R.z.string().describe("The version specifier from package manifest"),isDevDependency:R.z.boolean().describe("Whether this is a dev dependency")}),lo=s=>{let e=new Map;for(let t of s){let n=e.get(t.id);n?e.set(t.id,{...n,versions:[...n.versions,...t.versions]}):e.set(t.id,t)}return Array.from(e.values())},on=async s=>{let t=(await Promise.all(Object.values(U).map(n=>n.dependencies?n.dependencies(s):Promise.resolve([])))).flat();return lo(t)}});var pt,W,$e=h(()=>{"use strict";pt=L(require("fs"),1);rn();Se();cn();we();W=class{slug;config;_rootFilesCache=null;constructor(e){this.slug=e,this.config=as(e)}get name(){return this.config.name}get path(){return`${J().codeRootDir}/${this.slug}`}get packageManagers(){let e=this.rootFiles,t=[];return e.includes("pnpm-lock.yaml")?t.push("pnpm"):e.includes("package-lock.json")?t.push("npm"):e.includes("yarn.lock")&&t.push("yarn"),(e.includes("deno.json")||e.includes("deno.jsonc"))&&t.push("deno"),e.includes("pyproject.toml")&&t.push("uv"),t}get primaryPackageManager(){return this.packageManagers[0]||null}async dependencies(){return await on(this)}async outdatedDependencies(e){return(await Promise.all(Object.values(U).map(n=>n.outdatedDependencies?n.outdatedDependencies(this,e):Promise.resolve([])))).flat()}get actions(){return nn(this)}get services(){return this.config.services||{}}get rootFiles(){return this._rootFilesCache===null&&(this._rootFilesCache=pt.default.readdirSync(this.path)),this._rootFilesCache}findFilesByName(e){let t=[],n=r=>{let i=pt.default.readdirSync(r,{withFileTypes:!0});for(let l of i)l.isDirectory()?l.name!=="node_modules"&&n(`${r}/${l.name}`):l.name===e&&t.push(`${r}/${l.name}`)};return n(this.path),t}}});var ln,an=h(()=>{ln={name:"denvig",version:"0.4.3",license:"MIT",description:"A CLI tool to consistently manage cross-discipline projects",bin:{denvig:"./dist/cli.cjs"},type:"module",main:"./dist/sdk.cjs",module:"./dist/sdk.js",types:"./dist/sdk.d.ts",exports:{".":{import:{types:"./dist/sdk.d.ts",default:"./dist/sdk.js"},require:{types:"./dist/sdk.d.ts",default:"./dist/sdk.cjs"}}},files:["dist/","LICENSE","README.md"],scripts:{build:"rm -rf dist && tsup","check-types":"tsc --noEmit",codegen:"bin/codegen",prepublishOnly:"npm run build",lint:"biome check","lint:fix":"biome check --fix",test:"node --test --test-skip-pattern='node_modules' 'src/**/*.test.ts'","test:ci":"node --test --test-skip-pattern='node_modules' 'src/**/*.test.ts' --reporter=default",dev:"tsc --watch"},dependencies:{minimist:"^1.2.8",semver:"^7.7.3",yaml:"^2.8.2",zod:"^4.3.5"},devDependencies:{"@biomejs/biome":"^2.3.11","@types/minimist":"^1.2.5","@types/node":"^24","@types/semver":"^7.7.1",tsup:"^8.5.1",typescript:"^5.9.3"},engines:{node:">=22"},repository:{type:"git",url:"git+https://github.com/marcqualie/denvig.git"},keywords:["cli","node","developer-tools","productivity","typescript"]}});function oe(){return ln.version}var Ve=h(()=>{"use strict";an()});var b,k=h(()=>{"use strict";b=class{name;description;usage;example;args;flags;handler;completions;constructor(e){this.name=e.name,this.description=e.description||"",this.usage=e.usage,this.example=e.example,this.args=e.args,this.flags=e.flags,this.handler=e.handler,this.completions=e.completions}async run(e,t,n,r){try{return await this.handler({project:e,args:t,flags:n,extraArgs:r})}catch(i){return console.error(`Error executing command "${this.name}":`,i),{success:!1,message:"fail"}}}}});var mt={};x(mt,{runCommand:()=>mo});var pn,mo,dt=h(()=>{"use strict";pn=require("child_process");k();Ve();mo=new b({name:"run",description:"Run an action from the project. If no action is specified, lists available actions.",usage:"run [action]",example:"run build",args:[{name:"action",description:"The action to run (e.g. build, test, deploy)",required:!1,type:"string"}],flags:[],completions:async({project:s})=>{let e=await s.actions;return Object.keys(e)},handler:async({project:s,args:e,flags:t,extraArgs:n=[]})=>{let r=await s.actions;if(!e.action){if(t.format==="json")return console.log(JSON.stringify({actions:r})),{success:!0,message:"Actions listed."};console.log(`Denvig v${oe()}`),console.log(""),console.log("Usage: denvig run [action] [...actionArgs]"),console.log(""),console.log("Available actions:");for(let c in r){if(!r[c])continue;let a=r[c];for(let o of a){let p=o.split(`
9
+ `),m=p[0],u=p.slice(1);console.log(` ${c}: ${m}`);for(let d of u)d.trim()&&console.log(`${" ".repeat(c.length+4)}${d}`)}}return{success:!0,message:"No action specified."}}let i=r[e.action];if(!i)return console.error(`Action "${e.action}" not found in project ${s.name}.`),{success:!1,message:`Action "${e.action}" not found.`};let l={success:!0};for(let c of i){let a=`${c} ${n.join(" ")}`.trim();console.log(`$ ${a}`);let o={...process.env,DENVIG_PROJECT:s.slug},p=process.stdout.isTTY&&process.stdin.isTTY,m,u;p?process.platform==="darwin"?(m="script",u=["-q","/dev/null","sh","-c",a]):(m="script",u=["-q","-c",a,"/dev/null"]):(m="sh",u=["-c",a]);let d=(0,pn.spawn)(m,u,{cwd:s.path,env:o,stdio:"inherit"}),g=await new Promise(f=>{d.on("close",v=>{f({success:v===0})})});g.success||(l=g)}return l}})});var ie,ut=h(()=>{"use strict";ie=s=>s.replace(process.env.HOME||"/root","~")});var gt={};x(gt,{configCommand:()=>uo});var dn,mn,uo,ft=h(()=>{"use strict";dn=require("yaml");k();Se();ut();mn=s=>{let e=Object.fromEntries(Object.entries({...s,$sources:void 0}).filter(([t,n])=>n!==void 0));(0,dn.stringify)(e,{indent:2,lineWidth:80}).trim().split(`
10
+ `).map(t=>console.log(` ${ie(t)}`))},uo=new b({name:"config",description:"Display the current global and project configuration.",usage:"config",example:"config",args:[],flags:[],handler:({project:s,flags:e})=>{let t=J(),n=s.config;if(e.format==="json"){let{$sources:r,...i}=t,{$sources:l,...c}=n;return console.log(JSON.stringify({global:{sources:r,config:i},project:{slug:s.slug,sources:l,config:c}})),{success:!0,message:"Configuration displayed."}}return console.log("Denvig Config"),console.log(""),console.log(`Global: ${t.$sources.map(r=>ie(r)).join(", ")||"default"}`),mn(t),console.log(""),console.log(`Project: ${s.config.$sources.map(r=>ie(r)).join(", ")||"default"}`),console.log(` slug: ${s.slug}`),mn(n),{success:!0,message:"Configuration displayed."}}})});var ht={};x(ht,{pluginsCommand:()=>go});var go,vt=h(()=>{"use strict";k();we();go=new b({name:"plugins",description:"Show a list of available plugins and their actions",usage:"plugins",example:"denvig plugins",args:[],flags:[],handler:async({project:s,flags:e})=>{let t={};for(let[n,r]of Object.entries(U)){let i=await r.actions(s);t[n]={name:r.name,actions:i}}if(e.format==="json")return console.log(JSON.stringify(t)),{success:!0};for(let[n,r]of Object.entries(t)){let i=Object.keys(r.actions);console.log(`${r.name}: ${i.length} actions`);for(let l of i)console.log(` - ${l}: ${r.actions[l].join(" && ")}`)}return{success:!0}}})});var yt={};x(yt,{versionCommand:()=>fo});var fo,bt=h(()=>{"use strict";k();Ve();fo=new b({name:"version",description:"Show the current version of Denvig",usage:"version",example:"denvig version",args:[],flags:[],handler:({flags:s})=>{let e=oe();return s.format==="json"?console.log(JSON.stringify({version:e})):console.log(`v${e}`),{success:!0}}})});var St={};x(St,{infoCommand:()=>ho});var ho,jt=h(()=>{"use strict";k();ho=new b({name:"info",description:"Show information about the current project",usage:"info",example:"denvig info",args:[],flags:[],handler:async({project:s,flags:e})=>{let t=null;try{let i=`${s.path}/package.json`,l=await import("fs");if(l.existsSync(i)){let c=JSON.parse(l.readFileSync(i,"utf-8"));c.repository?.url&&(t=c.repository.url.replace("git+","").replace(".git",""))}}catch{}let n=await s.actions,r={name:s.name,primaryPackageManager:s.primaryPackageManager,allPackageManagers:s.packageManagers,numberOfActions:Object.keys(n).length,githubRepository:t};return e.format==="json"?(console.log(JSON.stringify(r)),{success:!0}):(console.log(`Project: ${r.name}`),console.log(`Primary Package Manager: ${r.primaryPackageManager||"None detected"}`),console.log(`All Package Managers: ${r.allPackageManagers.join(", ")||"None detected"}`),console.log(`Available Actions: ${r.numberOfActions}`),r.githubRepository&&console.log(`GitHub Repository: ${r.githubRepository}`),{success:!0})}})});var $,ce,un,H,ae=h(()=>{"use strict";$={reset:"\x1B[0m",white:"\x1B[37m",grey:"\x1B[90m",green:"\x1B[32m",yellow:"\x1B[33m",red:"\x1B[31m",bold:"\x1B[1m"},ce=s=>s.replace(/\x1b\[[0-9;]*m/g,""),un=s=>{if(s.depth===0)return"";let e="";for(let t=0;t<s.parentPath.length-1;t++)e+=s.parentPath[t]?" ":"\u2502 ";return s.hasChildren?e+=s.isLast?"\u2514\u2500\u252C ":"\u251C\u2500\u252C ":e+=s.isLast?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",e},H=s=>{let{columns:e,data:t,tree:n}=s,r=e.filter(o=>o.visible!==!1);if(t.length===0||r.length===0)return[];let i=r.map((o,p)=>{let m=o.header.length,u=Math.max(...t.map(d=>{let g=o.accessor(d);if(n&&p===0){let f={depth:n.getDepth(d),isLast:n.getIsLast(d),hasChildren:n.getHasChildren(d),parentPath:n.getParentPath(d)};g=un(f)+ce(g)}return ce(g).length}));return Math.max(m,u)}),l=[],c=r.map((o,p)=>o.header.padEnd(i[p]));l.push(c.join(" "));let a=i.reduce((o,p)=>o+p,0)+(r.length-1)*2;l.push("-".repeat(a));for(let o of t){let m=(n?n.getDepth(o):0)>0,u=r.map((d,g)=>{let f=d.accessor(o),v=i[g];if(n&&g===0){let D={depth:n.getDepth(o),isLast:n.getIsLast(o),hasChildren:n.getHasChildren(o),parentPath:n.getParentPath(o)},C=un(D),F=m?`${$.grey}${ce(f)}${$.reset}`:f;f=C+F}else if(m&&!d.format){let D=ce(f);D.trim()&&(f=`${$.grey}${D}${$.reset}`)}let y=ce(f).length,j=v-y;if(d.format){let C=ce(f).padEnd(v);return d.format(C,o)}return f+" ".repeat(Math.max(0,j))});l.push(u.join(" "))}return l}});var Ce,Je,Dt=h(()=>{"use strict";Ce=L(require("fs"),1);Se();Je=s=>{let t=J().codeRootDir,n=[],r=s?.withConfig??!1;if(!Ce.default.existsSync(t))return n;let i=Ce.default.readdirSync(t,{withFileTypes:!0});for(let l of i){if(!l.isDirectory()||l.name.startsWith("."))continue;let c=`${t}/${l.name}`,a=Ce.default.readdirSync(c,{withFileTypes:!0});for(let o of a){if(!o.isDirectory()||o.name.startsWith("."))continue;let p=`${c}/${o.name}`;if(r){let m=`${p}/.denvig.yml`;if(!Ce.default.existsSync(m))continue}n.push(`${l.name}/${o.name}`)}}return n.sort()}});function Ge(){return`gui/${process.getuid?.()??501}`}async function vo(s){try{let e=Ge(),{stdout:t,stderr:n}=await le(`launchctl bootstrap ${e} "${s}"`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||"Unknown error"}}}async function yo(s){try{let e=Ge(),{stdout:t,stderr:n}=await le(`launchctl bootout ${e}/${s}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||"Unknown error"}}}async function bo(s){try{let{stdout:e,stderr:t}=await le(`launchctl start ${s}`);return{success:!0,output:e||t}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||"Unknown error"}}}async function So(s){try{let{stdout:e,stderr:t}=await le(`launchctl stop ${s}`);return{success:!0,output:e||t}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||"Unknown error"}}}async function jo(s){try{let e=Ge(),{stdout:t}=await le(`launchctl print ${e}/${s}`),n=t.match(/pid\s*=\s*(\d+)/),r=t.match(/state\s*=\s*(\w+)/),i=t.match(/last exit code\s*=\s*(\d+)/);return{label:s,pid:n?parseInt(n[1],10):void 0,state:r?r[1]:"unknown",status:r?r[1]:"unknown",lastExitCode:i?parseInt(i[1],10):void 0}}catch{return null}}async function Do(s){try{let{stdout:e}=await le("launchctl list"),n=e.trim().split(`
11
+ `).slice(1).map(r=>{let i=r.trim().split(/\s+/);return i.length<3?null:{pid:i[0]==="-"?"-":parseInt(i[0],10),status:parseInt(i[1],10),label:i[2]}}).filter(r=>r!==null);return s?n.filter(r=>r.label.includes(s)):n}catch{return[]}}var gn,fn,le,O,ke=h(()=>{"use strict";gn=require("child_process"),fn=require("util"),le=(0,fn.promisify)(gn.exec);O={bootstrap:vo,bootout:yo,start:bo,stop:So,print:jo,list:Do,getUserDomain:Ge}});function Po(s){let e={},t=s.split(`
12
+ `);for(let n=0;n<t.length;n++){let r=t[n].trim();if(!r||r.startsWith("#"))continue;let i=r.indexOf("=");if(i===-1)continue;let l=r.slice(0,i).trim(),c=r.slice(i+1).trim(),a=c.startsWith('"'),o=c.startsWith("'");if(a||o){let p=a?'"':"'",m=c.indexOf(p,1);if(m!==-1)c=c.slice(1,m);else{let u=c.indexOf("#");u!==-1&&(c=c.slice(0,u).trim())}}else{let p=c.indexOf("#");p!==-1&&(c=c.slice(0,p).trim())}l&&(e[l]=c)}return e}async function vn(s){try{let e=await(0,hn.readFile)(s,"utf-8");return Po(e)}catch(e){let t=e;throw t.code==="ENOENT"?new Error(`Environment file not found: ${s}`):new Error(`Failed to read environment file: ${t.message||"Unknown error"}`)}}var hn,yn=h(()=>{"use strict";hn=require("fs/promises")});function pe(s){return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&apos;")}function wo(s){return`{ ${s.trim()}; } 2>&1 | while IFS= read -r line; do printf '[%s] %s\\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$line"; done`}function bn(s){let{label:e,command:t,workingDirectory:n,environmentVariables:r={},standardOutPath:i,keepAlive:l,runAtLoad:c}=s,a=wo(t),o=Object.entries(r).map(([p,m])=>` <key>${pe(p)}</key>
13
+ <string>${pe(m)}</string>`).join(`
14
14
  `);return`<?xml version="1.0" encoding="UTF-8"?>
15
15
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
16
16
  <plist version="1.0">
17
17
  <dict>
18
18
  <key>Label</key>
19
- <string>${le(e)}</string>
19
+ <string>${pe(e)}</string>
20
20
 
21
21
  <key>ProgramArguments</key>
22
22
  <array>
23
23
  <string>/bin/zsh</string>
24
24
  <string>-l</string>
25
25
  <string>-c</string>
26
- <string>${le(l)}</string>
26
+ <string>${pe(a)}</string>
27
27
  </array>
28
28
 
29
29
  <key>WorkingDirectory</key>
30
- <string>${le(n)}</string>
30
+ <string>${pe(n)}</string>
31
31
 
32
32
  <key>EnvironmentVariables</key>
33
33
  <dict>
34
- ${i}
34
+ ${o}
35
35
  </dict>
36
36
 
37
37
  <key>StandardOutPath</key>
38
- <string>${le(c)}</string>
38
+ <string>${pe(i)}</string>
39
39
 
40
40
  <key>KeepAlive</key>
41
- <${a?"true":"false"}/>
41
+ <${l?"true":"false"}/>
42
42
 
43
43
  <key>RunAtLoad</key>
44
- <false/>
44
+ <${c?"true":"false"}/>
45
45
  </dict>
46
46
  </plist>
47
- `}var Js=h(()=>{"use strict"});var I,ot,U,H,We=h(()=>{"use strict";I=require("fs/promises"),ot=require("os"),U=require("path");Ms();rt();Js();H=class{project;constructor(e){this.project=e}async listServices(){let e=this.project.config.services||{};return Object.entries(e).map(([t,n])=>({name:t,cwd:n.cwd||".",command:n.command,http:n.http}))}async startService(e){let t=this.getServiceConfig(e);if(!t)return{name:e,success:!1,message:`Service "${e}" not found in configuration`};let n=this.getServiceLabel(e),r=await this.isServiceBootstrapped(e);await this.ensureDenvigDirectories();let c=this.getPlistPath(e),a=this.resolveServiceCwd(t),l={DENVIG_PROJECT:this.project.slug,DENVIG_SERVICE:e};if(t.envFile)try{let o=(0,U.resolve)(this.project.path,t.envFile),p=await Ws(o);Object.assign(l,p)}catch(o){let p=o instanceof Error?o.message:"Unknown error";return{name:e,success:!1,message:`Failed to load environment file: ${p}`}}t.env&&Object.assign(l,t.env),t.http?.port!==void 0&&(l.PORT=t.http.port.toString());let i=_s({label:n,command:t.command,workingDirectory:a,environmentVariables:l,standardOutPath:this.getLogPath(e,"stdout"),keepAlive:t.keepAlive??!0});if(await(0,I.writeFile)(c,i,"utf-8"),r){let o=await E.bootout(n);if(!o.success)return{name:e,success:!1,message:`Failed to bootout service: ${o.output}`};await new Promise(u=>setTimeout(u,1e3));let p=await E.bootstrap(c);if(!p.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${p.output}`}}else{let o=await E.bootstrap(c);if(!o.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${o.output}`}}try{let o=new Date().toISOString();await(0,I.appendFile)(this.getLogPath(e,"stdout"),`[${o}] Service Started
48
- `,"utf-8")}catch{}return{name:e,success:!0,message:"Service started successfully"}}async stopService(e){if(!this.getServiceConfig(e))return{name:e,success:!1,message:`Service "${e}" not found in configuration`};let n=this.getServiceLabel(e);if(!await this.isServiceBootstrapped(e))return{name:e,success:!1,message:`Service "${e}" is not running`};let c=await E.bootout(n);if(!c.success)return{name:e,success:!1,message:`Failed to stop service: ${c.output}`};try{let a=new Date().toISOString();await(0,I.appendFile)(this.getLogPath(e,"stdout"),`[${a}] Service Stopped
49
- `,"utf-8")}catch{}return{name:e,success:!0,message:"Service stopped successfully"}}async restartService(e){if(!this.getServiceConfig(e))return{name:e,success:!1,message:`Service "${e}" not found in configuration`};if(await this.isServiceBootstrapped(e)){let r=await this.stopService(e);if(!r.success)return r}return await this.startService(e)}async getServiceStatus(e){let t=this.getServiceConfig(e);if(!t)return null;let n=this.getServiceLabel(e),r=await E.print(n);if(!r)return{name:e,running:!1,command:t.command,cwd:this.resolveServiceCwd(t),logPath:this.getLogPath(e,"stdout")};let c=await this.getRecentLogs(e,20);return{name:e,running:r.state==="running",pid:r.pid,command:t.command,cwd:this.resolveServiceCwd(t),logs:c,logPath:this.getLogPath(e,"stdout"),lastExitCode:r.lastExitCode}}async startAll(){let e=this.project.config.services||{},t=Object.keys(e);return await Promise.all(t.map(n=>this.startService(n)))}async stopAll(){let e=this.project.config.services||{},t=Object.keys(e),r=(await Promise.all(t.map(async c=>({name:c,isBootstrapped:await this.isServiceBootstrapped(c)})))).filter(c=>c.isBootstrapped).map(c=>c.name);return await Promise.all(r.map(c=>this.stopService(c)))}async restartAll(){let e=this.project.config.services||{},t=Object.keys(e),r=(await Promise.all(t.map(async c=>({name:c,isBootstrapped:await this.isServiceBootstrapped(c)})))).filter(c=>c.isBootstrapped).map(c=>c.name);return await Promise.all(r.map(c=>this.restartService(c)))}async isServiceBootstrapped(e){let t=this.getServiceLabel(e);return await E.print(t)!==null}normalizeForLabel(e){return e.replace(/\//g,"__").replace(/:/g,"-").replace(/[^a-zA-Z0-9_.-]/g,"_")}getServiceLabel(e){let t=this.normalizeForLabel(this.project.slug),n=this.normalizeForLabel(e);return`denvig.${t}__${n}`}getDenvigHomeDir(){return(0,U.resolve)((0,ot.homedir)(),".denvig")}getPlistPath(e){let t=this.getServiceLabel(e);return(0,U.resolve)((0,ot.homedir)(),"Library","LaunchAgents",`${t}.plist`)}getLogPath(e,t){let n=this.normalizeForLabel(this.project.slug),r=this.normalizeForLabel(e),c=t==="stderr"?".error":"";return(0,U.resolve)(this.getDenvigHomeDir(),"logs",`${n}__${r}${c}.log`)}async ensureDenvigDirectories(){let e=this.getDenvigHomeDir();await(0,I.mkdir)((0,U.resolve)(e,"logs"),{recursive:!0})}async getRecentLogs(e,t){try{let n=this.getLogPath(e,"stdout");return(await(0,I.readFile)(n,"utf-8")).trim().split(`
50
- `).slice(-t)}catch{return[]}}resolveServiceCwd(e){return(0,U.resolve)(this.project.path,e.cwd||".")}getServiceConfig(e){return this.project.config.services?.[e]}getServiceUrl(e){let t=this.getServiceConfig(e);return t?t.http?.domain?`${t.http.secure?"https":"http"}://${t.http.domain}`:t.http?.port?`http://localhost:${t.http.port}`:null:null}async plistExists(e){try{return await(0,I.access)(this.getPlistPath(e)),!0}catch{return!1}}async getServiceResponse(e,t){let n=this.getServiceConfig(e);if(!n)return null;let r=this.getServiceLabel(e),c="stopped",a=null,l=null;if(t?.launchctlList){let o=t.launchctlList.find(p=>p.label===r);o&&(a=o.pid==="-"?null:o.pid,l=o.status,a!==null?c=l!==0?"error":"running":c=l!==0?"error":"stopped")}else if(await this.plistExists(e)){let p=await E.print(r);p&&(a=p.pid??null,l=p.lastExitCode??null,p.state==="running"&&(l!==null&&l!==0?c="error":c="running"))}let i={name:e,project:this.project.slug,status:c,pid:a,url:this.getServiceUrl(e),command:n.command,cwd:this.resolveServiceCwd(n),logPath:this.getLogPath(e,"stdout"),envFile:n.envFile?(0,U.resolve)(this.project.path,n.envFile):null,lastExitCode:l};return t?.includeLogs&&(i.logs=await this.getRecentLogs(e,t.logLines??20)),i}}});var Gs={};C(Gs,{servicesCommand:()=>Zr});var Kr,Zr,qs=h(()=>{"use strict";x();be();Ae();As();rt();We();Kr=s=>{switch(s){case"running":return"\u{1F7E2}";case"error":return"\u{1F534}";default:return"\u25EF"}},Zr=new b({name:"services",description:"List all services across all projects",usage:"services [--format table|json]",example:"services",args:[],flags:[{name:"format",description:"Output format: table or json (default: table)",required:!1,type:"string",defaultValue:"table"}],handler:async({project:s,flags:e})=>{let t=e.format,n=s.slug,r=Is();if(r.length===0)return console.log(t==="json"?JSON.stringify([]):"No projects found with .denvig.yml configuration."),{success:!0,message:"No projects found."};let c=await E.list("denvig."),a=[];for(let o of r){let p=new q(o),u=new H(p),m=await u.listServices();for(let d of m){let g=await u.getServiceResponse(d.name,{launchctlList:c});g&&a.push(g)}}if(a.length===0)return console.log(t==="json"?JSON.stringify([]):"No services configured across any project."),{success:!0,message:"No services configured."};let l=a.sort((o,p)=>{let u=o.project===n,m=p.project===n;if(u&&!m)return-1;if(!u&&m)return 1;let d=o.project.localeCompare(p.project);return d!==0?d:o.name.localeCompare(p.name)});if(t==="json")return console.log(JSON.stringify(l)),{success:!0,message:"Services listed successfully."};let i=ce({columns:[{header:"",accessor:o=>Kr(o.status)},{header:"Project",accessor:o=>o.project},{header:"Name",accessor:o=>o.name},{header:"URL",accessor:o=>o.url||"-"}],data:l});for(let o of i)console.log(o);return console.log(""),console.log(`${a.length} service${a.length===1?"":"s"} configured across ${r.length} project${r.length===1?"":"s"}`),{success:!0,message:"Services listed successfully."}}})});var Qr,z,Pe=h(()=>{"use strict";Ae();We();Qr=(s,e)=>{if(!s.includes("/"))return{projectSlug:e,serviceName:s};let t=s.split("/"),n=t.pop();return{projectSlug:t.join("/"),serviceName:n}},z=(s,e)=>{let{projectSlug:t,serviceName:n}=Qr(s,e.slug),r=t===e.slug?e:new q(t),c=new H(r);return{project:r,manager:c,serviceName:n}}});var Hs={};C(Hs,{servicesStartCommand:()=>Xr});var Us,Xr,zs=h(()=>{"use strict";Us=require("zod");x();Pe();Xr=new b({name:"services:start",description:"Start a service",usage:"services start <name> [--format table|json]",example:"services start api",args:[{name:"name",description:"Service name or project/service path (e.g., api or marcqualie/denvig/hello)",required:!0,type:"string"}],flags:[{name:"format",description:"Output format: table or json (default: table)",required:!1,type:"string",defaultValue:"table"}],handler:async({project:s,args:e,flags:t})=>{let n=Us.z.string().parse(e.name),r=t.format,{manager:c,serviceName:a,project:l}=z(n,s),i=l.slug!==s.slug?`${l.slug}/`:"";r!=="json"&&console.log(`Starting ${i}${a}...`);let o=await c.startService(a);if(!o.success)return r==="json"?console.log(JSON.stringify({success:!1,service:a,project:l.slug,message:o.message})):console.error(`\u2717 Failed to start ${i}${a}: ${o.message}`),{success:!1,message:o.message};await new Promise(u=>setTimeout(u,2e3));let p=await c.getServiceResponse(a,{includeLogs:!0});if(p?.status==="running"){if(r==="json")console.log(JSON.stringify(p));else{let u=p.url?` \u2192 ${p.url}`:"";console.log(`\u2713 ${i}${a} started successfully${u}`)}return{success:!0,message:"Service started successfully."}}if(r==="json")console.log(JSON.stringify(p));else if(console.error(`\u2717 ${i}${a} failed to start`),p?.logs&&p.logs.length>0){console.error(""),console.error("Recent logs:");for(let u of p.logs)console.error(` ${u}`)}return{success:!1,message:"Service failed to start."}}})});var Ys={};C(Ys,{servicesStopCommand:()=>eo});var Bs,eo,Ks=h(()=>{"use strict";Bs=require("zod");x();Pe();eo=new b({name:"services:stop",description:"Stop a service",usage:"services stop <name> [--format table|json]",example:"services stop api",args:[{name:"name",description:"Service name or project/service path (e.g., api or marcqualie/denvig/hello)",required:!0,type:"string"}],flags:[{name:"format",description:"Output format: table or json (default: table)",required:!1,type:"string",defaultValue:"table"}],handler:async({project:s,args:e,flags:t})=>{let n=Bs.z.string().parse(e.name),r=t.format,{manager:c,serviceName:a,project:l}=z(n,s),i=l.slug!==s.slug?`${l.slug}/`:"";r!=="json"&&console.log(`Stopping ${i}${a}...`);let o=await c.stopService(a);if(!o.success)return r==="json"?console.log(JSON.stringify({success:!1,service:a,project:l.slug,message:o.message})):console.error(`\u2717 Failed to stop ${i}${a}: ${o.message}`),{success:!1,message:o.message};let p=await c.getServiceResponse(a);return console.log(r==="json"?JSON.stringify(p):`\u2713 ${i}${a} stopped successfully`),{success:!0,message:"Service stopped successfully."}}})});var Qs={};C(Qs,{servicesRestartCommand:()=>to});var Zs,to,Xs=h(()=>{"use strict";Zs=require("zod");x();Pe();to=new b({name:"services:restart",description:"Restart a service",usage:"services restart <name> [--format table|json]",example:"services restart api",args:[{name:"name",description:"Service name or project/service path (e.g., api or marcqualie/denvig/hello)",required:!0,type:"string"}],flags:[{name:"format",description:"Output format: table or json (default: table)",required:!1,type:"string",defaultValue:"table"}],handler:async({project:s,args:e,flags:t})=>{let n=Zs.z.string().parse(e.name),r=t.format,{manager:c,serviceName:a,project:l}=z(n,s),i=l.slug!==s.slug?`${l.slug}/`:"";r!=="json"&&console.log(`Restarting ${i}${a}...`);let o=await c.restartService(a);if(!o.success)return r==="json"?console.log(JSON.stringify({success:!1,service:a,project:l.slug,message:o.message})):console.error(`\u2717 Failed to restart ${i}${a}: ${o.message}`),{success:!1,message:o.message};await new Promise(u=>setTimeout(u,2e3));let p=await c.getServiceResponse(a,{includeLogs:!0});if(p?.status==="running"){if(r==="json")console.log(JSON.stringify(p));else{let u=p.url?` \u2192 ${p.url}`:"";console.log(`\u2713 ${i}${a} restarted successfully${u}`)}return{success:!0,message:"Service restarted successfully."}}if(r==="json")console.log(JSON.stringify(p));else if(console.error(`\u2717 ${i}${a} failed to restart`),p?.logs&&p.logs.length>0){console.error(""),console.error("Recent logs:");for(let u of p.logs)console.error(` ${u}`)}return{success:!1,message:"Service failed to restart."}}})});var sn={};C(sn,{servicesStatusCommand:()=>so});var en,Me,tn,so,nn=h(()=>{"use strict";en=require("fs"),Me=require("os"),tn=require("zod");x();Pe();so=new b({name:"services:status",description:"Show status of a specific service",usage:"services status <name> [--format table|json]",example:"services status api or services status marcqualie/denvig/hello",args:[{name:"name",description:"Service name or project/service path (e.g., hello or marcqualie/denvig/hello)",required:!0,type:"string"}],flags:[{name:"format",description:"Output format: table or json (default: table)",required:!1,type:"string",defaultValue:"table"}],handler:async({project:s,args:e,flags:t})=>{let n=tn.z.string().parse(e.name),r=t.format,{manager:c,serviceName:a,project:l}=z(n,s),i=await c.getServiceResponse(a,{includeLogs:!0});if(!i){let m=l.slug!==s.slug?` in project "${l.slug}"`:"";return r==="json"?console.log(JSON.stringify({success:!1,service:a,project:l.slug,message:`Service "${a}" not found in configuration${m}`})):console.error(`Service "${a}" not found in configuration${m}`),{success:!1,message:`Service "${a}" not found.`}}if(r==="json")return console.log(JSON.stringify(i)),{success:!0,message:"Status retrieved successfully."};let o=l.slug!==s.slug?`${l.slug}/`:"",p=i.status==="running"?"Running":i.status==="error"?"Error":"Stopped";console.log(`Service: ${o}${i.name}`),console.log(`Status: ${p}`),i.status==="running"&&i.pid&&console.log(`PID: ${i.pid}`),console.log(`Command: ${i.command}`),console.log(`CWD: ${i.cwd.replace((0,Me.homedir)(),"~")}`),console.log(`Logs: ${i.logPath.replace((0,Me.homedir)(),"~")}`);let u=c.getPlistPath(a);if((0,en.existsSync)(u)&&console.log(`Plist: ${u.replace((0,Me.homedir)(),"~")}`),i.lastExitCode!==null&&i.lastExitCode!==0&&i.status!=="running"&&console.log(`Last exit code: ${i.lastExitCode}`),i.logs&&i.logs.length>0){console.log(""),console.log("Recent logs (last 10 lines):");for(let m of i.logs.slice(-10))console.log(` ${m}`)}return{success:!0,message:"Status retrieved successfully."}}})});var cn={};C(cn,{logsCommand:()=>no});var rn,on,no,an=h(()=>{"use strict";rn=require("child_process"),on=require("fs/promises");x();We();no=new b({name:"services:logs",description:"Show logs for a service",usage:"services logs <name> [-n <lines>] [--follow]",example:"services logs api -n 50 --follow",args:[{name:"name",description:"Name of the service",required:!0,type:"string"}],flags:[{name:"lines",description:"Number of lines to show (use -n)",required:!1,type:"number",defaultValue:10},{name:"follow",description:"Follow the log output",required:!1,type:"boolean",defaultValue:!1}],handler:async({project:s,args:e,flags:t})=>{let n=new H(s),r=e.name,c=t.lines??t.n??10,a=!!t.follow,l=n.getLogPath(r,"stdout");if(a){let i=["-n",`${c}`,"-f",l];return(0,rn.spawn)("tail",i,{stdio:"inherit"}),new Promise(()=>{})}try{let p=(await(0,on.readFile)(l,"utf-8")).trim().split(`
51
- `).filter(Boolean).slice(-c);for(let u of p)console.log(u);return{success:!0}}catch(i){return console.error(`Failed to read logs for ${r}:`,i instanceof Error?i.message:i),{success:!1,message:"failed to read logs"}}}})});var ln,it,pn,dn=h(()=>{"use strict";ln=require("crypto"),it=s=>{let{project:e,workspace:t="root",resource:n}=s;if(!n.startsWith("action/")&&!n.startsWith("service/"))throw new Error(`Invalid resource format: ${n}. Must start with "action/" or "service/".`);return`@${e.slug}|${t}|${n}`},pn=s=>{let e=it(s),t=(0,ln.createHash)("sha256").update(e).digest("hex");return{id:e,hash:t}}});var un={};C(un,{internalsResourceHashCommand:()=>ro,internalsResourceIdCommand:()=>oo});var ro,oo,mn=h(()=>{"use strict";x();dn();ro=new b({name:"internals:resource-hash",description:"Generate hash for a denvig resource",usage:"internals:resource-hash <resource>",example:"denvig internals:resource-hash service/hello",args:[{name:"resource",description:"Resource identifier (e.g., service/api, action/build, apps/web|action/dev, or full ID)",required:!0,type:"string"}],flags:[{name:"workspace",description:'Workspace path (defaults to "root")',required:!1,type:"string"}],handler:async({project:s,args:e,flags:t})=>{let n=e.resource,r=t.workspace,c=n;if(n.startsWith("@")){let l=n.match(/^@([^#]+)#([^|]+)\|(.+)$/);if(!l)return console.error("Error: Invalid full ID format. Expected: @project#workspace|resource"),{success:!1,message:"Invalid ID format"};r=l[2],c=l[3]}else if(n.includes("|")){let l=n.split("|");r=l[0],c=l[1]}if(!c.startsWith("action/")&&!c.startsWith("service/"))return console.error('Error: Resource must start with "action/" or "service/" (e.g., service/api, action/build)'),{success:!1,message:"Invalid resource format"};let a=pn({project:s,workspace:r,resource:c});return console.log(`${a.id}
52
- ${a.hash}`),{success:!0,message:"Hash generated successfully"}}}),oo=new b({name:"internals:resource-id",description:"Generate ID for a denvig resource",usage:"internals:resource-id <resource>",example:"denvig internals:id service/hello",args:[{name:"resource",description:"Resource identifier (e.g., service/api, action/build, apps/web|action/dev)",required:!0,type:"string"}],flags:[{name:"workspace",description:'Workspace path (defaults to "root")',required:!1,type:"string"}],handler:async({project:s,args:e,flags:t})=>{let n=e.resource,r=t.workspace,c=n;if(n.includes("|")){let l=n.split("|");r=l[0],c=l[1]}if(!c.startsWith("action/")&&!c.startsWith("service/"))return console.error('Error: Resource must start with "action/" or "service/" (e.g., service/api, action/build)'),{success:!1,message:"Invalid resource format"};let a=it({project:s,workspace:r,resource:c});return console.log(a),{success:!0,message:"ID generated successfully"}}})});var gn,ct,at,io,lt,fn,hn,pt=h(()=>{"use strict";gn=["pnpm-lock.yaml:","yarn.lock:","Gemfile.lock:","uv.lock:"],ct=s=>{for(let e of gn)if(s.startsWith(e)){let n=s.slice(e.length).match(/^([^@]+)@([^(@]+)/);if(n)return{name:n[1],version:n[2]}}return null},at=s=>gn.some(e=>s.startsWith(e)),io=s=>s.endsWith("#dependencies"),lt=s=>s.endsWith("#devDependencies"),fn=(s,e,t)=>{let n=new Map;for(let i of s)n.set(i.name,i);let r=[],c=new Set;for(let i of s)if(!(t&&i.ecosystem!==t)){for(let o of i.versions)if(!at(o.source)){let p=lt(o.source);if(io(o.source)||p){let m=`${i.name}@${o.resolved}`;c.has(m)||(c.add(m),r.push({dep:i,version:o.resolved,isDevDependency:p,children:[]}))}}}if(e>0){let i=new Map;for(let p of s)if(!(t&&p.ecosystem!==t))for(let u of p.versions){let m=ct(u.source);if(m){let d=`${m.name}@${m.version}`,g=i.get(d)||[];g.some(f=>f.name===p.name)||(g.push(p),i.set(d,g))}}let o=(p,u,m)=>{if(u>=e)return;let d=`${p.dep.name}@${p.version}`;if(m.has(d))return;m.add(d);let g=i.get(d)||[];for(let f of g){let y=f.versions.find(v=>{let D=ct(v.source);return D?.name===p.dep.name&&D?.version===p.version});if(y){let v={dep:f,version:y.resolved,isDevDependency:!1,children:[]};p.children.push(v),o(v,u+1,new Set(m))}}p.children.sort((f,y)=>f.dep.name.localeCompare(y.dep.name))};for(let p of r)o(p,0,new Set)}r.sort((i,o)=>{let p=i.dep.ecosystem.localeCompare(o.dep.ecosystem);return p!==0?p:i.dep.name.localeCompare(o.dep.name)});let a=[],l=(i,o,p,u)=>{a.push({name:i.dep.name,version:i.version,ecosystem:i.dep.ecosystem,isDevDependency:i.isDevDependency,depth:o,isLast:p,hasChildren:i.children.length>0,parentPath:[...u]});let m=[...u,p];i.children.forEach((d,g)=>{l(d,o+1,g===i.children.length-1,m)})};return r.forEach((i,o)=>{l(i,0,o===r.length-1,[])}),a},hn=(s,e,t,n)=>{if(!at(t))return{name:s,version:e,children:[]};let r=[{name:s,version:e}],c=t,a=50,l=0;for(;l<a;){let p=ct(c);if(!p)break;r.unshift({name:p.name,version:p.version});let u=n.get(p.name);if(!u)break;let m=u.versions.find(d=>d.resolved===p.version);if(!m||!at(m.source))break;c=m.source,l++}if(r.length===0)return null;let i={name:r[0].name,version:r[0].version,children:[]},o=i;for(let p=1;p<r.length;p++){let u={name:r[p].name,version:r[p].version,children:[]};o.children.push(u),o=u}return i}});var yn={};C(yn,{depsListCommand:()=>co});var co,vn=h(()=>{"use strict";x();pt();be();co=new b({name:"deps:list",description:"List all dependencies detected by plugins",usage:"deps:list [--depth <n>] [--ecosystem <name>] [--format table|json]",example:"denvig deps:list --depth 1",args:[],flags:[{name:"depth",description:"Show subdependencies up to N levels deep (default: 0)",required:!1,type:"number",defaultValue:0},{name:"ecosystem",description:"Filter to a specific ecosystem (e.g., npm, rubygems, pypi)",required:!1,type:"string",defaultValue:void 0},{name:"format",description:"Output format: table or json (default: table)",required:!1,type:"string",defaultValue:"table"}],handler:async({project:s,flags:e})=>{let t=e.ecosystem,n=e.depth??0,r=e.format,c=await s.dependencies();if(c.length===0)return console.log(r==="json"?JSON.stringify([]):"No dependencies detected in this project."),{success:!0,message:"No dependencies detected."};let a=fn(c,n,t);if(a.length===0){if(r==="json")console.log(JSON.stringify([]));else{let g=t?`No dependencies found for ecosystem "${t}".`:"No direct dependencies detected in this project.";console.log(g)}return{success:!0,message:t?`No dependencies found for ecosystem "${t}".`:"No direct dependencies detected in this project."}}if(r==="json")return console.log(JSON.stringify(c)),{success:!0,message:"Dependencies listed successfully."};let i=new Set(a.map(g=>g.ecosystem)).size>1&&!t,o=ce({columns:[{header:"Package",accessor:g=>g.name},{header:"",accessor:g=>g.depth===0&&g.isDevDependency?`${w.grey}(dev)${w.reset}`:" "},{header:"Current",accessor:g=>g.version},{header:"Ecosystem",accessor:g=>g.ecosystem,visible:i}],data:a,tree:{getDepth:g=>g.depth,getIsLast:g=>g.isLast,getHasChildren:g=>g.hasChildren,getParentPath:g=>g.parentPath}});for(let g of o)console.log(g);let p=a.filter(g=>g.depth===0),u=p.filter(g=>!g.isDevDependency).length,m=p.filter(g=>g.isDevDependency).length,d=c.length-p.length;return console.log(""),console.log(`${c.length} total (${u} dependencies, ${m} devDependencies, ${d} subdependencies)`),{success:!0,message:"Dependencies listed successfully."}}})});var bn,dt,Dn,Pn=h(()=>{"use strict";bn=F(require("semver"),1),dt=(s,e)=>{if(s===e)return null;try{let t=bn.default.diff(s,e);return t?t==="major"||t==="premajor"?"major":t==="minor"||t==="preminor"?"minor":t==="patch"||t==="prepatch"||t==="prerelease"?"patch":null:null}catch{return null}},Dn=(s,e)=>s===null?!1:e==="patch"?s==="patch":e==="minor"?s==="patch"||s==="minor":!1});var jn={};C(jn,{depsOutdatedCommand:()=>ao});var Sn,ao,$n=h(()=>{"use strict";x();be();Pn();Sn=(s,e)=>{if(s===e)return w.white;let t=dt(s,e);return t?t==="major"?w.red:t==="minor"?w.yellow:t==="patch"?w.green:w.white:w.white},ao=new b({name:"deps:outdated",description:"Show outdated dependencies",usage:"deps:outdated [--no-cache] [--semver patch|minor] [--ecosystem <name>] [--format table|json]",example:"denvig deps:outdated --semver patch",args:[],flags:[{name:"no-cache",description:"Skip cache and fetch fresh data from registry",required:!1,type:"boolean",defaultValue:!1},{name:"semver",description:'Filter by semver level: "patch" for patch updates only, "minor" for minor and patch updates',required:!1,type:"string",defaultValue:void 0},{name:"ecosystem",description:"Filter to a specific ecosystem (e.g., npm, rubygems, pypi)",required:!1,type:"string",defaultValue:void 0},{name:"format",description:"Output format: table or json (default: table)",required:!1,type:"string",defaultValue:"table"}],handler:async({project:s,flags:e})=>{let t=!e["no-cache"],n=e.semver,r=e.ecosystem,c=e.format;if(n&&n!=="patch"&&n!=="minor")return console.error(`Invalid --semver value: "${n}". Must be "patch" or "minor".`),{success:!1,message:"Invalid --semver value."};let l=await s.outdatedDependencies({cache:t}),i=d=>d.versions[0]?.resolved||"";if(r&&(l=l.filter(d=>d.ecosystem===r)),n&&(l=l.filter(d=>{let g=dt(i(d),d.latest);return Dn(g,n)})),l.length===0){if(c==="json")console.log(JSON.stringify([]));else{let g="All dependencies are up to date!";r&&n?g=`No ${n}-level updates available for ecosystem "${r}".`:r?g=`No outdated dependencies found for ecosystem "${r}".`:n&&(g=`No ${n}-level updates available.`),console.log(g)}let d="All dependencies are up to date!";return r&&n?d=`No ${n}-level updates available for ecosystem "${r}".`:r?d=`No outdated dependencies found for ecosystem "${r}".`:n&&(d=`No ${n}-level updates available.`),{success:!0,message:d}}let o=l.sort((d,g)=>{let f=d.ecosystem.localeCompare(g.ecosystem);return f!==0?f:d.name.localeCompare(g.name)});if(c==="json")return console.log(JSON.stringify(o)),{success:!0,message:"Outdated dependencies listed."};let u=new Set(l.map(d=>d.ecosystem)).size>1&&!r,m=ce({columns:[{header:"Package",accessor:d=>d.name},{header:"",accessor:d=>d.isDevDependency?`${w.grey}(dev)${w.reset}`:" "},{header:"Current",accessor:d=>i(d)},{header:"Wanted",accessor:d=>d.wanted,format:(d,g)=>`${Sn(i(g),g.wanted)}${d}${w.reset}`},{header:"Latest",accessor:d=>d.latest,format:(d,g)=>`${Sn(i(g),g.latest)}${d}${w.reset}`},{header:"Ecosystem",accessor:d=>d.ecosystem,visible:u}],data:o});for(let d of m)console.log(d);return{success:!0,message:"Outdated dependencies listed."}}})});var _e,Je,wn=h(()=>{"use strict";be();_e=(s,e="",t=!0,n=!0)=>{let r=[],c=s.children.length>0;if(n)r.push(`${s.name} ${w.grey}${s.version}${w.reset}`);else{let l=c?t?"\u2514\u2500\u252C ":"\u251C\u2500\u252C ":t?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ";r.push(`${e}${l}${s.name} ${w.grey}${s.version}${w.reset}`)}let a=n?"":e+(t?" ":"\u2502 ");for(let l=0;l<s.children.length;l++){let i=s.children[l],o=l===s.children.length-1;r.push(..._e(i,a,o,!1))}return r},Je=(s,e)=>{let t=s.find(n=>n.name===e.name&&n.version===e.version);if(t)for(let n of e.children)Je(t.children,n);else s.push(e)}});var kn={};C(kn,{depsWhyCommand:()=>lo});var lo,xn=h(()=>{"use strict";x();pt();wn();lo=new b({name:"deps:why",description:"Show why a dependency is installed",usage:"deps:why <dependency>",example:"denvig deps:why yaml",args:[{name:"dependency",description:"The dependency name to look up",required:!0,type:"string"}],flags:[],handler:async({project:s,args:e})=>{let t=e.dependency,n=await s.dependencies(),r=n.find(i=>i.name===t);if(!r)return console.log(`Dependency "${t}" not found in this project.`),{success:!1,message:"Dependency not found."};let c=new Map;for(let i of n)c.set(i.name,i);console.log(`${s.name} ${s.path}`),console.log("");let a=[],l=[];for(let i of r.versions){let o=hn(r.name,i.resolved,i.source,c);o&&(c.get(o.name)?.versions.some(m=>lt(m.source))?Je(l,o):Je(a,o))}if(a.length>0){console.log("dependencies:");for(let i=0;i<a.length;i++){let o=_e(a[i],"",i===a.length-1,!0);for(let p of o)console.log(p)}console.log("")}if(l.length>0){console.log("devDependencies:");for(let i=0;i<l.length;i++){let o=_e(l[i],"",i===l.length-1,!0);for(let p of o)console.log(p)}console.log("")}return a.length===0&&l.length===0&&console.log(`Could not determine dependency chain for "${t}".`),{success:!0,message:"Dependency chain shown."}}})});var Rn={};C(Rn,{configVerifyCommand:()=>po});var Cn,On,po,Nn=h(()=>{"use strict";Cn=require("path"),On=require("yaml");x();He();Ue();po=new b({name:"config:verify",description:"Verify a .denvig.yml file against the config schema.",usage:"config verify [path]",example:"config verify .denvig.yml",args:[{name:"path",description:"Path to the config file (defaults to .denvig.yml)",required:!1,type:"string",defaultValue:".denvig.yml"}],flags:[],handler:({project:s,args:e})=>{let t=(0,Cn.resolve)(s.path,e.path?.toString()||".denvig.yml"),n=me(t);if(!n)return console.error(`Config file not found: ${t}`),{success:!1,message:"Config file not found."};let r;try{r=(0,On.parse)(n)}catch(a){return console.error(`Failed to parse YAML at ${t}:`),a instanceof Error&&console.error(` ${a.message}`),{success:!1,message:"Invalid YAML syntax."}}let c=Ce.safeParse(r);if(!c.success){console.error(`Config validation failed for ${t}:`);for(let a of c.error.issues){let l=a.path.length>0?a.path.join("."):"(root)";console.error(` - ${l}: ${a.message}`)}return{success:!1,message:"Config validation failed."}}return console.log(`Config is valid: ${t}`),{success:!0,message:"Config is valid."}}})});var ut=F(require("minimist"),1);ge();Ae();Fe();var Ln=[{name:"project",description:"The project slug to run against. Defaults to current directory.",required:!1,type:"string",defaultValue:void 0}];async function uo(){let s=process.argv[2],e=process.argv.slice(2),t=W(),n=process.cwd(),r=(0,ut.default)(process.argv.slice(2)).project?.toString()||n.replace(`${t.codeRootDir}/`,"").split("/").slice(0,2).join("/"),c=new q(r),a={outdated:"deps:outdated"};a[s]&&(s=a[s]);let l=["start","stop","restart","status","logs"];if(s==="services"){let P=process.argv[3];P&&l.includes(P)&&(s=`services:${P}`,e=[process.argv[2],...process.argv.slice(4)])}let i=["list","outdated","why"];if(s==="deps"){let P=process.argv[3];P&&i.includes(P)&&(s=`deps:${P}`,e=[process.argv[2],...process.argv.slice(4)])}let o=["verify"];if(s==="config"){let P=process.argv[3];P&&o.includes(P)&&(s=`config:${P}`,e=[process.argv[2],...process.argv.slice(4)])}let p=[...t.quickActions||[],...c?.config?.quickActions||[]].sort();p.includes(s)&&(e=["run",...process.argv.slice(2)],s="run",console.log("> Proxying to denvig run",...process.argv.slice(2)));let{runCommand:u}=await Promise.resolve().then(()=>(Ps(),Ds)),{configCommand:m}=await Promise.resolve().then(()=>(ks(),ws)),{pluginsCommand:d}=await Promise.resolve().then(()=>(Cs(),xs)),{versionCommand:g}=await Promise.resolve().then(()=>(Rs(),Os)),{infoCommand:f}=await Promise.resolve().then(()=>(Ls(),Ns)),{servicesCommand:y}=await Promise.resolve().then(()=>(qs(),Gs)),{servicesStartCommand:v}=await Promise.resolve().then(()=>(zs(),Hs)),{servicesStopCommand:D}=await Promise.resolve().then(()=>(Ks(),Ys)),{servicesRestartCommand:S}=await Promise.resolve().then(()=>(Xs(),Qs)),{servicesStatusCommand:k}=await Promise.resolve().then(()=>(nn(),sn)),{logsCommand:A}=await Promise.resolve().then(()=>(an(),cn)),{internalsResourceHashCommand:V,internalsResourceIdCommand:M}=await Promise.resolve().then(()=>(mn(),un)),{depsListCommand:K}=await Promise.resolve().then(()=>(vn(),yn)),{depsOutdatedCommand:pe}=await Promise.resolve().then(()=>($n(),jn)),{depsWhyCommand:Se}=await Promise.resolve().then(()=>(xn(),kn)),{configVerifyCommand:je}=await Promise.resolve().then(()=>(Nn(),Rn)),de={run:u,config:m,"config:verify":je,plugins:d,version:g,info:f,services:y,"services:start":v,"services:stop":D,"services:restart":S,"services:status":k,"services:logs":A,deps:K,"deps:list":K,"deps:outdated":pe,"deps:why":Se,"internals:resource-hash":V,"internals:resource-id":M},$e=de[s],ue=(0,ut.default)(e),Tn=$e?.args.reduce((P,j,ke)=>{let xe=ue._[ke+1];return xe!==void 0?P[j.name]=xe:j.required&&(console.error(`Missing required argument: ${j.name}`),process.exit(1)),P},{})||{},In=ue._.slice($e?.args.length+1).map(P=>String(P))||[],mt=[...Ln,...$e?.flags||[]],An=new Set(mt.map(P=>P.name)),Fn=mt.reduce((P,j)=>(ue[j.name]!==void 0?P[j.name]=ue[j.name]:j.defaultValue!==void 0?P[j.name]=j.defaultValue:j.required&&(console.error(`Missing required flag: ${j.name}`),process.exit(1)),P),{}),we=[];for(let[P,j]of Object.entries(ue))P!=="_"&&!An.has(P)&&(j===!0?we.push(`--${P}`):j===!1?we.push(`--no-${P}`):we.push(`--${P}`,String(j)));let En=[...In,...we];if(!s){console.log(`Denvig v${oe()}`),console.log(""),console.log("Usage: denvig <command> [args] [flags]"),console.log(""),console.log("Available commands:"),Object.keys(de).forEach(j=>{j.startsWith("internals:")||console.log(` - ${de[j].usage.padEnd(20," ")} ${de[j].description}`)}),console.log(""),console.log("Quick Actions:");for(let j of p){let ke=(await c?.actions)?.[j];if(!ke){console.log(` - ${j.padEnd(20," ")} not defined`);return}for(let xe of ke){let gt=xe.split(`
53
- `),Vn=gt[0],Wn=gt.slice(1);console.log(` - ${j.padEnd(20," ")} $ ${Vn}`);for(let ft of Wn)ft.trim()&&console.log(`${" ".repeat(27)}${ft}`)}}console.log(""),console.log("Global flags:"),Ln.forEach(j=>{console.log(` --${j.name.padEnd(20," ")} ${j.description}`)}),process.exit(1)}de[s]||(console.error(`Command "${s}" not found.`),process.exit(1));try{r||console.error("No project provided or detected.");let{success:P}=await $e.run(c,Tn,Fn,En);P||process.exit(1)}catch(P){console.error(`Error executing command "${s}":`,P),process.exit(1)}}uo();
47
+ `}var Sn=h(()=>{"use strict"});var N,ze,T,A,me=h(()=>{"use strict";N=require("fs/promises"),ze=require("os"),T=require("path");yn();ke();Sn();A=class{project;constructor(e){this.project=e}async listServices(){let e=this.project.config.services||{};return Object.entries(e).map(([t,n])=>({name:t,cwd:n.cwd||".",command:n.command,http:n.http,startOnBoot:n.startOnBoot}))}async startService(e){let t=this.getServiceConfig(e);if(!t)return{name:e,success:!1,message:`Service "${e}" not found in configuration`};let n=this.getServiceLabel(e),r=await this.isServiceBootstrapped(e);await this.ensureDenvigDirectories();let i=this.getPlistPath(e),l=this.resolveServiceCwd(t),c={DENVIG_PROJECT:this.project.slug,DENVIG_SERVICE:e};if(t.envFile)try{let o=(0,T.resolve)(this.project.path,t.envFile),p=await vn(o);Object.assign(c,p)}catch(o){let p=o instanceof Error?o.message:"Unknown error";return{name:e,success:!1,message:`Failed to load environment file: ${p}`}}t.env&&Object.assign(c,t.env),t.http?.port!==void 0&&(c.PORT=t.http.port.toString());let a=bn({label:n,command:t.command,workingDirectory:l,environmentVariables:c,standardOutPath:this.getLogPath(e,"stdout"),keepAlive:t.keepAlive??!0,runAtLoad:t.startOnBoot??!1});if(await(0,N.writeFile)(i,a,"utf-8"),r){let o=await O.bootout(n);if(!o.success)return{name:e,success:!1,message:`Failed to bootout service: ${o.output}`};await new Promise(m=>setTimeout(m,1e3));let p=await O.bootstrap(i);if(!p.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${p.output}`}}else{let o=await O.bootstrap(i);if(!o.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${o.output}`}}try{let o=new Date().toISOString();await(0,N.appendFile)(this.getLogPath(e,"stdout"),`[${o}] Service Started
48
+ `,"utf-8")}catch{}return{name:e,success:!0,message:"Service started successfully"}}async stopService(e){let t=this.getServiceConfig(e);if(!t)return{name:e,success:!1,message:`Service "${e}" not found in configuration`};let n=this.getServiceLabel(e);if(!await this.isServiceBootstrapped(e))return{name:e,success:!1,message:`Service "${e}" is not running`};if(t.startOnBoot){let i=await O.stop(n);if(!i.success)return{name:e,success:!1,message:`Failed to stop service: ${i.output}`}}else{let i=await O.bootout(n);if(!i.success)return{name:e,success:!1,message:`Failed to stop service: ${i.output}`};try{await(0,N.unlink)(this.getPlistPath(e))}catch{}}try{let i=new Date().toISOString();await(0,N.appendFile)(this.getLogPath(e,"stdout"),`[${i}] Service Stopped
49
+ `,"utf-8")}catch{}return{name:e,success:!0,message:"Service stopped successfully"}}async restartService(e){if(!this.getServiceConfig(e))return{name:e,success:!1,message:`Service "${e}" not found in configuration`};if(await this.isServiceBootstrapped(e)){let r=await this.stopService(e);if(!r.success)return r}return await this.startService(e)}async getServiceStatus(e){let t=this.getServiceConfig(e);if(!t)return null;let n=this.getServiceLabel(e),r=await O.print(n);if(!r)return{name:e,running:!1,command:t.command,cwd:this.resolveServiceCwd(t),logPath:this.getLogPath(e,"stdout")};let i=await this.getRecentLogs(e,20);return{name:e,running:r.state==="running",pid:r.pid,command:t.command,cwd:this.resolveServiceCwd(t),logs:i,logPath:this.getLogPath(e,"stdout"),lastExitCode:r.lastExitCode}}async startAll(){let e=this.project.config.services||{},t=Object.keys(e);return await Promise.all(t.map(n=>this.startService(n)))}async stopAll(){let e=this.project.config.services||{},t=Object.keys(e),r=(await Promise.all(t.map(async i=>({name:i,isBootstrapped:await this.isServiceBootstrapped(i)})))).filter(i=>i.isBootstrapped).map(i=>i.name);return await Promise.all(r.map(i=>this.stopService(i)))}async restartAll(){let e=this.project.config.services||{},t=Object.keys(e),r=(await Promise.all(t.map(async i=>({name:i,isBootstrapped:await this.isServiceBootstrapped(i)})))).filter(i=>i.isBootstrapped).map(i=>i.name);return await Promise.all(r.map(i=>this.restartService(i)))}async teardownAll(e){let t=[],r=`denvig.${this.normalizeForLabel(this.project.slug)}__`,i=[],l=await O.list(r);for(let a of l){let o=await O.bootout(a.label),p=a.label.replace(r,"");o.success?(i.push(a.label),t.push({name:p,success:!0,message:"Service removed from launchctl"})):t.push({name:p,success:!1,message:`Failed to bootout: ${o.output}`})}let c=(0,T.resolve)((0,ze.homedir)(),"Library","LaunchAgents");if(await Promise.all(i.map(async a=>{try{await(0,N.unlink)((0,T.resolve)(c,`${a}.plist`))}catch{}})),e?.removeLogs&&i.length>0){let a=(0,T.resolve)(this.getDenvigHomeDir(),"logs"),o=i.map(p=>p.replace("denvig.",""));await Promise.all(o.flatMap(p=>[(0,N.unlink)((0,T.resolve)(a,`${p}.log`)).catch(()=>{}),(0,N.unlink)((0,T.resolve)(a,`${p}.error.log`)).catch(()=>{})]))}return t}async isServiceBootstrapped(e){let t=this.getServiceLabel(e);return await O.print(t)!==null}normalizeForLabel(e){return e.replace(/\//g,"__").replace(/:/g,"-").replace(/[^a-zA-Z0-9_.-]/g,"_")}getServiceLabel(e){let t=this.normalizeForLabel(this.project.slug),n=this.normalizeForLabel(e);return`denvig.${t}__${n}`}getDenvigHomeDir(){return(0,T.resolve)((0,ze.homedir)(),".denvig")}getPlistPath(e){let t=this.getServiceLabel(e);return(0,T.resolve)((0,ze.homedir)(),"Library","LaunchAgents",`${t}.plist`)}getLogPath(e,t){let n=this.normalizeForLabel(this.project.slug),r=this.normalizeForLabel(e),i=t==="stderr"?".error":"";return(0,T.resolve)(this.getDenvigHomeDir(),"logs",`${n}__${r}${i}.log`)}async ensureDenvigDirectories(){let e=this.getDenvigHomeDir();await(0,N.mkdir)((0,T.resolve)(e,"logs"),{recursive:!0})}async getRecentLogs(e,t){try{let n=this.getLogPath(e,"stdout");return(await(0,N.readFile)(n,"utf-8")).trim().split(`
50
+ `).slice(-t)}catch{return[]}}resolveServiceCwd(e){return(0,T.resolve)(this.project.path,e.cwd||".")}getServiceConfig(e){return this.project.config.services?.[e]}getServiceUrl(e){let t=this.getServiceConfig(e);return t?t.http?.domain?`${t.http.secure?"https":"http"}://${t.http.domain}`:t.http?.port?`http://localhost:${t.http.port}`:null:null}async plistExists(e){try{return await(0,N.access)(this.getPlistPath(e)),!0}catch{return!1}}async getServiceResponse(e,t){let n=this.getServiceConfig(e);if(!n)return null;let r=this.getServiceLabel(e),i="stopped",l=null,c=null;if(t?.launchctlList){let o=t.launchctlList.find(p=>p.label===r);o&&(l=o.pid==="-"?null:o.pid,c=o.status,l!==null?i=c!==0?"error":"running":i=c!==0?"error":"stopped")}else if(await this.plistExists(e)){let p=await O.print(r);p&&(l=p.pid??null,c=p.lastExitCode??null,p.state==="running"&&(c!==null&&c!==0?i="error":i="running"))}let a={name:e,project:this.project.slug,status:i,pid:l,url:this.getServiceUrl(e),command:n.command,cwd:this.resolveServiceCwd(n),logPath:this.getLogPath(e,"stdout"),envFile:n.envFile?(0,T.resolve)(this.project.path,n.envFile):null,lastExitCode:c};return t?.includeLogs&&(a.logs=await this.getRecentLogs(e,t.logLines??20)),a}}});var Pt={};x(Pt,{servicesCommand:()=>Co});var $o,Co,wt=h(()=>{"use strict";k();ae();$e();Dt();ke();me();$o=s=>{switch(s){case"running":return"\u{1F7E2}";case"error":return"\u{1F534}";default:return"\u25EF"}},Co=new b({name:"services",description:"List all services across all projects",usage:"services",example:"services",args:[],flags:[],completions:({project:s},e)=>[],handler:async({project:s,flags:e})=>{let t=e.format,n=s.slug,r=Je();if(r.length===0)return console.log(t==="json"?JSON.stringify([]):"No projects found with .denvig.yml configuration."),{success:!0,message:"No projects found."};let i=await O.list("denvig."),l=[];for(let o of r){let p=new W(o),m=new A(p),u=await m.listServices();for(let d of u){let g=await m.getServiceResponse(d.name,{launchctlList:i});g&&l.push(g)}}if(l.length===0)return console.log(t==="json"?JSON.stringify([]):"No services configured across any project."),{success:!0,message:"No services configured."};let c=l.sort((o,p)=>{let m=o.project===n,u=p.project===n;if(m&&!u)return-1;if(!m&&u)return 1;let d=o.project.localeCompare(p.project);return d!==0?d:o.name.localeCompare(p.name)});if(t==="json")return console.log(JSON.stringify(c)),{success:!0,message:"Services listed successfully."};let a=H({columns:[{header:"",accessor:o=>$o(o.status)},{header:"Project",accessor:o=>o.project},{header:"Name",accessor:o=>o.name},{header:"URL",accessor:o=>o.url||"-"}],data:c});for(let o of a)console.log(o);return console.log(""),console.log(`${l.length} service${l.length===1?"":"s"} configured across ${r.length} project${r.length===1?"":"s"}`),{success:!0,message:"Services listed successfully."}}})});var ko,B,xe=h(()=>{"use strict";$e();me();ko=(s,e)=>{if(!s.includes("/"))return{projectSlug:e,serviceName:s};let t=s.split("/"),n=t.pop();return{projectSlug:t.join("/"),serviceName:n}},B=(s,e)=>{let{projectSlug:t,serviceName:n}=ko(s,e.slug),r=t===e.slug?e:new W(t),i=new A(r);return{project:r,manager:i,serviceName:n}}});var $t={};x($t,{servicesStartCommand:()=>xo});var jn,xo,Ct=h(()=>{"use strict";jn=require("zod");k();xe();xo=new b({name:"services:start",description:"Start a service",usage:"services start <name>",example:"services start api",args:[{name:"name",description:"Service name or project/service path (e.g., api or marcqualie/denvig/hello)",required:!0,type:"string"}],flags:[],completions:({project:s},e)=>{let t=s.services;return Object.entries(t).flatMap(([n,r])=>n)},handler:async({project:s,args:e,flags:t})=>{let n=jn.z.string().parse(e.name),r=t.format,{manager:i,serviceName:l,project:c}=B(n,s),a=c.slug!==s.slug?`${c.slug}/`:"";r!=="json"&&console.log(`Starting ${a}${l}...`);let o=await i.startService(l);if(!o.success)return r==="json"?console.log(JSON.stringify({success:!1,service:l,project:c.slug,message:o.message})):console.error(`\u2717 Failed to start ${a}${l}: ${o.message}`),{success:!1,message:o.message};await new Promise(m=>setTimeout(m,2e3));let p=await i.getServiceResponse(l,{includeLogs:!0});if(p?.status==="running"){if(r==="json")console.log(JSON.stringify(p));else{let m=p.url?` \u2192 ${p.url}`:"";console.log(`\u2713 ${a}${l} started successfully${m}`)}return{success:!0,message:"Service started successfully."}}if(r==="json")console.log(JSON.stringify(p));else if(console.error(`\u2717 ${a}${l} failed to start`),p?.logs&&p.logs.length>0){console.error(""),console.error("Recent logs:");for(let m of p.logs)console.error(` ${m}`)}return{success:!1,message:"Service failed to start."}}})});var kt={};x(kt,{servicesStopCommand:()=>Oo});var Dn,Oo,xt=h(()=>{"use strict";Dn=require("zod");k();xe();Oo=new b({name:"services:stop",description:"Stop a service",usage:"services stop <name>",example:"services stop api",args:[{name:"name",description:"Service name or project/service path (e.g., api or marcqualie/denvig/hello)",required:!0,type:"string"}],flags:[],completions:({project:s})=>Object.keys(s.services),handler:async({project:s,args:e,flags:t})=>{let n=Dn.z.string().parse(e.name),r=t.format,{manager:i,serviceName:l,project:c}=B(n,s),a=c.slug!==s.slug?`${c.slug}/`:"";r!=="json"&&console.log(`Stopping ${a}${l}...`);let o=await i.stopService(l);if(!o.success)return r==="json"?console.log(JSON.stringify({success:!1,service:l,project:c.slug,message:o.message})):console.error(`\u2717 Failed to stop ${a}${l}: ${o.message}`),{success:!1,message:o.message};let p=await i.getServiceResponse(l);return console.log(r==="json"?JSON.stringify(p):`\u2713 ${a}${l} stopped successfully`),{success:!0,message:"Service stopped successfully."}}})});var Ot={};x(Ot,{servicesRestartCommand:()=>Ro});var Pn,Ro,Rt=h(()=>{"use strict";Pn=require("zod");k();xe();Ro=new b({name:"services:restart",description:"Restart a service",usage:"services restart <name>",example:"services restart api",args:[{name:"name",description:"Service name or project/service path (e.g., api or marcqualie/denvig/hello)",required:!0,type:"string"}],flags:[],completions:({project:s})=>Object.keys(s.services),handler:async({project:s,args:e,flags:t})=>{let n=Pn.z.string().parse(e.name),r=t.format,{manager:i,serviceName:l,project:c}=B(n,s),a=c.slug!==s.slug?`${c.slug}/`:"";r!=="json"&&console.log(`Restarting ${a}${l}...`);let o=await i.restartService(l);if(!o.success)return r==="json"?console.log(JSON.stringify({success:!1,service:l,project:c.slug,message:o.message})):console.error(`\u2717 Failed to restart ${a}${l}: ${o.message}`),{success:!1,message:o.message};await new Promise(m=>setTimeout(m,2e3));let p=await i.getServiceResponse(l,{includeLogs:!0});if(p?.status==="running"){if(r==="json")console.log(JSON.stringify(p));else{let m=p.url?` \u2192 ${p.url}`:"";console.log(`\u2713 ${a}${l} restarted successfully${m}`)}return{success:!0,message:"Service restarted successfully."}}if(r==="json")console.log(JSON.stringify(p));else if(console.error(`\u2717 ${a}${l} failed to restart`),p?.logs&&p.logs.length>0){console.error(""),console.error("Recent logs:");for(let m of p.logs)console.error(` ${m}`)}return{success:!1,message:"Service failed to restart."}}})});var Nt={};x(Nt,{servicesStatusCommand:()=>No});var wn,qe,$n,No,Lt=h(()=>{"use strict";wn=require("fs"),qe=require("os"),$n=require("zod");k();xe();No=new b({name:"services:status",description:"Show status of a specific service",usage:"services status <name>",example:"services status api or services status marcqualie/denvig/hello",args:[{name:"name",description:"Service name or project/service path (e.g., hello or marcqualie/denvig/hello)",required:!0,type:"string"}],flags:[],completions:({project:s})=>Object.keys(s.services),handler:async({project:s,args:e,flags:t})=>{let n=$n.z.string().parse(e.name),r=t.format,{manager:i,serviceName:l,project:c}=B(n,s),a=await i.getServiceResponse(l,{includeLogs:!0});if(!a){let u=c.slug!==s.slug?` in project "${c.slug}"`:"";return r==="json"?console.log(JSON.stringify({success:!1,service:l,project:c.slug,message:`Service "${l}" not found in configuration${u}`})):console.error(`Service "${l}" not found in configuration${u}`),{success:!1,message:`Service "${l}" not found.`}}if(r==="json")return console.log(JSON.stringify(a)),{success:!0,message:"Status retrieved successfully."};let o=c.slug!==s.slug?`${c.slug}/`:"",p=a.status==="running"?"Running":a.status==="error"?"Error":"Stopped";console.log(`Service: ${o}${a.name}`),console.log(`Status: ${p}`),a.status==="running"&&a.pid&&console.log(`PID: ${a.pid}`),console.log(`Command: ${a.command}`),console.log(`CWD: ${a.cwd.replace((0,qe.homedir)(),"~")}`),console.log(`Logs: ${a.logPath.replace((0,qe.homedir)(),"~")}`);let m=i.getPlistPath(l);if((0,wn.existsSync)(m)&&console.log(`Plist: ${m.replace((0,qe.homedir)(),"~")}`),a.lastExitCode!==null&&a.lastExitCode!==0&&a.status!=="running"&&console.log(`Last exit code: ${a.lastExitCode}`),a.logs&&a.logs.length>0){console.log(""),console.log("Recent logs (last 10 lines):");for(let u of a.logs.slice(-10))console.log(` ${u}`)}return{success:!0,message:"Status retrieved successfully."}}})});var Tt={};x(Tt,{logsCommand:()=>Lo});var Cn,kn,Lo,It=h(()=>{"use strict";Cn=require("child_process"),kn=require("fs/promises");k();me();Lo=new b({name:"services:logs",description:"Show logs for a service",usage:"services logs <name> [-n <lines>] [--follow]",example:"services logs api -n 50 --follow",args:[{name:"name",description:"Name of the service",required:!0,type:"string"}],flags:[{name:"lines",description:"Number of lines to show (use -n)",required:!1,type:"number",defaultValue:10},{name:"follow",description:"Follow the log output",required:!1,type:"boolean",defaultValue:!1}],completions:({project:s})=>Object.keys(s.services),handler:async({project:s,args:e,flags:t})=>{let n=new A(s),r=e.name,i=t.format,l=t.lines??t.n??10,c=!!t.follow,a=n.getLogPath(r,"stdout");if(c){if(i==="json")return console.log(JSON.stringify({success:!1,error:"JSON format is not supported with --follow"})),{success:!1,message:"JSON format not supported with follow"};let o=["-n",`${l}`,"-f",a];return(0,Cn.spawn)("tail",o,{stdio:"inherit"}),new Promise(()=>{})}try{let m=(await(0,kn.readFile)(a,"utf-8")).trim().split(`
51
+ `).filter(Boolean).slice(-l);if(i==="json")return console.log(JSON.stringify({service:r,logPath:a,lines:m})),{success:!0};for(let u of m)console.log(u);return{success:!0}}catch(o){let p=o instanceof Error?o.message:String(o);return i==="json"?console.log(JSON.stringify({success:!1,service:r,error:p})):console.error(`Failed to read logs for ${r}:`,p),{success:!1,message:"failed to read logs"}}}})});var Ft={};x(Ft,{servicesTeardownCommand:()=>Io});async function To(s){let e=[],t=[],n=await O.list("denvig.");for(let i of n){let l=await O.bootout(i.label);l.success?(t.push(i.label),e.push({name:i.label,success:!0,message:"Service removed from launchctl"})):e.push({name:i.label,success:!1,message:`Failed to bootout: ${l.output}`})}let r=(0,de.resolve)((0,At.homedir)(),"Library","LaunchAgents");if(await Promise.all(t.map(async i=>{try{await(0,Ue.unlink)((0,de.resolve)(r,`${i}.plist`))}catch{}})),s?.removeLogs&&t.length>0){let i=(0,de.resolve)((0,At.homedir)(),".denvig","logs"),l=t.map(c=>c.replace("denvig.",""));await Promise.all(l.flatMap(c=>[(0,Ue.unlink)((0,de.resolve)(i,`${c}.log`)).catch(()=>{}),(0,Ue.unlink)((0,de.resolve)(i,`${c}.error.log`)).catch(()=>{})]))}return{success:!0,services:e,logsRemoved:s?.removeLogs??!1}}var Ue,At,de,Io,_t=h(()=>{"use strict";Ue=require("fs/promises"),At=require("os"),de=require("path");k();ke();me();Io=new b({name:"services:teardown",description:"Stop all services and remove them from launchctl",usage:"services teardown [--global] [--remove-logs]",example:"services teardown",args:[],flags:[{name:"global",description:"Teardown all denvig services across all projects",required:!1,type:"boolean",defaultValue:!1},{name:"remove-logs",description:"Also remove log files",required:!1,type:"boolean",defaultValue:!1}],handler:async({project:s,flags:e})=>{let t=e.format,n=e["remove-logs"];if(e.global){t!=="json"&&console.log("Tearing down all denvig services globally...");let c=await To({removeLogs:n});if(t==="json")console.log(JSON.stringify(c));else if(c.services.length===0)console.log("No services found to teardown.");else{for(let a of c.services)a.success?console.log(`\u2713 ${a.name} removed`):console.log(`\u2717 ${a.name}: ${a.message}`);console.log(""),console.log(`Teardown complete. ${c.services.filter(a=>a.success).length}/${c.services.length} services removed.`),n&&console.log("Log files have been removed.")}return{success:!0,message:"Global teardown complete"}}let i=new A(s);t!=="json"&&console.log(`Tearing down all services for ${s.slug}...`);let l=await i.teardownAll({removeLogs:n});if(t==="json")console.log(JSON.stringify({success:!0,project:s.slug,services:l,logsRemoved:n}));else if(l.length===0)console.log("No services found to teardown.");else{for(let c of l)c.success?console.log(`\u2713 ${c.name} removed`):console.log(`\u2717 ${c.name}: ${c.message}`);console.log(""),console.log(`Teardown complete. ${l.filter(c=>c.success).length}/${l.length} services removed.`),n&&console.log("Log files have been removed.")}return{success:!0,message:"Teardown complete"}}})});var xn,Et,On,Rn=h(()=>{"use strict";xn=require("crypto"),Et=s=>{let{project:e,workspace:t="root",resource:n}=s;if(!n.startsWith("action/")&&!n.startsWith("service/"))throw new Error(`Invalid resource format: ${n}. Must start with "action/" or "service/".`);return`@${e.slug}|${t}|${n}`},On=s=>{let e=Et(s),t=(0,xn.createHash)("sha256").update(e).digest("hex");return{id:e,hash:t}}});var Nn={};x(Nn,{internalsResourceHashCommand:()=>Ao,internalsResourceIdCommand:()=>Fo});var Ao,Fo,Ln=h(()=>{"use strict";k();Rn();Ao=new b({name:"internals:resource-hash",description:"Generate hash for a denvig resource",usage:"internals:resource-hash <resource>",example:"denvig internals:resource-hash service/hello",args:[{name:"resource",description:"Resource identifier (e.g., service/api, action/build, apps/web|action/dev, or full ID)",required:!0,type:"string"}],flags:[{name:"workspace",description:'Workspace path (defaults to "root")',required:!1,type:"string"}],handler:async({project:s,args:e,flags:t})=>{let n=e.resource,r=t.workspace,i=n;if(n.startsWith("@")){let c=n.match(/^@([^#]+)#([^|]+)\|(.+)$/);if(!c)return t.format==="json"?console.log(JSON.stringify({success:!1,error:"Invalid full ID format. Expected: @project#workspace|resource"})):console.error("Error: Invalid full ID format. Expected: @project#workspace|resource"),{success:!1,message:"Invalid ID format"};r=c[2],i=c[3]}else if(n.includes("|")){let c=n.split("|");r=c[0],i=c[1]}if(!i.startsWith("action/")&&!i.startsWith("service/"))return t.format==="json"?console.log(JSON.stringify({success:!1,error:'Resource must start with "action/" or "service/" (e.g., service/api, action/build)'})):console.error('Error: Resource must start with "action/" or "service/" (e.g., service/api, action/build)'),{success:!1,message:"Invalid resource format"};let l=On({project:s,workspace:r,resource:i});return t.format==="json"?console.log(JSON.stringify(l)):console.log(`${l.id}
52
+ ${l.hash}`),{success:!0,message:"Hash generated successfully"}}}),Fo=new b({name:"internals:resource-id",description:"Generate ID for a denvig resource",usage:"internals:resource-id <resource>",example:"denvig internals:id service/hello",args:[{name:"resource",description:"Resource identifier (e.g., service/api, action/build, apps/web|action/dev)",required:!0,type:"string"}],flags:[{name:"workspace",description:'Workspace path (defaults to "root")',required:!1,type:"string"}],handler:async({project:s,args:e,flags:t})=>{let n=e.resource,r=t.workspace,i=n;if(n.includes("|")){let c=n.split("|");r=c[0],i=c[1]}if(!i.startsWith("action/")&&!i.startsWith("service/"))return t.format==="json"?console.log(JSON.stringify({success:!1,error:'Resource must start with "action/" or "service/" (e.g., service/api, action/build)'})):console.error('Error: Resource must start with "action/" or "service/" (e.g., service/api, action/build)'),{success:!1,message:"Invalid resource format"};let l=Et({project:s,workspace:r,resource:i});return t.format==="json"?console.log(JSON.stringify({id:l})):console.log(l),{success:!0,message:"ID generated successfully"}}})});var Tn,Mt,Wt,_o,Vt,In,An,Jt=h(()=>{"use strict";Tn=["pnpm-lock.yaml:","yarn.lock:","Gemfile.lock:","uv.lock:"],Mt=s=>{for(let e of Tn)if(s.startsWith(e)){let n=s.slice(e.length).match(/^([^@]+)@([^(@]+)/);if(n)return{name:n[1],version:n[2]}}return null},Wt=s=>Tn.some(e=>s.startsWith(e)),_o=s=>s.endsWith("#dependencies"),Vt=s=>s.endsWith("#devDependencies"),In=(s,e,t)=>{let n=new Map;for(let a of s)n.set(a.name,a);let r=[],i=new Set;for(let a of s)if(!(t&&a.ecosystem!==t)){for(let o of a.versions)if(!Wt(o.source)){let p=Vt(o.source);if(_o(o.source)||p){let u=`${a.name}@${o.resolved}`;i.has(u)||(i.add(u),r.push({dep:a,version:o.resolved,isDevDependency:p,children:[]}))}}}if(e>0){let a=new Map;for(let p of s)if(!(t&&p.ecosystem!==t))for(let m of p.versions){let u=Mt(m.source);if(u){let d=`${u.name}@${u.version}`,g=a.get(d)||[];g.some(f=>f.name===p.name)||(g.push(p),a.set(d,g))}}let o=(p,m,u)=>{if(m>=e)return;let d=`${p.dep.name}@${p.version}`;if(u.has(d))return;u.add(d);let g=a.get(d)||[];for(let f of g){let v=f.versions.find(y=>{let j=Mt(y.source);return j?.name===p.dep.name&&j?.version===p.version});if(v){let y={dep:f,version:v.resolved,isDevDependency:!1,children:[]};p.children.push(y),o(y,m+1,new Set(u))}}p.children.sort((f,v)=>f.dep.name.localeCompare(v.dep.name))};for(let p of r)o(p,0,new Set)}r.sort((a,o)=>{let p=a.dep.ecosystem.localeCompare(o.dep.ecosystem);return p!==0?p:a.dep.name.localeCompare(o.dep.name)});let l=[],c=(a,o,p,m)=>{l.push({name:a.dep.name,version:a.version,ecosystem:a.dep.ecosystem,isDevDependency:a.isDevDependency,depth:o,isLast:p,hasChildren:a.children.length>0,parentPath:[...m]});let u=[...m,p];a.children.forEach((d,g)=>{c(d,o+1,g===a.children.length-1,u)})};return r.forEach((a,o)=>{c(a,0,o===r.length-1,[])}),l},An=(s,e,t,n)=>{if(!Wt(t))return{name:s,version:e,children:[]};let r=[{name:s,version:e}],i=t,l=50,c=0;for(;c<l;){let p=Mt(i);if(!p)break;r.unshift({name:p.name,version:p.version});let m=n.get(p.name);if(!m)break;let u=m.versions.find(d=>d.resolved===p.version);if(!u||!Wt(u.source))break;i=u.source,c++}if(r.length===0)return null;let a={name:r[0].name,version:r[0].version,children:[]},o=a;for(let p=1;p<r.length;p++){let m={name:r[p].name,version:r[p].version,children:[]};o.children.push(m),o=m}return a}});var Gt={};x(Gt,{depsListCommand:()=>Eo});var Eo,zt=h(()=>{"use strict";k();Jt();ae();Eo=new b({name:"deps:list",description:"List all dependencies detected by plugins",usage:"deps list [--depth <n>] [--ecosystem <name>]",example:"denvig deps list --depth 1",args:[],flags:[{name:"depth",description:"Show subdependencies up to N levels deep (default: 0)",required:!1,type:"number",defaultValue:0},{name:"ecosystem",description:"Filter to a specific ecosystem (e.g., npm, rubygems, pypi)",required:!1,type:"string",defaultValue:void 0}],handler:async({project:s,flags:e})=>{let t=e.ecosystem,n=e.depth??0,r=e.format,i=await s.dependencies();if(i.length===0)return console.log(r==="json"?JSON.stringify([]):"No dependencies detected in this project."),{success:!0,message:"No dependencies detected."};let l=In(i,n,t);if(l.length===0){if(r==="json")console.log(JSON.stringify([]));else{let g=t?`No dependencies found for ecosystem "${t}".`:"No direct dependencies detected in this project.";console.log(g)}return{success:!0,message:t?`No dependencies found for ecosystem "${t}".`:"No direct dependencies detected in this project."}}if(r==="json")return console.log(JSON.stringify(i)),{success:!0,message:"Dependencies listed successfully."};let a=new Set(l.map(g=>g.ecosystem)).size>1&&!t,o=H({columns:[{header:"Package",accessor:g=>g.name},{header:"",accessor:g=>g.depth===0&&g.isDevDependency?`${$.grey}(dev)${$.reset}`:" "},{header:"Current",accessor:g=>g.version},{header:"Ecosystem",accessor:g=>g.ecosystem,visible:a}],data:l,tree:{getDepth:g=>g.depth,getIsLast:g=>g.isLast,getHasChildren:g=>g.hasChildren,getParentPath:g=>g.parentPath}});for(let g of o)console.log(g);let p=l.filter(g=>g.depth===0),m=p.filter(g=>!g.isDevDependency).length,u=p.filter(g=>g.isDevDependency).length,d=i.length-p.length;return console.log(""),console.log(`${i.length} total (${m} dependencies, ${u} devDependencies, ${d} subdependencies)`),{success:!0,message:"Dependencies listed successfully."}}})});var Fn,qt,_n,En=h(()=>{"use strict";Fn=L(require("semver"),1),qt=(s,e)=>{if(s===e)return null;try{let t=Fn.default.diff(s,e);return t?t==="major"||t==="premajor"?"major":t==="minor"||t==="preminor"?"minor":t==="patch"||t==="prepatch"||t==="prerelease"?"patch":null:null}catch{return null}},_n=(s,e)=>s===null?!1:e==="patch"?s==="patch":e==="minor"?s==="patch"||s==="minor":!1});var Ut={};x(Ut,{depsOutdatedCommand:()=>Mo});var Mn,Mo,Ht=h(()=>{"use strict";k();ae();En();Mn=(s,e)=>{if(s===e)return $.white;let t=qt(s,e);return t?t==="major"?$.red:t==="minor"?$.yellow:t==="patch"?$.green:$.white:$.white},Mo=new b({name:"deps:outdated",description:"Show outdated dependencies",usage:"deps outdated [--no-cache] [--semver patch|minor] [--ecosystem <name>]",example:"denvig deps outdated --semver patch",args:[],flags:[{name:"no-cache",description:"Skip cache and fetch fresh data from registry",required:!1,type:"boolean",defaultValue:!1},{name:"semver",description:'Filter by semver level: "patch" for patch updates only, "minor" for minor and patch updates',required:!1,type:"string",defaultValue:void 0},{name:"ecosystem",description:"Filter to a specific ecosystem (e.g., npm, rubygems, pypi)",required:!1,type:"string",defaultValue:void 0}],handler:async({project:s,flags:e})=>{let t=!e["no-cache"],n=e.semver,r=e.ecosystem,i=e.format;if(n&&n!=="patch"&&n!=="minor")return console.error(`Invalid --semver value: "${n}". Must be "patch" or "minor".`),{success:!1,message:"Invalid --semver value."};let c=await s.outdatedDependencies({cache:t}),a=d=>d.versions[0]?.resolved||"";if(r&&(c=c.filter(d=>d.ecosystem===r)),n&&(c=c.filter(d=>{let g=qt(a(d),d.latest);return _n(g,n)})),c.length===0){if(i==="json")console.log(JSON.stringify([]));else{let g="All dependencies are up to date!";r&&n?g=`No ${n}-level updates available for ecosystem "${r}".`:r?g=`No outdated dependencies found for ecosystem "${r}".`:n&&(g=`No ${n}-level updates available.`),console.log(g)}let d="All dependencies are up to date!";return r&&n?d=`No ${n}-level updates available for ecosystem "${r}".`:r?d=`No outdated dependencies found for ecosystem "${r}".`:n&&(d=`No ${n}-level updates available.`),{success:!0,message:d}}let o=c.sort((d,g)=>{let f=d.ecosystem.localeCompare(g.ecosystem);return f!==0?f:d.name.localeCompare(g.name)});if(i==="json")return console.log(JSON.stringify(o)),{success:!0,message:"Outdated dependencies listed."};let m=new Set(c.map(d=>d.ecosystem)).size>1&&!r,u=H({columns:[{header:"Package",accessor:d=>d.name},{header:"",accessor:d=>d.isDevDependency?`${$.grey}(dev)${$.reset}`:" "},{header:"Current",accessor:d=>a(d)},{header:"Wanted",accessor:d=>d.wanted,format:(d,g)=>`${Mn(a(g),g.wanted)}${d}${$.reset}`},{header:"Latest",accessor:d=>d.latest,format:(d,g)=>`${Mn(a(g),g.latest)}${d}${$.reset}`},{header:"Ecosystem",accessor:d=>d.ecosystem,visible:m}],data:o});for(let d of u)console.log(d);return{success:!0,message:"Outdated dependencies listed."}}})});var He,Be,Wn=h(()=>{"use strict";ae();He=(s,e="",t=!0,n=!0)=>{let r=[],i=s.children.length>0;if(n)r.push(`${s.name} ${$.grey}${s.version}${$.reset}`);else{let c=i?t?"\u2514\u2500\u252C ":"\u251C\u2500\u252C ":t?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ";r.push(`${e}${c}${s.name} ${$.grey}${s.version}${$.reset}`)}let l=n?"":e+(t?" ":"\u2502 ");for(let c=0;c<s.children.length;c++){let a=s.children[c],o=c===s.children.length-1;r.push(...He(a,l,o,!1))}return r},Be=(s,e)=>{let t=s.find(n=>n.name===e.name&&n.version===e.version);if(t)for(let n of e.children)Be(t.children,n);else s.push(e)}});var Bt={};x(Bt,{depsWhyCommand:()=>Wo});var Wo,Yt=h(()=>{"use strict";k();Jt();Wn();Wo=new b({name:"deps:why",description:"Show why a dependency is installed",usage:"deps why <dependency>",example:"denvig deps why yaml",args:[{name:"dependency",description:"The dependency name to look up",required:!0,type:"string"}],flags:[],completions:async({project:s})=>(await s.dependencies()).map(t=>t.name),handler:async({project:s,args:e,flags:t})=>{let n=e.dependency,r=await s.dependencies(),i=r.find(o=>o.name===n);if(!i)return t.format==="json"?console.log(JSON.stringify({dependency:n,found:!1,dependencies:[],devDependencies:[]})):console.log(`Dependency "${n}" not found in this project.`),{success:!1,message:"Dependency not found."};let l=new Map;for(let o of r)l.set(o.name,o);let c=[],a=[];for(let o of i.versions){let p=An(i.name,o.resolved,o.source,l);p&&(l.get(p.name)?.versions.some(d=>Vt(d.source))?Be(a,p):Be(c,p))}if(t.format==="json")return console.log(JSON.stringify({dependency:n,found:!0,project:{name:s.name,path:s.path},dependencies:c,devDependencies:a})),{success:!0,message:"Dependency chain shown."};if(console.log(`${s.name} ${s.path}`),console.log(""),c.length>0){console.log("dependencies:");for(let o=0;o<c.length;o++){let p=He(c[o],"",o===c.length-1,!0);for(let m of p)console.log(m)}console.log("")}if(a.length>0){console.log("devDependencies:");for(let o=0;o<a.length;o++){let p=He(a[o],"",o===a.length-1,!0);for(let m of p)console.log(m)}console.log("")}return c.length===0&&a.length===0&&console.log(`Could not determine dependency chain for "${n}".`),{success:!0,message:"Dependency chain shown."}}})});var Kt={};x(Kt,{configVerifyCommand:()=>Vo});var Vn,Jn,Vo,Zt=h(()=>{"use strict";Vn=require("path"),Jn=require("yaml");k();Xe();Qe();Vo=new b({name:"config:verify",description:"Verify a .denvig.yml file against the config schema.",usage:"config verify [path]",example:"config verify .denvig.yml",args:[{name:"path",description:"Path to the config file (defaults to .denvig.yml)",required:!1,type:"string",defaultValue:".denvig.yml"}],flags:[],handler:({project:s,args:e,flags:t})=>{let n=(0,Vn.resolve)(s.path,e.path?.toString()||".denvig.yml"),r=be(n);if(!r)return t.format==="json"?console.log(JSON.stringify({valid:!1,path:n,error:"Config file not found."})):console.error(`Config file not found: ${n}`),{success:!1,message:"Config file not found."};let i;try{i=(0,Jn.parse)(r)}catch(c){let a=c instanceof Error?c.message:"Unknown error";return t.format==="json"?console.log(JSON.stringify({valid:!1,path:n,error:`Invalid YAML syntax: ${a}`})):(console.error(`Failed to parse YAML at ${n}:`),console.error(` ${a}`)),{success:!1,message:"Invalid YAML syntax."}}let l=Ie.safeParse(i);if(!l.success){if(t.format==="json")console.log(JSON.stringify({valid:!1,path:n,errors:l.error.issues.map(c=>({path:c.path.length>0?c.path.join("."):"(root)",message:c.message}))}));else{console.error(`Config validation failed for ${n}:`);for(let c of l.error.issues){let a=c.path.length>0?c.path.join("."):"(root)";console.error(` - ${a}: ${c.message}`)}}return{success:!1,message:"Config validation failed."}}return t.format==="json"?console.log(JSON.stringify({valid:!0,path:n})):console.log(`Config is valid: ${n}`),{success:!0,message:"Config is valid."}}})});var Qt={};x(Qt,{projectsListCommand:()=>Go});var Jo,Go,Xt=h(()=>{"use strict";k();ae();ut();$e();Dt();ke();me();Jo=s=>{switch(s){case"running":return"\u{1F7E2}";case"stopped":return"\u25EF";default:return""}},Go=new b({name:"projects",description:"List all projects on the system",usage:"projects [list] [--with-config]",example:"projects --format json",args:[],flags:[{name:"with-config",description:"Only show projects with a .denvig.yml configuration file",required:!1,type:"boolean",defaultValue:!1}],handler:async({project:s,flags:e})=>{let t=e.format,n=e["with-config"],r=s.slug,i=Je({withConfig:n});if(i.length===0)return console.log(t==="json"?JSON.stringify([]):"No projects found."),{success:!0,message:"No projects found."};let l=await O.list("denvig."),c=[];for(let p of i){let m=new W(p),u=m.config.$sources.length>0,{$sources:d,...g}=m.config,f="none",v=m.config.services||{},y=Object.keys(v);if(y.length>0){let j=new A(m),D=!1;for(let C of y)if((await j.getServiceResponse(C,{launchctlList:l}))?.status==="running"){D=!0;break}f=D?"running":"stopped"}c.push({slug:p,name:m.name,path:m.path,config:u?g:null,serviceStatus:f})}let a=c.sort((p,m)=>{let u=p.slug===r,d=m.slug===r;return u&&!d?-1:!u&&d?1:p.slug.localeCompare(m.slug)});if(t==="json")return console.log(JSON.stringify(a)),{success:!0,message:"Projects listed successfully."};let o=H({columns:[{header:"",accessor:p=>Jo(p.serviceStatus)},{header:"Name",accessor:p=>p.config?.name||p.slug},{header:"Path",accessor:p=>ie(p.path)}],data:a});for(let p of o)console.log(p);return console.log(""),console.log(`${c.length} project${c.length===1?"":"s"} found`),{success:!0,message:"Projects listed successfully."}}})});var qn={};x(qn,{zshCompletionsCommand:()=>zo});var ue,zn,es,Gn,zo,Un=h(()=>{"use strict";ue=L(require("fs"),1),zn=L(require("os"),1),es=L(require("path"),1);k();Gn=`#compdef denvig
53
+
54
+ _denvig() {
55
+ local -a completions
56
+ local line
57
+
58
+ # Get completions from denvig itself
59
+ completions=("\${(@f)$(denvig zsh __complete__ -- "\${words[@]}" 2>/dev/null)}")
60
+
61
+ if [[ \${#completions[@]} -gt 0 && -n "\${completions[1]}" ]]; then
62
+ _describe 'denvig' completions
63
+ fi
64
+ }
65
+
66
+ _denvig "$@"
67
+ `,zo=new b({name:"zsh:completions",description:"Output zsh completion script",usage:"zsh completions [--install]",example:"denvig zsh completions --install",args:[],flags:[{name:"install",description:"Install completions to ~/.zsh/completions/_denvig",required:!1,type:"boolean",defaultValue:!1}],handler:({flags:s})=>{if(s.install){let e=zn.homedir(),t=es.join(e,".zsh","completions"),n=es.join(t,"_denvig");return ue.existsSync(t)||ue.mkdirSync(t,{recursive:!0}),ue.writeFileSync(n,Gn),console.log(`Installed completions to ${n}`),{success:!0}}return console.log(Gn),{success:!0}}})});var Hn,Bn=h(()=>{"use strict";Hn=async()=>{let{runCommand:s}=await Promise.resolve().then(()=>(dt(),mt)),{configCommand:e}=await Promise.resolve().then(()=>(ft(),gt)),{pluginsCommand:t}=await Promise.resolve().then(()=>(vt(),ht)),{versionCommand:n}=await Promise.resolve().then(()=>(bt(),yt)),{infoCommand:r}=await Promise.resolve().then(()=>(jt(),St)),{servicesCommand:i}=await Promise.resolve().then(()=>(wt(),Pt)),{servicesStartCommand:l}=await Promise.resolve().then(()=>(Ct(),$t)),{servicesStopCommand:c}=await Promise.resolve().then(()=>(xt(),kt)),{servicesRestartCommand:a}=await Promise.resolve().then(()=>(Rt(),Ot)),{servicesStatusCommand:o}=await Promise.resolve().then(()=>(Lt(),Nt)),{logsCommand:p}=await Promise.resolve().then(()=>(It(),Tt)),{servicesTeardownCommand:m}=await Promise.resolve().then(()=>(_t(),Ft)),{depsListCommand:u}=await Promise.resolve().then(()=>(zt(),Gt)),{depsOutdatedCommand:d}=await Promise.resolve().then(()=>(Ht(),Ut)),{depsWhyCommand:g}=await Promise.resolve().then(()=>(Yt(),Bt)),{configVerifyCommand:f}=await Promise.resolve().then(()=>(Zt(),Kt)),{projectsListCommand:v}=await Promise.resolve().then(()=>(Xt(),Qt));return{run:s,config:e,"config:verify":f,plugins:t,version:n,info:r,services:i,"services:start":l,"services:stop":c,"services:restart":a,"services:status":o,"services:logs":p,"services:teardown":m,deps:u,"deps:list":u,"deps:outdated":d,"deps:why":g,projects:v,"projects:list":v}}});var Ye,Yn,Kn=h(()=>{"use strict";Ye=["config","deps","info","outdated","plugins","projects","run","services","version","zsh"],Yn={services:["start","stop","restart","status","logs","teardown"],deps:["list","outdated","why"],config:["verify"],projects:["list"],zsh:["completions","__complete__"]}});var Zn,Qn=h(()=>{"use strict";Kn();Zn=async(s,e)=>{if(s.length===1)return[...Ye];let t=s[1],n=Yn[t];if(s.length===2){if(n)return[...n];if(Ye.includes(t)&&e?.commands&&e?.project){let r=e.commands[t];return r?.completions?await r.completions({project:e.project},[]):[]}return Ye.filter(r=>r.startsWith(t))}if(s.length===3&&n){let r=s[2];if(n.includes(r)){let i=`${t}:${r}`,l=e?.commands[i];return l?.completions&&e?.project?await l.completions({project:e.project},[]):[]}return n.filter(i=>i.startsWith(r))}if(e?.commands&&e?.project){let r,i;if(n){let l=s[2],c=`${t}:${l}`;r=e.commands[c],i=s.slice(3)}else r=e.commands[t],i=s.slice(2);if(r?.completions){let l=await r.completions({project:e.project},i),c=i[i.length-1]||"";return c?l.filter(a=>a.startsWith(c)):l}}return[]}});var Xn={};x(Xn,{zshCompleteCommand:()=>qo});var qo,er=h(()=>{"use strict";k();Bn();Qn();qo=new b({name:"zsh:__complete__",description:"Handle zsh completion requests (internal)",usage:"zsh __complete__ -- <words...>",example:"denvig zsh __complete__ -- denvig services",args:[],flags:[],handler:async({project:s,extraArgs:e=[]})=>{let t=e,n=await Hn(),r=await Zn(t,{project:s,commands:n});for(let i of r)console.log(i.replace(/:/g,"\\:"));return{success:!0}}})});var ts=L(require("minimist"),1);Se();$e();Ve();var tr=[{name:"project",description:"The project slug to run against. Defaults to current directory.",required:!1,type:"string",defaultValue:void 0},{name:"format",description:"Output format: table or json (default: table)",required:!1,type:"string",defaultValue:"table"}];async function Uo(){let s=process.argv[2],e=process.argv.slice(2),t=J(),n=process.cwd(),r=(0,ts.default)(process.argv.slice(2)).project?.toString()||n.replace(`${t.codeRootDir}/`,"").split("/").slice(0,2).join("/"),i=new W(r),l={outdated:"deps:outdated"};l[s]&&(s=l[s]);let c=["start","stop","restart","status","logs","teardown"];if(s==="services"){let S=process.argv[3];S&&c.includes(S)&&(s=`services:${S}`,e=[process.argv[2],...process.argv.slice(4)])}let a=["list","outdated","why"];if(s==="deps"){let S=process.argv[3];S&&a.includes(S)&&(s=`deps:${S}`,e=[process.argv[2],...process.argv.slice(4)])}let o=["verify"];if(s==="config"){let S=process.argv[3];S&&o.includes(S)&&(s=`config:${S}`,e=[process.argv[2],...process.argv.slice(4)])}let p=["list"];if(s==="projects"){let S=process.argv[3];S&&p.includes(S)&&(s=`projects:${S}`,e=[process.argv[2],...process.argv.slice(4)])}let m=["completions","__complete__"];if(s==="zsh"){let S=process.argv[3];S&&m.includes(S)&&(s=`zsh:${S}`,e=[process.argv[2],...process.argv.slice(4)])}let u=[...t.quickActions||[],...i?.config?.quickActions||[]].sort();u.includes(s)&&(e=["run",...process.argv.slice(2)],s="run",console.log("> Proxying to denvig run",...process.argv.slice(2)));let{runCommand:d}=await Promise.resolve().then(()=>(dt(),mt)),{configCommand:g}=await Promise.resolve().then(()=>(ft(),gt)),{pluginsCommand:f}=await Promise.resolve().then(()=>(vt(),ht)),{versionCommand:v}=await Promise.resolve().then(()=>(bt(),yt)),{infoCommand:y}=await Promise.resolve().then(()=>(jt(),St)),{servicesCommand:j}=await Promise.resolve().then(()=>(wt(),Pt)),{servicesStartCommand:D}=await Promise.resolve().then(()=>(Ct(),$t)),{servicesStopCommand:C}=await Promise.resolve().then(()=>(xt(),kt)),{servicesRestartCommand:F}=await Promise.resolve().then(()=>(Rt(),Ot)),{servicesStatusCommand:V}=await Promise.resolve().then(()=>(Lt(),Nt)),{logsCommand:G}=await Promise.resolve().then(()=>(It(),Tt)),{servicesTeardownCommand:ge}=await Promise.resolve().then(()=>(_t(),Ft)),{internalsResourceHashCommand:fe,internalsResourceIdCommand:Oe}=await Promise.resolve().then(()=>(Ln(),Nn)),{depsListCommand:he}=await Promise.resolve().then(()=>(zt(),Gt)),{depsOutdatedCommand:sr}=await Promise.resolve().then(()=>(Ht(),Ut)),{depsWhyCommand:nr}=await Promise.resolve().then(()=>(Yt(),Bt)),{configVerifyCommand:rr}=await Promise.resolve().then(()=>(Zt(),Kt)),{projectsListCommand:ss}=await Promise.resolve().then(()=>(Xt(),Qt)),{zshCompletionsCommand:or}=await Promise.resolve().then(()=>(Un(),qn)),{zshCompleteCommand:ir}=await Promise.resolve().then(()=>(er(),Xn)),ve={run:d,config:g,"config:verify":rr,plugins:f,version:v,info:y,services:j,"services:start":D,"services:stop":C,"services:restart":F,"services:status":V,"services:logs":G,"services:teardown":ge,deps:he,"deps:list":he,"deps:outdated":sr,"deps:why":nr,"internals:resource-hash":fe,"internals:resource-id":Oe,projects:ss,"projects:list":ss,"zsh:completions":or,"zsh:__complete__":ir},Re=ve[s],ye=(0,ts.default)(e),cr=Re?.args.reduce((S,P,Le)=>{let Te=ye._[Le+1];return Te!==void 0?S[P.name]=Te:P.required&&(console.error(`Missing required argument: ${P.name}`),process.exit(1)),S},{})||{},ar=ye._.slice(Re?.args.length+1).map(S=>String(S))||[],ns=[...tr,...Re?.flags||[]],lr=new Set(ns.map(S=>S.name)),pr=ns.reduce((S,P)=>(ye[P.name]!==void 0?S[P.name]=ye[P.name]:P.defaultValue!==void 0?S[P.name]=P.defaultValue:P.required&&(console.error(`Missing required flag: ${P.name}`),process.exit(1)),S),{format:"table"}),Ne=[];for(let[S,P]of Object.entries(ye))S!=="_"&&!lr.has(S)&&(P===!0?Ne.push(`--${S}`):P===!1?Ne.push(`--no-${S}`):Ne.push(`--${S}`,String(P)));let mr=[...ar,...Ne];if(!s){console.log(`Denvig v${oe()}`),console.log(""),console.log("Usage: denvig <command> [args] [flags]"),console.log(""),console.log("Available commands:"),Object.keys(ve).forEach(P=>{P.startsWith("internals:")||P==="zsh:__complete__"||P==="deps"||P==="projects"||console.log(` - ${ve[P].usage.padEnd(20," ")} ${ve[P].description}`)}),console.log(""),console.log("Quick Actions:");for(let P of u){let Le=(await i?.actions)?.[P];if(!Le){console.log(` - ${P.padEnd(20," ")} not defined`);return}for(let Te of Le){let rs=Te.split(`
68
+ `),dr=rs[0],ur=rs.slice(1);console.log(` - ${P.padEnd(20," ")} $ ${dr}`);for(let os of ur)os.trim()&&console.log(`${" ".repeat(27)}${os}`)}}console.log(""),console.log("Global flags:"),tr.forEach(P=>{console.log(` --${P.name.padEnd(20," ")} ${P.description}`)}),process.exit(1)}ve[s]||(console.error(`Command "${s}" not found.`),process.exit(1));try{r||console.error("No project provided or detected.");let{success:S}=await Re.run(i,cr,pr,mr);S||process.exit(1)}catch(S){console.error(`Error executing command "${s}":`,S),process.exit(1)}}Uo();
package/dist/sdk.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var a=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var v=(i,e)=>{for(var s in e)a(i,s,{get:e[s],enumerable:!0})},m=(i,e,s,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of g(e))!h.call(i,r)&&r!==s&&a(i,r,{get:()=>e[r],enumerable:!(t=u(e,r))||t.enumerable});return i};var y=i=>m(a({},"__esModule",{value:!0}),i);var O={};v(O,{DenvigSDK:()=>o,DenvigSDKError:()=>n,default:()=>f});module.exports=y(O);var l=require("child_process"),d=require("util"),p=(0,d.promisify)(l.exec),o=class{locale;cliPath;cwd;shell;constructor(e={}){this.locale=e.locale??"en_GB.UTF-8",this.cliPath=e.cliPath??"./node_modules/.bin/denvig",this.cwd=e.cwd??process.cwd(),this.shell=e.shell??"/bin/zsh"}async run(e){try{let{stdout:s}=await p(`${this.cliPath} ${e} --format json`,{encoding:"utf-8",cwd:this.cwd,shell:this.shell,env:{...process.env,LC_ALL:this.locale}});return JSON.parse(s)}catch(s){let t=s;if(t.stdout)try{return JSON.parse(t.stdout)}catch{}throw new n(`Command failed: denvig ${e}`,t.message,t.stderr,t.stdout)}}async runText(e){try{let{stdout:s}=await p(`${this.cliPath} ${e}`,{encoding:"utf-8",cwd:this.cwd,shell:this.shell,env:{...process.env,LC_ALL:this.locale}});return s.trim()}catch(s){let t=s;throw new n(`Command failed: denvig ${e}`,t.message,t.stderr,t.stdout)}}buildFlags(e){let s=[];for(let[t,r]of Object.entries(e)){if(r==null)continue;let c=t.replace(/([A-Z])/g,"-$1").toLowerCase();typeof r=="boolean"?r&&s.push(`--${c}`):s.push(`--${c}`,String(r))}return s.join(" ")}async version(){return(await this.runText("version")).replace(/^v/,"")}services={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`services ${s}`.trim())},status:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services status ${e} ${t}`.trim())},start:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services start ${e} ${t}`.trim())},stop:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services stop ${e} ${t}`.trim())},restart:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services restart ${e} ${t}`.trim())}};deps={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`deps list ${s}`.trim())},outdated:async e=>{let s=e?this.buildFlags(e):"";return this.run(`deps outdated ${s}`.trim())}}},n=class extends Error{constructor(s,t,r,c){super(s);this.originalMessage=t;this.stderr=r;this.stdout=c;this.name="DenvigSDKError"}},f=o;0&&(module.exports={DenvigSDK,DenvigSDKError});
1
+ "use strict";var a=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var h=Object.prototype.hasOwnProperty;var v=(i,e)=>{for(var s in e)a(i,s,{get:e[s],enumerable:!0})},m=(i,e,s,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of g(e))!h.call(i,r)&&r!==s&&a(i,r,{get:()=>e[r],enumerable:!(t=u(e,r))||t.enumerable});return i};var y=i=>m(a({},"__esModule",{value:!0}),i);var O={};v(O,{DenvigSDK:()=>o,DenvigSDKError:()=>n,default:()=>f});module.exports=y(O);var l=require("child_process"),d=require("util"),p=(0,d.promisify)(l.exec),o=class{locale;cliPath;cwd;shell;constructor(e={}){this.locale=e.locale??"en_GB.UTF-8",this.cliPath=e.cliPath??"./node_modules/.bin/denvig",this.cwd=e.cwd??process.cwd(),this.shell=e.shell??"/bin/zsh"}async run(e){try{let{stdout:s}=await p(`${this.cliPath} ${e} --format json`,{encoding:"utf-8",cwd:this.cwd,shell:this.shell,env:{...process.env,LC_ALL:this.locale}});return JSON.parse(s)}catch(s){let t=s;if(t.stdout)try{return JSON.parse(t.stdout)}catch{}throw new n(`Command failed: denvig ${e}`,t.message,t.stderr,t.stdout)}}async runText(e){try{let{stdout:s}=await p(`${this.cliPath} ${e}`,{encoding:"utf-8",cwd:this.cwd,shell:this.shell,env:{...process.env,LC_ALL:this.locale}});return s.trim()}catch(s){let t=s;throw new n(`Command failed: denvig ${e}`,t.message,t.stderr,t.stdout)}}buildFlags(e){let s=[];for(let[t,r]of Object.entries(e)){if(r==null)continue;let c=t.replace(/([A-Z])/g,"-$1").toLowerCase();typeof r=="boolean"?r&&s.push(`--${c}`):s.push(`--${c}`,String(r))}return s.join(" ")}async version(){return(await this.runText("version")).replace(/^v/,"")}services={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`services ${s}`.trim())},status:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services status ${e} ${t}`.trim())},start:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services start ${e} ${t}`.trim())},stop:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services stop ${e} ${t}`.trim())},restart:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services restart ${e} ${t}`.trim())}};deps={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`deps list ${s}`.trim())},outdated:async e=>{let s=e?this.buildFlags(e):"";return this.run(`deps outdated ${s}`.trim())}};projects={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`projects list ${s}`.trim())}}},n=class extends Error{constructor(s,t,r,c){super(s);this.originalMessage=t;this.stderr=r;this.stdout=c;this.name="DenvigSDKError"}},f=o;0&&(module.exports={DenvigSDK,DenvigSDKError});
package/dist/sdk.d.cts CHANGED
@@ -1,8 +1,45 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * The per project configuration.
5
+ * This is usually loaded from ~/.denvig.yml or ~/.denvig/config.yml
6
+ *
7
+ * @example
8
+ * name: My Project
9
+ * actions:
10
+ * build:
11
+ * command: pnpm build
12
+ * clean:
13
+ * command: rf -rf dist
14
+ */
15
+ declare const ProjectConfigSchema: z.ZodObject<{
16
+ name: z.ZodString;
17
+ actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
18
+ command: z.ZodString;
19
+ }, z.core.$strip>>>;
20
+ quickActions: z.ZodOptional<z.ZodArray<z.ZodString>>;
21
+ services: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
22
+ cwd: z.ZodOptional<z.ZodString>;
23
+ command: z.ZodString;
24
+ http: z.ZodOptional<z.ZodObject<{
25
+ port: z.ZodOptional<z.ZodNumber>;
26
+ domain: z.ZodOptional<z.ZodString>;
27
+ secure: z.ZodOptional<z.ZodBoolean>;
28
+ }, z.core.$strict>>;
29
+ envFile: z.ZodOptional<z.ZodString>;
30
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
31
+ keepAlive: z.ZodOptional<z.ZodBoolean>;
32
+ startOnBoot: z.ZodOptional<z.ZodBoolean>;
33
+ }, z.core.$strict>>>;
34
+ }, z.core.$strict>;
35
+ type ProjectConfigSchema = z.infer<typeof ProjectConfigSchema>;
36
+
1
37
  /**
2
38
  * Shared response types for CLI JSON output and SDK.
3
39
  * This is the single source of truth for all JSON response shapes.
4
40
  * @module
5
41
  */
42
+
6
43
  /**
7
44
  * Service information for display.
8
45
  */
@@ -15,6 +52,7 @@ type ServiceInfo = {
15
52
  domain?: string;
16
53
  secure?: boolean;
17
54
  };
55
+ startOnBoot?: boolean;
18
56
  };
19
57
  /**
20
58
  * Result of a service operation.
@@ -83,12 +121,15 @@ type OutdatedDependency = Dependency & {
83
121
  specifier: string;
84
122
  isDevDependency: boolean;
85
123
  };
86
-
87
124
  /**
88
- * Re-exported types from shared types file.
89
- * These are the single source of truth for CLI JSON responses.
90
- * @module
125
+ * A project from projects:list command.
91
126
  */
127
+ type ProjectResponse = {
128
+ slug: string;
129
+ name: string;
130
+ path: string;
131
+ config: ProjectConfigSchema | null;
132
+ };
92
133
 
93
134
  /**
94
135
  * Response when a service operation fails.
@@ -147,6 +188,10 @@ type DepsOutdatedOptions = {
147
188
  /** Filter to a specific ecosystem (e.g., npm, rubygems, pypi) */
148
189
  ecosystem?: string;
149
190
  };
191
+ type ProjectsListOptions = {
192
+ /** Only include projects with a .denvig.yml configuration file */
193
+ withConfig?: boolean;
194
+ };
150
195
  /**
151
196
  * Denvig SDK for programmatic access to the CLI.
152
197
  *
@@ -229,6 +274,15 @@ declare class DenvigSDK {
229
274
  */
230
275
  outdated: (options?: DepsOutdatedOptions) => Promise<OutdatedDependency[]>;
231
276
  };
277
+ /**
278
+ * Project management commands.
279
+ */
280
+ projects: {
281
+ /**
282
+ * List all projects on the system.
283
+ */
284
+ list: (options?: ProjectsListOptions) => Promise<ProjectResponse[]>;
285
+ };
232
286
  }
233
287
  /**
234
288
  * Error thrown when a denvig CLI command fails.
@@ -240,4 +294,4 @@ declare class DenvigSDKError extends Error {
240
294
  constructor(message: string, originalMessage?: string | undefined, stderr?: string | undefined, stdout?: string | undefined);
241
295
  }
242
296
 
243
- export { DenvigSDK, DenvigSDKError, type DenvigSDKOptions, type Dependency, type DependencyVersion, type DepsListOptions, type DepsOutdatedOptions, type ListServicesOptions, type OutdatedDependency, type ServiceInfo, type ServiceOperationError, type ServiceOperationOptions, type ServiceResponse, type ServiceResult, type ServiceStatus, DenvigSDK as default };
297
+ export { DenvigSDK, DenvigSDKError, type DenvigSDKOptions, type Dependency, type DependencyVersion, type DepsListOptions, type DepsOutdatedOptions, type ListServicesOptions, type OutdatedDependency, ProjectConfigSchema, type ProjectResponse, type ProjectsListOptions, type ServiceInfo, type ServiceOperationError, type ServiceOperationOptions, type ServiceResponse, type ServiceResult, type ServiceStatus, DenvigSDK as default };
package/dist/sdk.d.ts CHANGED
@@ -1,8 +1,45 @@
1
+ import { z } from 'zod';
2
+
3
+ /**
4
+ * The per project configuration.
5
+ * This is usually loaded from ~/.denvig.yml or ~/.denvig/config.yml
6
+ *
7
+ * @example
8
+ * name: My Project
9
+ * actions:
10
+ * build:
11
+ * command: pnpm build
12
+ * clean:
13
+ * command: rf -rf dist
14
+ */
15
+ declare const ProjectConfigSchema: z.ZodObject<{
16
+ name: z.ZodString;
17
+ actions: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
18
+ command: z.ZodString;
19
+ }, z.core.$strip>>>;
20
+ quickActions: z.ZodOptional<z.ZodArray<z.ZodString>>;
21
+ services: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
22
+ cwd: z.ZodOptional<z.ZodString>;
23
+ command: z.ZodString;
24
+ http: z.ZodOptional<z.ZodObject<{
25
+ port: z.ZodOptional<z.ZodNumber>;
26
+ domain: z.ZodOptional<z.ZodString>;
27
+ secure: z.ZodOptional<z.ZodBoolean>;
28
+ }, z.core.$strict>>;
29
+ envFile: z.ZodOptional<z.ZodString>;
30
+ env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
31
+ keepAlive: z.ZodOptional<z.ZodBoolean>;
32
+ startOnBoot: z.ZodOptional<z.ZodBoolean>;
33
+ }, z.core.$strict>>>;
34
+ }, z.core.$strict>;
35
+ type ProjectConfigSchema = z.infer<typeof ProjectConfigSchema>;
36
+
1
37
  /**
2
38
  * Shared response types for CLI JSON output and SDK.
3
39
  * This is the single source of truth for all JSON response shapes.
4
40
  * @module
5
41
  */
42
+
6
43
  /**
7
44
  * Service information for display.
8
45
  */
@@ -15,6 +52,7 @@ type ServiceInfo = {
15
52
  domain?: string;
16
53
  secure?: boolean;
17
54
  };
55
+ startOnBoot?: boolean;
18
56
  };
19
57
  /**
20
58
  * Result of a service operation.
@@ -83,12 +121,15 @@ type OutdatedDependency = Dependency & {
83
121
  specifier: string;
84
122
  isDevDependency: boolean;
85
123
  };
86
-
87
124
  /**
88
- * Re-exported types from shared types file.
89
- * These are the single source of truth for CLI JSON responses.
90
- * @module
125
+ * A project from projects:list command.
91
126
  */
127
+ type ProjectResponse = {
128
+ slug: string;
129
+ name: string;
130
+ path: string;
131
+ config: ProjectConfigSchema | null;
132
+ };
92
133
 
93
134
  /**
94
135
  * Response when a service operation fails.
@@ -147,6 +188,10 @@ type DepsOutdatedOptions = {
147
188
  /** Filter to a specific ecosystem (e.g., npm, rubygems, pypi) */
148
189
  ecosystem?: string;
149
190
  };
191
+ type ProjectsListOptions = {
192
+ /** Only include projects with a .denvig.yml configuration file */
193
+ withConfig?: boolean;
194
+ };
150
195
  /**
151
196
  * Denvig SDK for programmatic access to the CLI.
152
197
  *
@@ -229,6 +274,15 @@ declare class DenvigSDK {
229
274
  */
230
275
  outdated: (options?: DepsOutdatedOptions) => Promise<OutdatedDependency[]>;
231
276
  };
277
+ /**
278
+ * Project management commands.
279
+ */
280
+ projects: {
281
+ /**
282
+ * List all projects on the system.
283
+ */
284
+ list: (options?: ProjectsListOptions) => Promise<ProjectResponse[]>;
285
+ };
232
286
  }
233
287
  /**
234
288
  * Error thrown when a denvig CLI command fails.
@@ -240,4 +294,4 @@ declare class DenvigSDKError extends Error {
240
294
  constructor(message: string, originalMessage?: string | undefined, stderr?: string | undefined, stdout?: string | undefined);
241
295
  }
242
296
 
243
- export { DenvigSDK, DenvigSDKError, type DenvigSDKOptions, type Dependency, type DependencyVersion, type DepsListOptions, type DepsOutdatedOptions, type ListServicesOptions, type OutdatedDependency, type ServiceInfo, type ServiceOperationError, type ServiceOperationOptions, type ServiceResponse, type ServiceResult, type ServiceStatus, DenvigSDK as default };
297
+ export { DenvigSDK, DenvigSDKError, type DenvigSDKOptions, type Dependency, type DependencyVersion, type DepsListOptions, type DepsOutdatedOptions, type ListServicesOptions, type OutdatedDependency, ProjectConfigSchema, type ProjectResponse, type ProjectsListOptions, type ServiceInfo, type ServiceOperationError, type ServiceOperationOptions, type ServiceResponse, type ServiceResult, type ServiceStatus, DenvigSDK as default };
package/dist/sdk.js CHANGED
@@ -1 +1 @@
1
- import{exec as p}from"child_process";import{promisify as l}from"util";var c=l(p),o=class{locale;cliPath;cwd;shell;constructor(e={}){this.locale=e.locale??"en_GB.UTF-8",this.cliPath=e.cliPath??"./node_modules/.bin/denvig",this.cwd=e.cwd??process.cwd(),this.shell=e.shell??"/bin/zsh"}async run(e){try{let{stdout:s}=await c(`${this.cliPath} ${e} --format json`,{encoding:"utf-8",cwd:this.cwd,shell:this.shell,env:{...process.env,LC_ALL:this.locale}});return JSON.parse(s)}catch(s){let t=s;if(t.stdout)try{return JSON.parse(t.stdout)}catch{}throw new i(`Command failed: denvig ${e}`,t.message,t.stderr,t.stdout)}}async runText(e){try{let{stdout:s}=await c(`${this.cliPath} ${e}`,{encoding:"utf-8",cwd:this.cwd,shell:this.shell,env:{...process.env,LC_ALL:this.locale}});return s.trim()}catch(s){let t=s;throw new i(`Command failed: denvig ${e}`,t.message,t.stderr,t.stdout)}}buildFlags(e){let s=[];for(let[t,r]of Object.entries(e)){if(r==null)continue;let n=t.replace(/([A-Z])/g,"-$1").toLowerCase();typeof r=="boolean"?r&&s.push(`--${n}`):s.push(`--${n}`,String(r))}return s.join(" ")}async version(){return(await this.runText("version")).replace(/^v/,"")}services={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`services ${s}`.trim())},status:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services status ${e} ${t}`.trim())},start:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services start ${e} ${t}`.trim())},stop:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services stop ${e} ${t}`.trim())},restart:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services restart ${e} ${t}`.trim())}};deps={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`deps list ${s}`.trim())},outdated:async e=>{let s=e?this.buildFlags(e):"";return this.run(`deps outdated ${s}`.trim())}}},i=class extends Error{constructor(s,t,r,n){super(s);this.originalMessage=t;this.stderr=r;this.stdout=n;this.name="DenvigSDKError"}},g=o;export{o as DenvigSDK,i as DenvigSDKError,g as default};
1
+ import{exec as p}from"child_process";import{promisify as l}from"util";var c=l(p),o=class{locale;cliPath;cwd;shell;constructor(e={}){this.locale=e.locale??"en_GB.UTF-8",this.cliPath=e.cliPath??"./node_modules/.bin/denvig",this.cwd=e.cwd??process.cwd(),this.shell=e.shell??"/bin/zsh"}async run(e){try{let{stdout:s}=await c(`${this.cliPath} ${e} --format json`,{encoding:"utf-8",cwd:this.cwd,shell:this.shell,env:{...process.env,LC_ALL:this.locale}});return JSON.parse(s)}catch(s){let t=s;if(t.stdout)try{return JSON.parse(t.stdout)}catch{}throw new i(`Command failed: denvig ${e}`,t.message,t.stderr,t.stdout)}}async runText(e){try{let{stdout:s}=await c(`${this.cliPath} ${e}`,{encoding:"utf-8",cwd:this.cwd,shell:this.shell,env:{...process.env,LC_ALL:this.locale}});return s.trim()}catch(s){let t=s;throw new i(`Command failed: denvig ${e}`,t.message,t.stderr,t.stdout)}}buildFlags(e){let s=[];for(let[t,r]of Object.entries(e)){if(r==null)continue;let n=t.replace(/([A-Z])/g,"-$1").toLowerCase();typeof r=="boolean"?r&&s.push(`--${n}`):s.push(`--${n}`,String(r))}return s.join(" ")}async version(){return(await this.runText("version")).replace(/^v/,"")}services={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`services ${s}`.trim())},status:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services status ${e} ${t}`.trim())},start:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services start ${e} ${t}`.trim())},stop:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services stop ${e} ${t}`.trim())},restart:async(e,s)=>{let t=s?this.buildFlags(s):"";return this.run(`services restart ${e} ${t}`.trim())}};deps={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`deps list ${s}`.trim())},outdated:async e=>{let s=e?this.buildFlags(e):"";return this.run(`deps outdated ${s}`.trim())}};projects={list:async e=>{let s=e?this.buildFlags(e):"";return this.run(`projects list ${s}`.trim())}}},i=class extends Error{constructor(s,t,r,n){super(s);this.originalMessage=t;this.stderr=r;this.stdout=n;this.name="DenvigSDKError"}},g=o;export{o as DenvigSDK,i as DenvigSDKError,g as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "denvig",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "license": "MIT",
5
5
  "description": "A CLI tool to consistently manage cross-discipline projects",
6
6
  "bin": {
@@ -34,8 +34,8 @@
34
34
  "prepublishOnly": "npm run build",
35
35
  "lint": "biome check",
36
36
  "lint:fix": "biome check --fix",
37
- "test": "node --test --test-skip-pattern='node_modules' src/**/*.test.ts",
38
- "test:ci": "node --test --test-skip-pattern='node_modules' src/**/*.test.ts --reporter=default",
37
+ "test": "node --test --test-skip-pattern='node_modules' 'src/**/*.test.ts'",
38
+ "test:ci": "node --test --test-skip-pattern='node_modules' 'src/**/*.test.ts' --reporter=default",
39
39
  "dev": "tsc --watch"
40
40
  },
41
41
  "dependencies": {