denvig 0.3.0 → 0.4.0
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/README.md +65 -8
- package/dist/cli.cjs +55 -4
- package/package.json +10 -9
package/README.md
CHANGED
|
@@ -49,6 +49,51 @@ denvig outdated
|
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
### Dependencies
|
|
53
|
+
|
|
54
|
+
Inspect and manage project dependencies across multiple ecosystems (npm, pnpm, yarn, Ruby/Bundler, Python/uv):
|
|
55
|
+
|
|
56
|
+
```shell
|
|
57
|
+
denvig deps # List all dependencies
|
|
58
|
+
denvig deps list # List all dependencies (explicit)
|
|
59
|
+
denvig deps outdated # Show outdated dependencies
|
|
60
|
+
denvig deps outdated --semver patch # Filter by semver level
|
|
61
|
+
denvig deps --format json # Output as JSON
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
### Services
|
|
66
|
+
|
|
67
|
+
Manage background services defined in `.denvig.yml`. Services run via launchctl on macOS:
|
|
68
|
+
|
|
69
|
+
```shell
|
|
70
|
+
denvig services # List services and their status
|
|
71
|
+
denvig services start # Start all services
|
|
72
|
+
denvig services stop # Stop all services
|
|
73
|
+
denvig services restart # Restart all services
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Target a specific service by name:
|
|
77
|
+
|
|
78
|
+
```shell
|
|
79
|
+
denvig services start api # Start only the 'api' service
|
|
80
|
+
denvig services status api # Start only the 'api' service
|
|
81
|
+
denvig services stop api # Stop only the 'api' service
|
|
82
|
+
denvig services restart api # Restart only the 'api' service
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Manage services globally from any directory:
|
|
86
|
+
|
|
87
|
+
```shell
|
|
88
|
+
denvig services start marcqualie/denvig/hello # Start 'api' in marcqualie/denvig project
|
|
89
|
+
denvig services status marcqualie/denvig/hello # Check status of 'api' service
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
See [docs/configuration.md](docs/configuration.md) for service configuration options.
|
|
93
|
+
|
|
94
|
+
All services commands also accept `--format json` for programmatic output.
|
|
95
|
+
|
|
96
|
+
|
|
52
97
|
|
|
53
98
|
## Languages / Frameworks
|
|
54
99
|
|
|
@@ -58,11 +103,9 @@ can be supported by using the per project configs.
|
|
|
58
103
|
- [x] Node.js (npm, pnpm, yarn)
|
|
59
104
|
- [ ] Bun
|
|
60
105
|
- [ ] Vite
|
|
61
|
-
- [
|
|
62
|
-
- [
|
|
63
|
-
- [
|
|
64
|
-
- [ ] Rails
|
|
65
|
-
- [x] Python
|
|
106
|
+
- [ ] Deno
|
|
107
|
+
- [x] Ruby (rubygems)
|
|
108
|
+
- [x] Python (uv)
|
|
66
109
|
|
|
67
110
|
|
|
68
111
|
|
|
@@ -72,14 +115,28 @@ can be supported by using the per project configs.
|
|
|
72
115
|
- [x] YAML configuration at ~/.denvig.yml
|
|
73
116
|
- [x] Per project configuration via ./.denvig.yml
|
|
74
117
|
- [x] Consistent API for all languages/frameworks
|
|
118
|
+
- [x] Dependency management across multiple ecosystems
|
|
119
|
+
- [x] Background service management
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
## Troubleshooting
|
|
124
|
+
|
|
125
|
+
For troubleshooting guides including service management, resource identification, and log browsing, see [docs/troubleshooting.md](docs/troubleshooting.md).
|
|
75
126
|
|
|
76
127
|
|
|
77
128
|
|
|
78
129
|
## Building from source
|
|
79
130
|
|
|
80
|
-
You can build
|
|
131
|
+
You can build from source instead of using the provided methods above:
|
|
132
|
+
|
|
133
|
+
```shell
|
|
134
|
+
pnpm install
|
|
135
|
+
pnpm build
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
After building, the CLI will be available at `dist/cli.cjs`. You can link it globally:
|
|
81
139
|
|
|
82
140
|
```shell
|
|
83
|
-
|
|
84
|
-
cp dist/denvig /usr/local/bin/denvig
|
|
141
|
+
npm link
|
|
85
142
|
```
|
package/dist/cli.cjs
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";var Be=Object.create;var U=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var Qe=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Ze=Object.prototype.hasOwnProperty;var a=(n,e)=>()=>(n&&(e=n(n=0)),e);var w=(n,e)=>{for(var o in e)U(n,o,{get:e[o],enumerable:!0})},en=(n,e,o,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of Qe(e))!Ze.call(n,s)&&s!==o&&U(n,s,{get:()=>e[s],enumerable:!(t=Ke(e,s))||t.enumerable});return n};var D=(n,e,o)=>(o=n!=null?Be(Xe(n)):{},en(e||!n||!n.__esModule?U(o,"default",{value:n,enumerable:!0}):o,n));var h,nn,oe,V,te,se=a(()=>{"use strict";h=require("zod"),nn=["build","check-types","dev","install","lint","outdated","test"],oe=h.z.object({}),V=oe.extend({codeRootDir:h.z.string().describe("The root directory where all code is stored"),quickActions:h.z.array(h.z.string()).default(nn).optional().describe("Actions that are available on the CLI root for quick access")}),te=oe.extend({name:h.z.string().describe("Unique identifier for the project"),actions:h.z.record(h.z.string().describe("Name of the action"),h.z.object({command:h.z.string().describe("Shell command to run for the action")})).optional().describe("Actions that can be run against the project"),quickActions:h.z.array(h.z.string()).optional().describe("Actions that are available on the CLI root for quick access")})});var ie,on,W,re=a(()=>{"use strict";ie=require("fs"),on=require("fs/promises"),W=n=>{try{return(0,ie.readFileSync)(n,"utf8").trim()||null}catch(e){if(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")return null;throw e}}});var R,z,N,tn,ce,$,ae,G=a(()=>{"use strict";R=require("path"),z=require("yaml");se();re();N=(0,R.resolve)(process.env.DENVIG_GLOBAL_CONFIG_PATH||`${process.env.HOME}/.denvig/config.yml`),tn=(0,R.resolve)(process.env.DENVIG_CODE_ROOT_DIR||`${process.env.HOME}/src`),ce={codeRootDir:tn,quickActions:void 0},$=()=>{let n=W(N);if(n){let e=(0,z.parse)(n)||{};try{if(e.codeRootDir?.startsWith(".")){let o=(0,R.dirname)(N);e.codeRootDir=(0,R.resolve)(`${o}/${e.codeRootDir}`)}return{...V.parse({...ce,...e}),$sources:[N]}}catch(o){console.error(`Error parsing global config at ${N}:`,o),process.exit(1)}}return{...V.parse(ce),$sources:[]}},ae=n=>{let e=$(),o={name:n,actions:{}},t=`${e.codeRootDir}/${n}/.denvig.yml`,s=W(t);if(s)try{return{...o,...te.parse((0,z.parse)(s)),$sources:[t]}}catch(i){console.warn(`Error parsing project config for ${n} at ${t}.`),i instanceof Error?console.warn(i.message):console.warn("Unknown error:",i)}return{...o,$sources:[]}}});var _,Y=a(()=>{"use strict";_=(n,e)=>{for(let[o,t]of Object.entries(e))n[o]||(n[o]=[]),n[o].push(...t);return n}});var B,P,O=a(()=>{"use strict";B=D(require("fs"),1),P=n=>{let e=`${n.path}/package.json`;if(!B.default.existsSync(e))return null;let o=B.default.readFileSync(e,"utf-8");return JSON.parse(o)}});var y,x=a(()=>{"use strict";y=n=>n});var j,sn,le,ge=a(()=>{"use strict";j=D(require("fs"),1);Y();O();x();sn=y({name:"deno",actions:async n=>{let e=j.default.readdirSync(n.path);if(!(e.includes("deno.json")||e.includes("deno.jsonc")))return{};let s=P(n)?.scripts||{},i={...Object.entries(s).map(([g,p])=>[g,`deno ${p}`]).reduce((g,[p,m])=>(g[p]=[m],g),{}),install:["deno install"],outdated:["deno outdated"]},r=((0,j.existsSync)(`${n.path}/deno.json`)?JSON.parse((0,j.readFileSync)(`${n.path}/deno.json`,"utf8")):(0,j.existsSync)(`${n.path}/deno.jsonc`)?JSON.parse((0,j.readFileSync)(`${n.path}/deno.jsonc`,"utf8")):{}).tasks||{};return i=_(i,{test:[r?.test?"deno task test":"deno test"],lint:[r?.lint?"deno task lint":"deno lint"],"check-types":[r?.checkTypes?"deno task check-types":"deno check"],...Object.entries(r).reduce((g,[p,m])=>(g[p]=[m.startsWith("deno")?m:`deno task ${p}`],g),{}),install:["deno install"],outdated:["deno outdated"]}),i}}),le=sn});var pe,rn,de,me=a(()=>{"use strict";pe=D(require("fs"),1);O();x();rn=y({name:"npm",actions:async n=>{let e=pe.default.readdirSync(n.path),o=e.includes("package.json"),t=e.includes("pnpm-lock.yaml"),s=e.includes("package-lock.json"),i=e.includes("yarn.lock"),d=e.includes("deno.json")||e.includes("deno.jsonc");if(!(s||o&&!t&&!i&&!d))return{};let p=P(n)?.scripts||{};return{...Object.entries(p).map(([f,u])=>[f,`npm run ${f}`]).reduce((f,[u,v])=>(f[u]=[v],f),{}),install:["npm install"],outdated:["npm outdated"]}}}),de=rn});var cn,fe,ue=a(()=>{"use strict";O();x();cn=y({name:"pnpm",actions:async n=>{if(!n.rootFiles.includes("pnpm-lock.yaml"))return{};let s=P(n)?.scripts||{},i=n.rootFiles.includes("pnpm-workspace.yaml");return{...Object.entries(s).map(([r,g])=>[r,`pnpm run ${r}`]).reduce((r,[g,p])=>(r[g]=[p],r),{}),install:["pnpm install"],outdated:[i?"pnpm outdated -r":"pnpm outdated"]}}}),fe=cn});var K,an,he,ye=a(()=>{"use strict";K=D(require("fs"),1);x();an=y({name:"ruby",actions:async n=>{let e=K.default.readdirSync(n.path),o=e.includes("Gemfile"),t=e.includes("Rakefile"),s=e.includes("config.ru"),i=K.default.existsSync(`${n.path}/config/application.rb`);if(!(o||t))return{};let r={install:["bundle install"],update:["bundle update"],outdated:["bundle outdated"]};return i&&(r.dev=["bundle exec rails server"],r.repl=["bundle exec rails console"]),s&&!i&&(r.dev=["bundle exec rackup"]),r}}),he=an});var be,ln,ve,ke=a(()=>{"use strict";be=D(require("fs"),1);x();ln=y({name:"uv",actions:async n=>{let e=be.default.readdirSync(n.path),o=e.includes("pyproject.toml");return e.includes("uv.lock")||o?{install:["uv sync"]}:{}}}),ve=ln});var gn,De,Pe=a(()=>{"use strict";O();x();gn=y({name:"yarn",actions:async n=>{let e=n.rootFiles.includes("package.json"),o=n.rootFiles.includes("yarn.lock");if(!(e&&o))return{};let i=P(n)?.scripts||{};return{...Object.entries(i).map(([r,g])=>[r,`yarn run ${r}`]).reduce((r,[g,p])=>(r[g]=[p],r),{}),install:["yarn install"],outdated:["yarn outdated"]}}}),De=gn});var T,Q=a(()=>{"use strict";ge();me();ue();ye();ke();Pe();T={deno:le,npm:de,pnpm:fe,ruby:he,uv:ve,yarn:De}});var Ae,xe=a(()=>{Ae={name:"denvig",version:"0.3.0",license:"MIT",description:"A CLI tool to consistently manage cross-discipline projects",bin:{denvig:"./dist/cli.cjs"},type:"module",files:["dist/","LICENSE","README.md"],scripts:{build:"rm -rf dist && tsup","check-types":"tsc --noEmit",prepublishOnly:"npm run build",lint:"biome check","lint:fix":"biome check --fix",test:"node --test src/**/*.test.ts","test:ci":"node --test src/**/*.test.ts --reporter=default",dev:"tsc --watch"},dependencies:{minimist:"^1.2.8",yaml:"^2.4.5",zod:"^4.1.5"},devDependencies:{"@biomejs/biome":"^2.2.2","@types/minimist":"^1.2.5","@types/node":"^22",tsup:"^8.5.0",typescript:"^5.0.0"},engines:{node:">=22"},repository:{type:"git",url:"git+https://github.com/marcqualie/denvig.git"},keywords:["cli","node","developer-tools","productivity","typescript"]}});function S(){return Ae.version}var H=a(()=>{"use strict";xe()});var b,F=a(()=>{"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,o,t,s){try{return await this.handler({project:e,args:o,flags:t,extraArgs:s})}catch(i){return console.error(`Error executing command "${this.name}":`,i),{success:!1,message:"fail"}}}}});var Se={};w(Se,{runCommand:()=>dn});var Re,dn,Fe=a(()=>{"use strict";Re=require("child_process");F();H();dn=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:n,args:e,extraArgs:o=[]})=>{let t=await n.actions;if(!e.action){console.log(`Denvig v${S()}`),console.log(""),console.log("Usage: denvig run [action] [...actionArgs]"),console.log(""),console.log("Available actions:");for(let d in t){if(!t[d])continue;let r=t[d];for(let g of r){let p=g.split(`
|
|
3
|
-
`),
|
|
4
|
-
`)
|
|
5
|
-
`),
|
|
2
|
+
"use strict";var kn=Object.create;var Me=Object.defineProperty;var xn=Object.getOwnPropertyDescriptor;var Cn=Object.getOwnPropertyNames;var On=Object.getPrototypeOf,Rn=Object.prototype.hasOwnProperty;var h=(s,e)=>()=>(s&&(e=s(s=0)),e);var C=(s,e)=>{for(var t in e)Me(s,t,{get:e[t],enumerable:!0})},Nn=(s,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Cn(e))!Rn.call(s,r)&&r!==t&&Me(s,r,{get:()=>e[r],enumerable:!(n=xn(e,r))||n.enumerable});return s};var F=(s,e,t)=>(t=s!=null?kn(On(s)):{},Nn(e||!s||!s.__esModule?Me(t,"default",{value:s,enumerable:!0}):t,s));var P,Ln,_e,pt,dt=h(()=>{"use strict";P=require("zod"),Ln=["build","check-types","dev","install","lint","outdated","test"],_e=P.z.object({codeRootDir:P.z.string().optional().default("~/src").describe("The base directory where projects are stored"),quickActions:P.z.array(P.z.string()).default(Ln).optional().describe("Quick actions that are available for all projects")}),pt=P.z.object({name:P.z.string().describe("Unique identifier for the project"),actions:P.z.record(P.z.string().describe("Name of the action"),P.z.object({command:P.z.string().describe("Shell command to run for the action")})).optional().describe("Actions that can be run against the project"),quickActions:P.z.array(P.z.string()).optional().describe("Actions that are available on the CLI root for quick access"),services:P.z.record(P.z.string(),P.z.object({cwd:P.z.string().optional().describe("Working directory for the service (relative to project root)"),command:P.z.string().describe("Shell command to execute"),http:P.z.object({port:P.z.number().optional().describe("Port number the service listens on"),domain:P.z.string().optional().describe("Domain to use for the service URL"),secure:P.z.boolean().optional().describe("Use HTTPS instead of HTTP")}).optional().describe("HTTP configuration for the service URL"),envFile:P.z.string().optional().describe("Path to .env file (relative to project root)"),env:P.z.record(P.z.string(),P.z.string()).optional().describe("Environment variables"),keepAlive:P.z.boolean().optional().describe("Restart service if it exits")})).optional().describe("Service that can be managed for this project")})});var ut,An,Je,mt=h(()=>{"use strict";ut=require("fs"),An=require("fs/promises"),Je=s=>{try{return(0,ut.readFileSync)(s,"utf8").trim()||null}catch(e){if(e&&typeof e=="object"&&"code"in e&&e.code==="ENOENT")return null;throw e}}});var Z,Ge,ke,In,gt,E,ft,ue=h(()=>{"use strict";Z=require("path"),Ge=require("yaml");dt();mt();ke=(0,Z.resolve)(process.env.DENVIG_GLOBAL_CONFIG_PATH||`${process.env.HOME}/.denvig/config.yml`),In=(0,Z.resolve)(process.env.DENVIG_CODE_ROOT_DIR||`${process.env.HOME}/src`),gt={codeRootDir:In,quickActions:void 0},E=()=>{let s=Je(ke);if(s){let e=(0,Ge.parse)(s)||{};try{if(e.codeRootDir?.startsWith(".")){let t=(0,Z.dirname)(ke);e.codeRootDir=(0,Z.resolve)(`${t}/${e.codeRootDir}`)}return{..._e.parse({...gt,...e}),$sources:[ke]}}catch(t){console.error(`Error parsing global config at ${ke}:`,t),process.exit(1)}}return{..._e.parse(gt),$sources:[]}},ft=s=>{let e=E(),t={name:s,actions:{}},n=`${e.codeRootDir}/${s}/.denvig.yml`,r=Je(n);if(r)try{return{...t,...pt.parse((0,Ge.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 xe,qe=h(()=>{"use strict";xe=(s,e)=>{for(let[t,n]of Object.entries(e))s[t]||(s[t]=[]),s[t].push(...n);return s}});var Ue,V,me=h(()=>{"use strict";Ue=F(require("fs"),1),V=s=>{let e=`${s.path}/package.json`;if(!Ue.default.existsSync(e))return null;let t=Ue.default.readFileSync(e,"utf-8");return JSON.parse(t)}});var N,H=h(()=>{"use strict";N=s=>s});var M,Tn,ht,yt=h(()=>{"use strict";M=F(require("fs"),1);qe();me();H();Tn=N({name:"deno",actions:async s=>{let e=M.default.readdirSync(s.path);if(!(e.includes("deno.json")||e.includes("deno.jsonc")))return{};let r=V(s)?.scripts||{},c={...Object.entries(r).map(([o,i])=>[o,`deno ${i}`]).reduce((o,[i,l])=>(o[i]=[l],o),{}),install:["deno install"],outdated:["deno outdated"]},a=((0,M.existsSync)(`${s.path}/deno.json`)?JSON.parse((0,M.readFileSync)(`${s.path}/deno.json`,"utf8")):(0,M.existsSync)(`${s.path}/deno.jsonc`)?JSON.parse((0,M.readFileSync)(`${s.path}/deno.jsonc`,"utf8")):{}).tasks||{};return c=xe(c,{test:[a?.test?"deno task test":"deno test"],lint:[a?.lint?"deno task lint":"deno lint"],"check-types":[a?.checkTypes?"deno task check-types":"deno check"],...Object.entries(a).reduce((o,[i,l])=>(o[i]=[l.startsWith("deno")?l:`deno task ${i}`],o),{}),install:["deno install"],outdated:["deno outdated"]}),c}}),ht=Tn});var vt,Fn,bt,Dt=h(()=>{"use strict";vt=F(require("fs"),1);me();H();Fn=N({name:"npm",actions:async s=>{let e=vt.default.readdirSync(s.path),t=e.includes("package.json"),n=e.includes("package-lock.json");if(!(t&&n))return{};let p=V(s)?.scripts||{};return{...Object.entries(p).map(([o,i])=>[o,`npm run ${o}`]).reduce((o,[i,l])=>(o[i]=[l],o),{}),install:["npm install"],outdated:["npm outdated"]}}}),bt=Fn});var L,St,En,Wn,Vn,jt,Mn,_n,Jn,Pt,$t=h(()=>{"use strict";L=require("fs"),St=require("os"),En=1800*1e3,Wn=()=>{let s=`${(0,St.homedir)()}/.cache/denvig/dependencies/npm`;return(0,L.existsSync)(s)||(0,L.mkdirSync)(s,{recursive:!0}),s},Vn=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},jt=s=>{let e=Vn(s);return`${Wn()}/${e}.json`},Mn=s=>{try{let e=(0,L.statSync)(s);return Date.now()-e.mtimeMs<En}catch{return!1}},_n=s=>{let e=jt(s);if(!(0,L.existsSync)(e)||!Mn(e))return null;try{let t=(0,L.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},Jn=(s,e)=>{try{let t=jt(s);(0,L.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},Pt=async(s,e=!1)=>{if(!e){let t=_n(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],p={versions:r,latest:c};return Jn(s,p),p}catch{return null}}});var Q,Ce,Gn,qn,Un,Oe,He=h(()=>{"use strict";$t();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},Ce=(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},Gn=(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&&Ce(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 Ce(s,e.slice(2))>=0;if(e.startsWith(">")&&!e.startsWith(">="))return Ce(s,e.slice(1))>0;let n=Q(e);return n?t.major===n.major&&t.minor===n.minor&&t.patch===n.patch:!1},qn=(s,e)=>{let t=s.filter(n=>Gn(n,e)).sort(Ce);return t.length>0?t[t.length-1]:null},Un=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}},Oe=async(s,e={})=>{let t=e.cache??!0,n=[],c=s.filter(p=>p.versions.some(a=>a.source.includes("#dependencies")||a.source.includes("#devDependencies"))).map(async p=>{let a=Un(p);if(!a)return;let o=await Pt(p.name,!t);if(!o)return;let i=qn(o.versions,a.specifier),l=o.latest,d=i&&i!==a.current,m=l&&l!==a.current;(d||m)&&n.push({...p,wanted:i||a.current,latest:l,specifier:a.specifier,isDevDependency:a.isDevDependency})});return await Promise.all(c),n}});var ge,wt,ze,kt,xt,Ct=h(()=>{"use strict";ge=require("fs"),wt=require("yaml");He();me();H();ze=s=>{let e=s.indexOf("(");return e===-1?s:s.slice(0,e)},kt=N({name:"pnpm",actions:async s=>{if(!s.rootFiles.includes("pnpm-lock.yaml"))return{};let r=V(s)?.scripts||{},c=s.rootFiles.includes("pnpm-workspace.yaml");return{...Object.entries(r).map(([a,o])=>[a,`pnpm run ${a}`]).reduce((a,[o,i])=>(a[o]=[i],a),{}),install:["pnpm install"],outdated:[c?"pnpm outdated -r":"pnpm outdated"]}},dependencies:async s=>{if(!(0,ge.existsSync)(`${s.path}/pnpm-lock.yaml`))return[];let e=new Map,t=new Set,n=(a,o,i,l,d,m)=>{let u=e.get(a);u?u.versions.push({resolved:l,specifier:m,source:d}):e.set(a,{id:a,name:o,ecosystem:i,versions:[{resolved:l,specifier:m,source:d}]})};e.set("npm:pnpm",{id:"npm:pnpm",name:"pnpm",ecosystem:"system",versions:[]});let r=`${s.path}/pnpm-lock.yaml`,c=(0,ge.readFileSync)(r,"utf-8"),p=(0,wt.parse)(c);if(p?.importers)for(let[a,o]of Object.entries(p.importers)){let i=a==="."?".":a;if(o.dependencies)for(let[l,d]of Object.entries(o.dependencies))d?.specifier&&d?.version&&(t.add(l),n(`npm:${l}`,l,"npm",ze(d.version),`${i}#dependencies`,d.specifier));if(o.devDependencies)for(let[l,d]of Object.entries(o.devDependencies))d?.specifier&&d?.version&&(t.add(l),n(`npm:${l}`,l,"npm",ze(d.version),`${i}#devDependencies`,d.specifier))}if(p?.snapshots)for(let[a,o]of Object.entries(p.snapshots)){let i={...o.dependencies};for(let[l,d]of Object.entries(i))if(!t.has(l)){let m=ze(d),u=`pnpm-lock.yaml:${a}`;n(`npm:${l}`,l,"npm",m,u,m)}}return Array.from(e.values()).sort((a,o)=>a.name.localeCompare(o.name))},outdatedDependencies:async(s,e)=>{if(!(0,ge.existsSync)(`${s.path}/pnpm-lock.yaml`))return[];let t=await kt.dependencies?.(s);return t?Oe(t,e):[]}}),xt=kt});var A,Ot,Hn,zn,Bn,Rt,Yn,Kn,Zn,Nt,Lt=h(()=>{"use strict";A=require("fs"),Ot=require("os"),Hn=1800*1e3,zn=()=>{let s=`${(0,Ot.homedir)()}/.cache/denvig/dependencies/rubygems`;return(0,A.existsSync)(s)||(0,A.mkdirSync)(s,{recursive:!0}),s},Bn=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},Rt=s=>{let e=Bn(s);return`${zn()}/${e}.json`},Yn=s=>{try{let e=(0,A.statSync)(s);return Date.now()-e.mtimeMs<Hn}catch{return!1}},Kn=s=>{let e=Rt(s);if(!(0,A.existsSync)(e)||!Yn(e))return null;try{let t=(0,A.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},Zn=(s,e)=>{try{let t=Rt(s);(0,A.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},Nt=async(s,e=!1)=>{if(!e){let t=Kn(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(o=>o.number),p=n.filter(o=>!o.prerelease).map(o=>o.number)[0]||r[0],a={versions:r,latest:p};return Zn(s,a),a}catch{return null}}});var ee,X,Qn,Xn,er,At,It=h(()=>{"use strict";Lt();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},Qn=(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(),p=ee(c);return p?c.split(".").length>=3?t.major===p.major&&t.minor===p.minor&&t.patch>=p.patch:t.major===p.major&&t.minor>=p.minor&&X(s,`${p.major}.${p.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(),p=ee(c);return p?t.major===p.major&&t.minor===p.minor&&t.patch===p.patch:!1}let r=ee(n);return r?t.major===r.major&&t.minor===r.minor&&t.patch===r.patch:!1},Xn=(s,e)=>{let t=s.filter(n=>Qn(n,e)).sort(X);return t.length>0?t[t.length-1]:null},er=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}},At=async(s,e={})=>{let t=e.cache??!0,n=[],c=s.filter(p=>p.versions.some(a=>a.source.includes("#dependencies")||a.source.includes("#devDependencies"))).map(async p=>{let a=er(p);if(!a)return;let o=await Nt(p.name,!t);if(!o)return;let i=Xn(o.versions,a.specifier),l=o.latest,d=i&&i!==a.current,m=l&&l!==a.current;(d||m)&&n.push({...p,wanted:i||a.current,latest:l,specifier:a.specifier,isDevDependency:a.isDevDependency})});return await Promise.all(c),n}});var te,tr,sr,Tt,Ft=h(()=>{"use strict";te=require("fs"),tr=s=>{let e=[],t=s.split(`
|
|
3
|
+
`),n="dependencies",r=0;for(let c of t){let p=c.trim();if(p.startsWith("#")||p==="")continue;if(p.startsWith("group ")){(p.includes(":development")||p.includes(":test"))&&(n="devDependencies"),p.includes(" do")&&r++;continue}if(p==="end"){r--,r<=0&&(n="dependencies",r=0);continue}let a=p.match(/^gem\s+['"]([^'"]+)['"](?:\s*,\s*['"]([^'"]+)['"])?/);if(a){let o=a[1],i=a[2]||"*";e.push({name:o,specifier:i,group:n})}}return e},sr=s=>{let e={},t={},n=s.split(`
|
|
4
|
+
`),r="none",c=null,p=null;for(let a of n){let o=a.trimEnd();if(o==="GEM"){r="gem";continue}if(o==="PLATFORMS"){r="platforms";continue}if(o==="DEPENDENCIES"){r="dependencies";continue}if(o==="BUNDLED WITH"){r="none";continue}if(r==="gem"&&o===" specs:"){r="specs";continue}if(r==="specs"){if(o==="")continue;let i=a.match(/^(\s*)/),l=i?i[1].length:0,d=a.trim();if(l===4){let m=d.match(/^([^\s(]+)\s+\(([^)]+)\)/);if(m){let u=m[2],g=u.match(/^[\d.]+/),f=g?g[0]:u;c=m[1],p=f,e[c]||(e[c]={version:f,dependencies:{}})}}else if(l===6&&c&&p){let m=d.match(/^([^\s(]+)(?:\s+\(([^)]+)\))?/);if(m){let u=m[1],g=m[2]||"*";e[c].dependencies[u]=g}}}if(r==="dependencies"){if(o===""||o.startsWith(" ")===!1)continue;let i=o.match(/^\s+([^\s(!]+)(?:\s+\(([^)]+)\))?/);if(i){let d=i[1].replace(/!$/,""),m=i[2]||"*";t[d]=m}}}return{specs:e,dependencies:t}},Tt=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"),p=tr(c),a=(o,i,l,d,m,u)=>{let g=n.get(o);g?g.versions.push({resolved:d,specifier:u,source:m}):n.set(o,{id:o,name:i,ecosystem:l,versions:[{resolved:d,specifier:u,source:m}]})};n.set("rubygems:bundler",{id:"rubygems:bundler",name:"bundler",ecosystem:"system",versions:[]});for(let o of p)r.add(o.name);if((0,te.existsSync)(t)){let o=(0,te.readFileSync)(t,"utf-8"),i=sr(o);for(let l of p){let d=i.specs[l.name];d&&a(`rubygems:${l.name}`,l.name,"rubygems",d.version,`.#${l.group}`,l.specifier)}for(let[l,d]of Object.entries(i.specs))if(!r.has(l)){for(let[m,u]of Object.entries(i.specs))if(u.dependencies[l]){let g=`Gemfile.lock:${m}@${u.version}`,f=u.dependencies[l];a(`rubygems:${l}`,l,"rubygems",d.version,g,f)}}}else for(let o of p)a(`rubygems:${o.name}`,o.name,"rubygems",o.specifier,`.#${o.group}`,o.specifier);return Array.from(n.values()).sort((o,i)=>o.name.localeCompare(i.name))}});var Be,Et,Wt,Vt=h(()=>{"use strict";Be=F(require("fs"),1);H();It();Ft();Et=N({name:"ruby",actions:async s=>{let e=Be.default.readdirSync(s.path),t=e.includes("Gemfile"),n=e.includes("Rakefile"),r=e.includes("config.ru"),c=Be.default.existsSync(`${s.path}/config/application.rb`);if(!(t||n))return{};let a={install:["bundle install"],update:["bundle update"],outdated:["bundle outdated"]};return c&&(a.dev=["bundle exec rails server"],a.repl=["bundle exec rails console"]),r&&!c&&(a.dev=["bundle exec rackup"]),a},dependencies:async s=>s.rootFiles.includes("Gemfile")?Tt(s):[],outdatedDependencies:async(s,e)=>{if(!s.rootFiles.includes("Gemfile"))return[];let n=await Et.dependencies?.(s);return n?At(n,e):[]}}),Wt=Et});var I,Mt,nr,rr,or,_t,ir,cr,ar,Jt,Gt=h(()=>{"use strict";I=require("fs"),Mt=require("os"),nr=1800*1e3,rr=()=>{let s=`${(0,Mt.homedir)()}/.cache/denvig/dependencies/pypi`;return(0,I.existsSync)(s)||(0,I.mkdirSync)(s,{recursive:!0}),s},or=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},_t=s=>{let e=or(s);return`${rr()}/${e}.json`},ir=s=>{try{let e=(0,I.statSync)(s);return Date.now()-e.mtimeMs<nr}catch{return!1}},cr=s=>{let e=_t(s);if(!(0,I.existsSync)(e)||!ir(e))return null;try{let t=(0,I.readFileSync)(e,"utf-8");return JSON.parse(t)}catch{return null}},ar=(s,e)=>{try{let t=_t(s);(0,I.writeFileSync)(t,JSON.stringify(e),"utf-8")}catch{}},Jt=async(s,e=!1)=>{let t=s.toLowerCase().replace(/_/g,"-");if(!e){let n=cr(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(([,o])=>o.length>0).map(([o])=>o),p=r.info?.version||c[c.length-1],a={versions:c,latest:p};return ar(t,a),a}catch{return null}}});var ne,se,lr,pr,dr,ur,qt,Ut=h(()=>{"use strict";Gt();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},lr=s=>/[a-zA-Z]/.test(s),pr=(s,e)=>{let t=ne(s);if(!t||lr(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 p=r.slice(0,-2);return s.startsWith(p)}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},dr=(s,e)=>{let t=s.filter(n=>pr(n,e)).sort(se);return t.length>0?t[t.length-1]:null},ur=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}},qt=async(s,e={})=>{let t=e.cache??!0,n=[],c=s.filter(p=>p.versions.some(a=>a.source.includes("#dependencies")||a.source.includes("#devDependencies"))).map(async p=>{let a=ur(p);if(!a)return;let o=await Jt(p.name,!t);if(!o)return;let i=dr(o.versions,a.specifier),l=o.latest,d=i&&i!==a.current,m=l&&l!==a.current;(d||m)&&n.push({...p,wanted:i||a.current,latest:l,specifier:a.specifier,isDevDependency:a.isDevDependency})});return await Promise.all(c),n}});var mr,Ye,Ke,Ne,Ht,Re,Ze,zt=h(()=>{"use strict";mr=s=>{let e=s.trim();return e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'")?e.slice(1,-1):e},Ye=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):mr(e)},Ke=s=>{let e={},t=s.slice(1,-1).trim();if(!t)return e;let n=[],r="",c=0,p=!1,a="";for(let o=0;o<t.length;o++){let i=t[o];if(!p&&(i==='"'||i==="'")?(p=!0,a=i):p&&i===a&&t[o-1]!=="\\"&&(p=!1),!p){if(i==="{"||i==="[")c++;else if(i==="}"||i==="]")c--;else if(i===","&&c===0){n.push(r.trim()),r="";continue}}r+=i}r.trim()&&n.push(r.trim());for(let o of n){let i=o.indexOf("=");if(i===-1)continue;let l=o.slice(0,i).trim(),d=o.slice(i+1).trim();d.startsWith("{")?e[l]=Ke(d):d.startsWith("[")?e[l]=Ne(d):e[l]=Ye(d)}return e},Ne=s=>{let e=[],t=s.slice(1,-1).trim();if(!t)return e;let n=[],r="",c=0,p=!1,a="";for(let o=0;o<t.length;o++){let i=t[o];if(!p&&(i==='"'||i==="'")?(p=!0,a=i):p&&i===a&&t[o-1]!=="\\"&&(p=!1),!p){if(i==="{"||i==="[")c++;else if(i==="}"||i==="]")c--;else if(i===","&&c===0){n.push(r.trim()),r="";continue}}r+=i}r.trim()&&n.push(r.trim());for(let o of n){let i=o.trim();i.startsWith("{")?e.push(Ke(i)):i.startsWith("[")?e.push(Ne(i)):e.push(Ye(i))}return e},Ht=(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},Re=(s,e)=>{let t=s;for(let n of e)(!(n in t)||typeof t[n]!="object")&&(t[n]={}),t=t[n];return t},Ze=s=>{let e={},t=s.split(`
|
|
5
|
+
`),n=[],r=null,c=null,p=null,a=null;for(let o=0;o<t.length;o++){let i=t[o];if(p!==null&&a!==null){if(p+=i,i.includes("]")){let f=0,y=-1;for(let v=0;v<p.length;v++)if(p[v]==="[")f++;else if(p[v]==="]"&&(f--,f===0)){y=v;break}if(y!==-1){let v=p.slice(0,y+1),D=Ne(v);if(c)c[a]=D;else{let w=[...n,a];Ht(e,w,D)}p=null,a=null}}continue}let l=i.indexOf("#");if(l!==-1){let f=!1,y="";for(let v=0;v<l;v++){let D=i[v];!f&&(D==='"'||D==="'")?(f=!0,y=D):f&&D===y&&i[v-1]!=="\\"&&(f=!1)}f||(i=i.slice(0,l))}if(i=i.trim(),!i)continue;if(i.startsWith("[[")&&i.endsWith("]]")){if(c&&r){let f=Re(e,r.slice(0,-1)),y=r[r.length-1];Array.isArray(f[y])||(f[y]=[]),f[y].push(c)}r=i.slice(2,-2).split("."),c={},n=[];continue}if(i.startsWith("[")&&i.endsWith("]")){if(c&&r){let f=Re(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=i.slice(1,-1).split("."),Re(e,n);continue}let d=i.indexOf("=");if(d===-1)continue;let m=i.slice(0,d).trim(),u=i.slice(d+1).trim();if(u.startsWith("[")&&!u.endsWith("]")){p=u,a=m;continue}let g;if(u.startsWith("{")?g=Ke(u):u.startsWith("[")?g=Ne(u):g=Ye(u),c)c[m]=g;else{let f=[...n,m];Ht(e,f,g)}}if(c&&r){let o=Re(e,r.slice(0,-1)),i=r[r.length-1];Array.isArray(o[i])||(o[i]=[]),o[i].push(c)}return e}});var re,fe,Qe,gr,fr,Bt,Yt=h(()=>{"use strict";re=require("fs");zt();fe=s=>s.toLowerCase().replace(/_/g,"-"),Qe=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:"*"}},gr=s=>{let e=[];try{let t=Ze(s);if(t.project?.dependencies)for(let n of t.project.dependencies){let{name:r,specifier:c}=Qe(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}=Qe(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:p}=Qe(r);e.push({name:c,specifier:p,group:"devDependencies"})}}catch{}return e},fr=s=>{let e={},t=null;try{let n=Ze(s);if(n.package)for(let r of n.package){let c=fe(r.name);r.source?.virtual&&(t=c);let p=r.dependencies?.map(a=>fe(a.name))||[];e[c]={name:r.name,version:r.version,dependencies:p}}}catch{}return{packages:e,projectName:t}},Bt=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=(o,i,l,d,m,u)=>{let g=n.get(o);g?g.versions.push({resolved:d,specifier:u,source:m}):n.set(o,{id:o,name:i,ecosystem:l,versions:[{resolved:d,specifier:u,source:m}]})};n.set("pypi:uv",{id:"pypi:uv",name:"uv",ecosystem:"system",versions:[]});let p=(0,re.readFileSync)(e,"utf-8"),a=gr(p);for(let o of a)r.add(fe(o.name));if((0,re.existsSync)(t)){let o=(0,re.readFileSync)(t,"utf-8"),i=fr(o);for(let l of a){let d=fe(l.name),m=i.packages[d];m&&c(`pypi:${d}`,m.name,"pypi",m.version,`.#${l.group}`,l.specifier)}for(let[l,d]of Object.entries(i.packages))if(!(l===i.projectName||r.has(l))){for(let[,m]of Object.entries(i.packages))if(m.dependencies.includes(l)){let u=`uv.lock:${m.name}@${m.version}`;c(`pypi:${l}`,d.name,"pypi",d.version,u,"*")}}}else for(let o of a){let i=fe(o.name);c(`pypi:${i}`,o.name,"pypi",o.specifier,`.#${o.group}`,o.specifier)}return Array.from(n.values()).sort((o,i)=>o.name.localeCompare(i.name))}});var Kt,Zt,Qt,Xt=h(()=>{"use strict";Kt=F(require("fs"),1);H();Ut();Yt();Zt=N({name:"uv",actions:async s=>{let e=Kt.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");return!e&&!t?[]:Bt(s)},outdatedDependencies:async(s,e)=>{if(!s.rootFiles.includes("pyproject.toml"))return[];let n=await Zt.dependencies?.(s);return n?qt(n,e):[]}}),Qt=Zt});var hr,es,ts=h(()=>{"use strict";hr=s=>{let e=s.split(`
|
|
6
|
+
|
|
7
|
+
`),t={};for(let n of e){let r=n.split(`
|
|
8
|
+
`);if(r.length<3)continue;let c=r[0].split(",").map(l=>l.trim().replace(/"|:/g,"")),p=r[1]?.match(/version "(.+)"/)?.[1],a=r[2]?.match(/resolved "(.+)"/)?.[1];if(!p||!a)continue;let o={},i=!1;for(let l=3;l<r.length;l++){let d=r[l];if(d.trim()==="dependencies:"){i=!0;continue}if(i&&d.startsWith(" ")){let m=d.trim().match(/^"?([^"\s]+)"?\s+"?([^"]+)"?$/);m&&(o[m[1]]=m[2])}else i&&!d.startsWith(" ")&&(i=!1)}for(let l of c)l&&(t[l]={version:p,resolved:a,dependencies:Object.keys(o).length>0?o:void 0})}return{type:"success",object:t}},es=s=>{let e={},t=hr(s),n=new Map;for(let[r,c]of Object.entries(t.object)){let p=/^(@?.+)@(.+)$/,[,a,o]=r.match(p)||[];a&&(n.has(a)||n.set(a,[]),n.get(a)?.push({version:c.version,specifier:o,deps:c.dependencies}))}for(let[r,c]of n.entries()){e[r]||(e[r]={versions:{}});for(let p of c)e[r].versions[p.version]||(e[r].versions[p.version]={}),e[r].versions[p.version]["yarn.lock"]=p.specifier;e[r].versions=Object.fromEntries(Object.entries(e[r].versions).sort((p,a)=>p[0].localeCompare(a[0],void 0,{numeric:!0})))}for(let[r,c]of n.entries())for(let p of c){if(!p.deps)continue;let a=`${r}@${p.version}`;for(let[o,i]of Object.entries(p.deps)){e[o]||(e[o]={versions:{}});let l=n.get(o);if(!l)continue;let m=l.find(u=>u.specifier===i)?.version||l[0]?.version;if(m){e[o].versions[m]||(e[o].versions[m]={});let u=`yarn.lock:${a}`;e[o].versions[m][u]=i}}}return{dependencies:e}}});function yr(s){return s.includes("__metadata:")}function vr(s){let e=s.match(/^(.+)@npm:/);if(e)return e[1];let t=s.lastIndexOf("@");return t>0?s.slice(0,t):s}var z,ss,ns,rs,os=h(()=>{"use strict";z=require("fs"),ss=require("yaml");He();me();ts();H();ns=N({name:"yarn",actions:async s=>{let e=s.rootFiles.includes("package.json"),t=s.rootFiles.includes("yarn.lock");if(!(e&&t))return{};let c=V(s)?.scripts||{};return{...Object.entries(c).map(([a,o])=>[a,`yarn run ${a}`]).reduce((a,[o,i])=>(a[o]=[i],a),{}),install:["yarn install"],outdated:["yarn outdated"]}},dependencies:async s=>{let e=`${s.path}/yarn.lock`,t=`${s.path}/package.json`;if(!(0,z.existsSync)(e)||!(0,z.existsSync)(t))return[];let n=new Map,r=new Set,c=(u,g,f,y,v,D)=>{let w=n.get(u);w?w.versions.push({resolved:y,specifier:D,source:v}):n.set(u,{id:u,name:g,ecosystem:f,versions:[{resolved:y,specifier:D,source:v}]})};n.set("npm:yarn",{id:"npm:yarn",name:"yarn",ecosystem:"system",versions:[]});let p=(0,z.readFileSync)(e,"utf-8"),a=yr(p),o=new Map,i=new Map,l=null;if(a){let u=(0,ss.parse)(p);for(let[g,f]of Object.entries(u)){if(g==="__metadata"||!f?.version||typeof f.version!="string")continue;let y=vr(g),v=f;o.has(y)||o.set(y,new Map);let D=g.match(/@npm:(.+)$/);D&&o.get(y)?.set(D[1],f.version),v.dependencies&&i.set(`${y}@${v.version}`,v.dependencies)}}else{l=es(p);for(let[u,g]of Object.entries(l.dependencies)){o.has(u)||o.set(u,new Map);for(let[f,y]of Object.entries(g.versions)){let v=y["yarn.lock"];v&&o.get(u)?.set(v,f)}}}let d=[t],m=s.findFilesByName("package.json");d.push(...m);for(let u of d)try{let g=(0,z.readFileSync)(u,"utf-8"),f=JSON.parse(g),y=".";u!==t&&(y=u.replace(`${s.path}/`,"").replace("/package.json",""));let v=(D,w)=>{if(D)for(let[R,T]of Object.entries(D)){r.add(R);let le=o.get(R),K=T;if(le){let De=le.get(T);if(De)K=De;else{let Se=le.values().next().value;Se&&(K=Se)}}c(`npm:${R}`,R,"npm",K,`${y}#${w}`,T)}};v(f.dependencies,"dependencies"),v(f.devDependencies,"devDependencies")}catch{}if(a){for(let[u,g]of i.entries())for(let[f,y]of Object.entries(g))if(!r.has(f)){let v=o.get(f),D=y;if(v){let R=v.get(y);if(R)D=R;else{let T=v.values().next().value;T&&(D=T)}}let w=`yarn.lock:${u}`;c(`npm:${f}`,f,"npm",D,w,y)}}else if(l){for(let[u,g]of Object.entries(l.dependencies))if(!r.has(u))for(let[f,y]of Object.entries(g.versions))for(let[v,D]of Object.entries(y))v.startsWith("yarn.lock:")&&c(`npm:${u}`,u,"npm",f,v,D)}return Array.from(n.values()).sort((u,g)=>u.name.localeCompare(g.name))},outdatedDependencies:async(s,e)=>{if(!(0,z.existsSync)(`${s.path}/yarn.lock`))return[];let t=await ns.dependencies?.(s);return t?Oe(t,e):[]}}),rs=ns});var _,he=h(()=>{"use strict";yt();Dt();Ct();Vt();Xt();os();_={deno:ht,npm:bt,pnpm:xt,ruby:Wt,uv:Qt,yarn:rs}});var is,cs=h(()=>{"use strict";he();qe();is=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(_)){let r=await n.actions(s);e=xe(e,r)}return e}});var k,br,Dr,ni,Sr,as,ls=h(()=>{"use strict";k=require("zod");he();br=k.z.object({resolved:k.z.string().describe("The resolved version of the dependency"),specifier:k.z.string().describe("The version constraint/specifier used"),source:k.z.string().describe("The source file/path of the dependency"),wanted:k.z.string().describe("The wanted version based on semver rules").optional(),latest:k.z.string().describe("The latest available version of the dependency").optional()}),Dr=k.z.object({id:k.z.string().describe("Unique identifier for the ecosystem / dependency"),name:k.z.string().describe("Name of the dependency"),versions:k.z.array(br).describe("Map of resolved versions to sources. Each source maps a package path to its version specifier."),ecosystem:k.z.string().describe("Ecosystem of the dependency (e.g., npm, rubygems, pip)")}),ni=Dr.extend({wanted:k.z.string().describe("Latest version compatible with the specifier (semver)"),latest:k.z.string().describe("Absolute latest version available"),specifier:k.z.string().describe("The version specifier from package manifest"),isDevDependency:k.z.boolean().describe("Whether this is a dev dependency")}),Sr=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())},as=async s=>{let e=[];for(let[t,n]of Object.entries(_)){let r=n.dependencies?await n.dependencies(s):[];e.push(...r)}return Sr(e)}});var Xe,J,Le=h(()=>{"use strict";Xe=F(require("fs"),1);cs();ue();ls();he();J=class{slug;config;constructor(e){this.slug=e,this.config=ft(e)}get name(){return this.config.name}get path(){return`${E().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 as(this)}async outdatedDependencies(e){let t=[];for(let n of Object.values(_))if(n.outdatedDependencies){let r=await n.outdatedDependencies(this,e);t.push(...r)}return t}get actions(){return is(this)}get rootFiles(){return Xe.default.readdirSync(this.path)}findFilesByName(e){let t=[],n=r=>{let c=Xe.default.readdirSync(r,{withFileTypes:!0});for(let p of c)p.isDirectory()?p.name!=="node_modules"&&n(`${r}/${p.name}`):p.name===e&&t.push(`${r}/${p.name}`)};return n(this.path),t}}});var ds,ps=h(()=>{ds={name:"denvig",version:"0.4.0",license:"MIT",description:"A CLI tool to consistently manage cross-discipline projects",bin:{denvig:"./dist/cli.cjs"},type:"module",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",yaml:"^2.8.2",zod:"^4.3.5"},devDependencies:{"@biomejs/biome":"^2.3.11","@types/minimist":"^1.2.5","@types/node":"^24",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 ds.version}var Ae=h(()=>{"use strict";ps()});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 ms={};C(ms,{runCommand:()=>Pr});var us,Pr,gs=h(()=>{"use strict";us=require("child_process");x();Ae();Pr=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 p in n){if(!n[p])continue;let a=n[p];for(let o of a){let i=o.split(`
|
|
9
|
+
`),l=i[0],d=i.slice(1);console.log(` ${p}: ${l}`);for(let m of d)m.trim()&&console.log(`${" ".repeat(p.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 p of r){let a=`${p} ${t.join(" ")}`.trim();console.log(`$ ${a}`);let o={...process.env,DENVIG_PROJECT:s.slug},i=process.stdout.isTTY&&process.stdin.isTTY,l,d;i?process.platform==="darwin"?(l="script",d=["-q","/dev/null","sh","-c",a]):(l="script",d=["-q","-c",a,"/dev/null"]):(l="sh",d=["-c",a]);let m=(0,us.spawn)(l,d,{cwd:s.path,env:o,stdio:"inherit"}),u=await new Promise(g=>{m.on("close",f=>{g({success:f===0})})});u.success||(c=u)}return c}})});var Ie,fs=h(()=>{"use strict";Ie=s=>s.replace(process.env.HOME||"/root","~")});var vs={};C(vs,{configCommand:()=>$r});var ys,hs,$r,bs=h(()=>{"use strict";ys=require("yaml");x();ue();fs();hs=s=>{let e=Object.fromEntries(Object.entries({...s,$sources:void 0}).filter(([t,n])=>n!==void 0));(0,ys.stringify)(e,{indent:2,lineWidth:80}).trim().split(`
|
|
10
|
+
`).map(t=>console.log(` ${Ie(t)}`))},$r=new b({name:"config",description:"Display the current global and project configuration.",usage:"config",example:"config",args:[],flags:[],handler:({project:s})=>{let e=E(),t=s.config;return console.log("Denvig Config"),console.log(""),console.log(`Global: ${e.$sources.map(n=>Ie(n)).join(", ")||"default"}`),hs(e),console.log(""),console.log(`Project: ${s.config.$sources.map(n=>Ie(n)).join(", ")||"default"}`),console.log(` slug: ${s.slug}`),hs(t),{success:!0,message:"Configuration displayed."}}})});var Ds={};C(Ds,{pluginsCommand:()=>wr});var wr,Ss=h(()=>{"use strict";x();he();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(_)){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 js={};C(js,{versionCommand:()=>kr});var kr,Ps=h(()=>{"use strict";x();Ae();kr=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 $s={};C($s,{infoCommand:()=>xr});var xr,ws=h(()=>{"use strict";x();xr=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 p=JSON.parse(c.readFileSync(r,"utf-8"));p.repository?.url&&(e=p.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 $,ie,ks,ce,ye=h(()=>{"use strict";$={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,""),ks=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(i=>i.visible!==!1);if(t.length===0||r.length===0)return[];let c=r.map((i,l)=>{let d=i.header.length,m=Math.max(...t.map(u=>{let g=i.accessor(u);if(n&&l===0){let f={depth:n.getDepth(u),isLast:n.getIsLast(u),hasChildren:n.getHasChildren(u),parentPath:n.getParentPath(u)};g=ks(f)+ie(g)}return ie(g).length}));return Math.max(d,m)}),p=[],a=r.map((i,l)=>i.header.padEnd(c[l]));p.push(a.join(" "));let o=c.reduce((i,l)=>i+l,0)+(r.length-1)*2;p.push("-".repeat(o));for(let i of t){let d=(n?n.getDepth(i):0)>0,m=r.map((u,g)=>{let f=u.accessor(i),y=c[g];if(n&&g===0){let w={depth:n.getDepth(i),isLast:n.getIsLast(i),hasChildren:n.getHasChildren(i),parentPath:n.getParentPath(i)},R=ks(w),T=d?`${$.grey}${ie(f)}${$.reset}`:f;f=R+T}else if(d&&!u.format){let w=ie(f);w.trim()&&(f=`${$.grey}${w}${$.reset}`)}let v=ie(f).length,D=y-v;if(u.format){let R=ie(f).padEnd(y);return u.format(R,i)}return f+" ".repeat(Math.max(0,D))});p.push(m.join(" "))}return p}});var ve,xs,Cs=h(()=>{"use strict";ve=F(require("fs"),1);ue();xs=()=>{let e=E().codeRootDir,t=[];if(!ve.default.existsSync(e))return t;let n=ve.default.readdirSync(e,{withFileTypes:!0});for(let r of n){if(!r.isDirectory()||r.name.startsWith("."))continue;let c=`${e}/${r.name}`,p=ve.default.readdirSync(c,{withFileTypes:!0});for(let a of p){if(!a.isDirectory()||a.name.startsWith("."))continue;let i=`${`${c}/${a.name}`}/.denvig.yml`;ve.default.existsSync(i)&&t.push(`${r.name}/${a.name}`)}}return t.sort()}});function Cr(s){let e={},t=s.split(`
|
|
11
|
+
`);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 p=r.slice(0,c).trim(),a=r.slice(c+1).trim();(a.startsWith('"')&&a.endsWith('"')||a.startsWith("'")&&a.endsWith("'"))&&(a=a.slice(1,-1)),p&&(e[p]=a)}return e}async function Rs(s){try{let e=await(0,Os.readFile)(s,"utf-8");return Cr(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 Os,Ns=h(()=>{"use strict";Os=require("fs/promises")});function Te(){return`gui/${process.getuid?.()??501}`}async function Or(s){try{let e=Te(),{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 Rr(s){try{let e=Te(),{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 Nr(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 Lr(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 Ar(s){try{let e=Te(),{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 Ir(s){try{let{stdout:e}=await ae("launchctl list"),n=e.trim().split(`
|
|
12
|
+
`).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 Ls,As,ae,G,Is=h(()=>{"use strict";Ls=require("child_process"),As=require("util"),ae=(0,As.promisify)(Ls.exec);G={bootstrap:Or,bootout:Rr,start:Nr,stop:Lr,print:Ar,list:Ir,getUserDomain:Te}});function B(s){return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function Ts(s){let{label:e,command:t,workingDirectory:n,environmentVariables:r={},standardOutPath:c,standardErrorPath:p,keepAlive:a}=s,o=Object.entries(r).map(([i,l])=>` <key>${B(i)}</key>
|
|
13
|
+
<string>${B(l)}</string>`).join(`
|
|
14
|
+
`);return`<?xml version="1.0" encoding="UTF-8"?>
|
|
15
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
16
|
+
<plist version="1.0">
|
|
17
|
+
<dict>
|
|
18
|
+
<key>Label</key>
|
|
19
|
+
<string>${B(e)}</string>
|
|
20
|
+
|
|
21
|
+
<key>ProgramArguments</key>
|
|
22
|
+
<array>
|
|
23
|
+
<string>/bin/zsh</string>
|
|
24
|
+
<string>-l</string>
|
|
25
|
+
<string>-c</string>
|
|
26
|
+
<string>${B(t.trim())}</string>
|
|
27
|
+
</array>
|
|
28
|
+
|
|
29
|
+
<key>WorkingDirectory</key>
|
|
30
|
+
<string>${B(n)}</string>
|
|
31
|
+
|
|
32
|
+
<key>EnvironmentVariables</key>
|
|
33
|
+
<dict>
|
|
34
|
+
${o}
|
|
35
|
+
</dict>
|
|
36
|
+
|
|
37
|
+
<key>StandardOutPath</key>
|
|
38
|
+
<string>${B(c)}</string>
|
|
39
|
+
|
|
40
|
+
<key>StandardErrorPath</key>
|
|
41
|
+
<string>${B(p)}</string>
|
|
42
|
+
|
|
43
|
+
<key>KeepAlive</key>
|
|
44
|
+
<${a?"true":"false"}/>
|
|
45
|
+
|
|
46
|
+
<key>RunAtLoad</key>
|
|
47
|
+
<false/>
|
|
48
|
+
</dict>
|
|
49
|
+
</plist>
|
|
50
|
+
`}var Fs=h(()=>{"use strict"});var W,et,q,O,Y=h(()=>{"use strict";W=require("fs/promises"),et=require("os"),q=require("path");Ns();Is();Fs();O=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),p=this.resolveServiceCwd(t),a={DENVIG_PROJECT:this.project.slug,DENVIG_SERVICE:e};if(t.envFile)try{let i=(0,q.resolve)(this.project.path,t.envFile),l=await Rs(i);Object.assign(a,l)}catch(i){let l=i instanceof Error?i.message:"Unknown error";return{name:e,success:!1,message:`Failed to load environment file: ${l}`}}t.env&&Object.assign(a,t.env),t.http?.port!==void 0&&(a.PORT=t.http.port.toString());let o=Ts({label:n,command:t.command,workingDirectory:p,environmentVariables:a,standardOutPath:this.getLogPath(e,"stdout"),standardErrorPath:this.getLogPath(e,"stderr"),keepAlive:t.keepAlive??!0});if(await(0,W.writeFile)(c,o,"utf-8"),r){let i=await G.bootout(n);if(!i.success)return{name:e,success:!1,message:`Failed to bootout service: ${i.output}`};await new Promise(d=>setTimeout(d,1e3));let l=await G.bootstrap(c);if(!l.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${l.output}`}}else{let i=await G.bootstrap(c);if(!i.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${i.output}`}}try{let i=new Date().toISOString();await(0,W.appendFile)(this.getLogPath(e,"stdout"),`[${i}] Service Started
|
|
51
|
+
`,"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 G.bootout(n);if(!c.success)return{name:e,success:!1,message:`Failed to stop service: ${c.output}`};try{let p=new Date().toISOString();await(0,W.appendFile)(this.getLogPath(e,"stdout"),`[${p}] Service Stopped
|
|
52
|
+
`,"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 G.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=[];for(let n of Object.keys(e))t.push(await this.startService(n));return t}async stopAll(){let e=this.project.config.services||{},t=[];for(let n of Object.keys(e))await this.isServiceBootstrapped(n)&&t.push(await this.stopService(n));return t}async restartAll(){let e=this.project.config.services||{},t=[];for(let n of Object.keys(e))await this.isServiceBootstrapped(n)&&t.push(await this.restartService(n));return t}async isServiceBootstrapped(e){let t=this.getServiceLabel(e);return await G.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,q.resolve)((0,et.homedir)(),".denvig")}getPlistPath(e){let t=this.getServiceLabel(e);return(0,q.resolve)((0,et.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,q.resolve)(this.getDenvigHomeDir(),"logs",`${n}__${r}${c}.log`)}async ensureDenvigDirectories(){let e=this.getDenvigHomeDir();await(0,W.mkdir)((0,q.resolve)(e,"logs"),{recursive:!0})}async getRecentLogs(e,t){try{let n=this.getLogPath(e,"stdout");return(await(0,W.readFile)(n,"utf-8")).trim().split(`
|
|
53
|
+
`).slice(-t)}catch{return[]}}resolveServiceCwd(e){return(0,q.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 getServiceResponse(e,t){let n=this.getServiceConfig(e);if(!n)return null;let r=this.getServiceLabel(e),c=await G.print(r),p="stopped",a=null,o=null;c&&(a=c.pid??null,o=c.lastExitCode??null,c.state==="running"&&(o!==null&&o!==0?p="error":p="running"));let i={name:e,project:this.project.slug,status:p,pid:a,url:this.getServiceUrl(e),command:n.command,cwd:this.resolveServiceCwd(n),logPath:this.getLogPath(e,"stdout"),envFile:n.envFile?(0,q.resolve)(this.project.path,n.envFile):null,lastExitCode:o};return t?.includeLogs&&(i.logs=await this.getRecentLogs(e,t.logLines??20)),i}}});var Es={};C(Es,{servicesCommand:()=>Fr});var Tr,Fr,Ws=h(()=>{"use strict";x();ye();Le();Cs();Y();Tr=s=>{switch(s){case"running":return"\u{1F7E2}";case"error":return"\u{1F534}";default:return"\u25EF"}},Fr=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=xs();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=[];for(let o of r){let i=new J(o),l=new O(i),d=await l.listServices();for(let m of d){let u=await l.getServiceResponse(m.name);u&&c.push(u)}}if(c.length===0)return console.log(t==="json"?JSON.stringify([]):"No services configured across any project."),{success:!0,message:"No services configured."};let p=c.sort((o,i)=>{let l=o.project===n,d=i.project===n;if(l&&!d)return-1;if(!l&&d)return 1;let m=o.project.localeCompare(i.project);return m!==0?m:o.name.localeCompare(i.name)});if(t==="json")return console.log(JSON.stringify(p)),{success:!0,message:"Services listed successfully."};let a=ce({columns:[{header:"",accessor:o=>Tr(o.status)},{header:"Project",accessor:o=>o.project},{header:"Name",accessor:o=>o.name},{header:"URL",accessor:o=>o.url||"-"}],data:p});for(let o of a)console.log(o);return console.log(""),console.log(`${c.length} service${c.length===1?"":"s"} configured across ${r.length} project${r.length===1?"":"s"}`),{success:!0,message:"Services listed successfully."}}})});var Er,U,be=h(()=>{"use strict";Le();Y();Er=(s,e)=>{if(!s.includes("/"))return{projectSlug:e,serviceName:s};let t=s.split("/"),n=t.pop();return{projectSlug:t.join("/"),serviceName:n}},U=(s,e)=>{let{projectSlug:t,serviceName:n}=Er(s,e.slug),r=t===e.slug?e:new J(t),c=new O(r);return{project:r,manager:c,serviceName:n}}});var Ms={};C(Ms,{servicesStartCommand:()=>Wr});var Vs,Wr,_s=h(()=>{"use strict";Vs=require("zod");x();be();Y();Wr=new b({name:"services:start",description:"Start all services or a specific service",usage:"services start [name] [--format table|json]",example:"services start api or services start marcqualie/api/dev",args:[{name:"name",description:"Service name or project/service path (e.g., hello or marcqualie/api/dev)",required:!1,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=Vs.z.string().parse(e.name),r=t.format;if(n){let{manager:l,serviceName:d,project:m}=U(n,s),u=m.slug!==s.slug?`${m.slug}/`:"";r!=="json"&&console.log(`Starting ${u}${d}...`);let g=await l.startService(d);if(!g.success)return r==="json"?console.log(JSON.stringify({success:!1,service:d,project:m.slug,message:g.message})):console.error(`\u2717 Failed to start ${u}${d}: ${g.message}`),{success:!1,message:g.message};await new Promise(y=>setTimeout(y,2e3));let f=await l.getServiceResponse(d,{includeLogs:!0});if(f?.status==="running"){if(r==="json")console.log(JSON.stringify(f));else{let y=f.url?` \u2192 ${f.url}`:"";console.log(`\u2713 ${u}${d} started successfully${y}`)}return{success:!0,message:"Service started successfully."}}if(r==="json")console.log(JSON.stringify(f));else if(console.error(`\u2717 ${u}${d} failed to start`),f?.logs&&f.logs.length>0){console.error(""),console.error("Recent logs:");for(let y of f.logs)console.error(` ${y}`)}return{success:!1,message:"Service failed to start."}}let c=new O(s);if((await c.listServices()).length===0)return console.log(r==="json"?JSON.stringify({success:!0,project:s.slug,services:[]}):"No services configured in this project."),{success:!0,message:"No services to start."};let a=await c.startAll();await new Promise(l=>setTimeout(l,2e3));let o=[],i=!1;for(let l of a){let d=await c.getServiceResponse(l.name,{includeLogs:!l.success});if(d){if(o.push(d),!l.success||d.status!=="running"){if(i=!0,r!=="json"){if(!l.success)console.error(`Starting ${l.name}... \u2717`),console.error(` ${l.message}`);else if(console.error(`Starting ${l.name}... \u2717 (failed to start)`),d.logs&&d.logs.length>0){console.error(" Recent logs:");for(let m of d.logs.slice(-3))console.error(` ${m}`)}}}else if(r!=="json"){let m=d.url?` \u2192 ${d.url}`:"";console.log(`Starting ${l.name}... \u2713${m}`)}}}return r==="json"?console.log(JSON.stringify({success:!i,project:s.slug,services:o})):(console.log(""),console.log(i?"Some services failed to start":"All services started successfully")),i?{success:!1,message:"Some services failed to start."}:{success:!0,message:"All services started successfully."}}})});var Js={};C(Js,{servicesStopCommand:()=>Vr});var Vr,Gs=h(()=>{"use strict";x();be();Y();Vr=new b({name:"services:stop",description:"Stop all services or a specific service",usage:"services stop [name] [--format table|json]",example:"services stop api or services stop marcqualie/api/dev",args:[{name:"name",description:"Service name or project/service path (e.g., hello or marcqualie/api/dev)",required:!1,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=t.format;if(typeof e.name=="string"&&e.name){let{manager:o,serviceName:i,project:l}=U(e.name,s),d=l.slug!==s.slug?`${l.slug}/`:"";n!=="json"&&console.log(`Stopping ${d}${i}...`);let m=await o.stopService(i);if(!m.success)return n==="json"?console.log(JSON.stringify({success:!1,service:i,project:l.slug,message:m.message})):console.error(`\u2717 Failed to stop ${d}${i}: ${m.message}`),{success:!1,message:m.message};let u=await o.getServiceResponse(i);return console.log(n==="json"?JSON.stringify(u):`\u2713 ${d}${i} stopped successfully`),{success:!0,message:"Service stopped successfully."}}let r=new O(s),c=await r.stopAll();if(c.length===0)return console.log(n==="json"?JSON.stringify({success:!0,project:s.slug,services:[]}):"No running services to stop."),{success:!0,message:"No services to stop."};let p=[],a=!1;for(let o of c){let i=await r.getServiceResponse(o.name);i&&(p.push(i),o.success?n!=="json"&&console.log(`Stopping ${o.name}... \u2713`):(a=!0,n!=="json"&&(console.error(`Stopping ${o.name}... \u2717`),console.error(` ${o.message}`))))}return n==="json"?console.log(JSON.stringify({success:!a,project:s.slug,services:p})):(console.log(""),console.log(a?"Some services failed to stop":"All services stopped successfully")),a?{success:!1,message:"Some services failed to stop."}:{success:!0,message:"All services stopped successfully."}}})});var Us={};C(Us,{servicesRestartCommand:()=>Mr});var qs,Mr,Hs=h(()=>{"use strict";qs=require("zod");x();be();Y();Mr=new b({name:"services:restart",description:"Restart all services or a specific service",usage:"services restart [name] [--format table|json]",example:"services restart api or services restart marcqualie/api/dev",args:[{name:"name",description:"Service name or project/service path (e.g., hello or marcqualie/api/dev)",required:!1,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=qs.z.string().parse(e.name),r=t.format;if(n){let{manager:i,serviceName:l,project:d}=U(n,s),m=d.slug!==s.slug?`${d.slug}/`:"";r!=="json"&&console.log(`Restarting ${m}${l}...`);let u=await i.restartService(l);if(!u.success)return r==="json"?console.log(JSON.stringify({success:!1,service:l,project:d.slug,message:u.message})):console.error(`\u2717 Failed to restart ${m}${l}: ${u.message}`),{success:!1,message:u.message};await new Promise(f=>setTimeout(f,2e3));let g=await i.getServiceResponse(l,{includeLogs:!0});if(g?.status==="running"){if(r==="json")console.log(JSON.stringify(g));else{let f=g.url?` \u2192 ${g.url}`:"";console.log(`\u2713 ${m}${l} restarted successfully${f}`)}return{success:!0,message:"Service restarted successfully."}}if(r==="json")console.log(JSON.stringify(g));else if(console.error(`\u2717 ${m}${l} failed to start`),g?.logs&&g.logs.length>0){console.error(""),console.error("Recent logs:");for(let f of g.logs)console.error(` ${f}`)}return{success:!1,message:"Service failed to start."}}let c=new O(s),p=await c.restartAll();if(p.length===0)return console.log(r==="json"?JSON.stringify({success:!0,project:s.slug,services:[]}):"No running services to restart."),{success:!0,message:"No services to restart."};await new Promise(i=>setTimeout(i,2e3));let a=[],o=!1;for(let i of p){let l=await c.getServiceResponse(i.name,{includeLogs:!i.success});if(l){if(a.push(l),!i.success||l.status!=="running"){if(o=!0,r!=="json"){if(!i.success)console.error(`Restarting ${i.name}... \u2717`),console.error(` ${i.message}`);else if(console.error(`Restarting ${i.name}... \u2717 (failed to start)`),l.logs&&l.logs.length>0){console.error(" Recent logs:");for(let d of l.logs.slice(-3))console.error(` ${d}`)}}}else if(r!=="json"){let d=l.url?` \u2192 ${l.url}`:"";console.log(`Restarting ${i.name}... \u2713${d}`)}}}return r==="json"?console.log(JSON.stringify({success:!o,project:s.slug,services:a})):(console.log(""),console.log(o?"Some services failed to restart":"All services restarted successfully")),o?{success:!1,message:"Some services failed to restart."}:{success:!0,message:"All services restarted successfully."}}})});var Ys={};C(Ys,{servicesStatusCommand:()=>_r});var zs,Fe,Bs,_r,Ks=h(()=>{"use strict";zs=require("fs"),Fe=require("os"),Bs=require("zod");x();be();_r=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/api/dev",args:[{name:"name",description:"Service name or project/service path (e.g., hello or marcqualie/api/dev)",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:p,project:a}=U(n,s),o=await c.getServiceResponse(p,{includeLogs:!0});if(!o){let m=a.slug!==s.slug?` in project "${a.slug}"`:"";return r==="json"?console.log(JSON.stringify({success:!1,service:p,project:a.slug,message:`Service "${p}" not found in configuration${m}`})):console.error(`Service "${p}" not found in configuration${m}`),{success:!1,message:`Service "${p}" not found.`}}if(r==="json")return console.log(JSON.stringify(o)),{success:!0,message:"Status retrieved successfully."};let i=a.slug!==s.slug?`${a.slug}/`:"",l=o.status==="running"?"Running":o.status==="error"?"Error":"Stopped";console.log(`Service: ${i}${o.name}`),console.log(`Status: ${l}`),o.status==="running"&&o.pid&&console.log(`PID: ${o.pid}`),console.log(`Command: ${o.command}`),console.log(`CWD: ${o.cwd.replace((0,Fe.homedir)(),"~")}`),console.log(`Logs: ${o.logPath.replace((0,Fe.homedir)(),"~")}`);let d=c.getPlistPath(p);if((0,zs.existsSync)(d)&&console.log(`Plist: ${d.replace((0,Fe.homedir)(),"~")}`),o.lastExitCode!==null&&o.lastExitCode!==0&&o.status!=="running"&&console.log(`Last exit code: ${o.lastExitCode}`),o.logs&&o.logs.length>0){console.log(""),console.log("Recent logs (last 10 lines):");for(let m of o.logs.slice(-10))console.log(` ${m}`)}return{success:!0,message:"Status retrieved successfully."}}})});var Xs={};C(Xs,{logsCommand:()=>Jr});var Zs,Qs,Jr,en=h(()=>{"use strict";Zs=require("child_process"),Qs=require("fs/promises");x();Y();Jr=new b({name:"logs",description:"Show logs for a service",usage:"logs <name> [-n <lines>] [--follow]",example:"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 O(s),r=e.name,c=t.lines??t.n??10,p=!!t.follow,a=n.getLogPath(r,"stdout");if(p){let o=["-n",`${c}`,"-f",a];return(0,Zs.spawn)("tail",o,{stdio:"inherit"}),new Promise(()=>{})}try{let l=(await(0,Qs.readFile)(a,"utf-8")).trim().split(`
|
|
54
|
+
`).filter(Boolean).slice(-c);for(let d of l)console.log(d);return{success:!0}}catch(o){return console.error(`Failed to read logs for ${r}:`,o instanceof Error?o.message:o),{success:!1,message:"failed to read logs"}}}})});var tn,tt,sn,nn=h(()=>{"use strict";tn=require("crypto"),tt=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}`},sn=s=>{let e=tt(s),t=(0,tn.createHash)("sha256").update(e).digest("hex");return{id:e,hash:t}}});var rn={};C(rn,{internalsResourceHashCommand:()=>Gr,internalsResourceIdCommand:()=>qr});var Gr,qr,on=h(()=>{"use strict";x();nn();Gr=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 a=n.match(/^@([^#]+)#([^|]+)\|(.+)$/);if(!a)return console.error("Error: Invalid full ID format. Expected: @project#workspace|resource"),{success:!1,message:"Invalid ID format"};r=a[2],c=a[3]}else if(n.includes("|")){let a=n.split("|");r=a[0],c=a[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 p=sn({project:s,workspace:r,resource:c});return console.log(`${p.id}
|
|
55
|
+
${p.hash}`),{success:!0,message:"Hash generated successfully"}}}),qr=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 a=n.split("|");r=a[0],c=a[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 p=tt({project:s,workspace:r,resource:c});return console.log(p),{success:!0,message:"ID generated successfully"}}})});var cn,st,nt,Ur,rt,an,ln,ot=h(()=>{"use strict";cn=["pnpm-lock.yaml:","yarn.lock:","Gemfile.lock:","uv.lock:"],st=s=>{for(let e of cn)if(s.startsWith(e)){let n=s.slice(e.length).match(/^([^@]+)@([^(@]+)/);if(n)return{name:n[1],version:n[2]}}return null},nt=s=>cn.some(e=>s.startsWith(e)),Ur=s=>s.endsWith("#dependencies"),rt=s=>s.endsWith("#devDependencies"),an=(s,e,t)=>{let n=new Map;for(let o of s)n.set(o.name,o);let r=[],c=new Set;for(let o of s)if(!(t&&o.ecosystem!==t)){for(let i of o.versions)if(!nt(i.source)){let l=rt(i.source);if(Ur(i.source)||l){let m=`${o.name}@${i.resolved}`;c.has(m)||(c.add(m),r.push({dep:o,version:i.resolved,isDevDependency:l,children:[]}))}}}if(e>0){let o=new Map;for(let l of s)if(!(t&&l.ecosystem!==t))for(let d of l.versions){let m=st(d.source);if(m){let u=`${m.name}@${m.version}`,g=o.get(u)||[];g.some(f=>f.name===l.name)||(g.push(l),o.set(u,g))}}let i=(l,d,m)=>{if(d>=e)return;let u=`${l.dep.name}@${l.version}`;if(m.has(u))return;m.add(u);let g=o.get(u)||[];for(let f of g){let y=f.versions.find(v=>{let D=st(v.source);return D?.name===l.dep.name&&D?.version===l.version});if(y){let v={dep:f,version:y.resolved,isDevDependency:!1,children:[]};l.children.push(v),i(v,d+1,new Set(m))}}l.children.sort((f,y)=>f.dep.name.localeCompare(y.dep.name))};for(let l of r)i(l,0,new Set)}r.sort((o,i)=>{let l=o.dep.ecosystem.localeCompare(i.dep.ecosystem);return l!==0?l:o.dep.name.localeCompare(i.dep.name)});let p=[],a=(o,i,l,d)=>{p.push({name:o.dep.name,version:o.version,ecosystem:o.dep.ecosystem,isDevDependency:o.isDevDependency,depth:i,isLast:l,hasChildren:o.children.length>0,parentPath:[...d]});let m=[...d,l];o.children.forEach((u,g)=>{a(u,i+1,g===o.children.length-1,m)})};return r.forEach((o,i)=>{a(o,0,i===r.length-1,[])}),p},ln=(s,e,t,n)=>{if(!nt(t))return{name:s,version:e,children:[]};let r=[{name:s,version:e}],c=t,p=50,a=0;for(;a<p;){let l=st(c);if(!l)break;r.unshift({name:l.name,version:l.version});let d=n.get(l.name);if(!d)break;let m=d.versions.find(u=>u.resolved===l.version);if(!m||!nt(m.source))break;c=m.source,a++}if(r.length===0)return null;let o={name:r[0].name,version:r[0].version,children:[]},i=o;for(let l=1;l<r.length;l++){let d={name:r[l].name,version:r[l].version,children:[]};i.children.push(d),i=d}return o}});var pn={};C(pn,{depsListCommand:()=>Hr});var Hr,dn=h(()=>{"use strict";x();ot();ye();Hr=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 p=an(c,n,t);if(p.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 o=new Set(p.map(g=>g.ecosystem)).size>1&&!t,i=ce({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:o}],data:p,tree:{getDepth:g=>g.depth,getIsLast:g=>g.isLast,getHasChildren:g=>g.hasChildren,getParentPath:g=>g.parentPath}});for(let g of i)console.log(g);let l=p.filter(g=>g.depth===0),d=l.filter(g=>!g.isDevDependency).length,m=l.filter(g=>g.isDevDependency).length,u=c.length-l.length;return console.log(""),console.log(`${c.length} total (${d} dependencies, ${m} devDependencies, ${u} subdependencies)`),{success:!0,message:"Dependencies listed successfully."}}})});var mn={};C(mn,{depsOutdatedCommand:()=>Yr});var Ee,un,zr,Br,Yr,gn=h(()=>{"use strict";x();ye();Ee=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)}:null},un=(s,e)=>{if(s===e)return $.white;let t=Ee(s),n=Ee(e);return!t||!n?$.white:n.major!==t.major?$.red:n.minor!==t.minor?$.yellow:n.patch!==t.patch?$.green:$.white},zr=(s,e)=>{if(s===e)return null;let t=Ee(s),n=Ee(e);return!t||!n?null:n.major!==t.major?"major":n.minor!==t.minor?"minor":n.patch!==t.patch?"patch":null},Br=(s,e)=>s===null?!1:e==="patch"?s==="patch":e==="minor"?s==="patch"||s==="minor":!1,Yr=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 a=await s.outdatedDependencies({cache:t}),o=u=>u.versions[0]?.resolved||"";if(r&&(a=a.filter(u=>u.ecosystem===r)),n&&(a=a.filter(u=>{let g=zr(o(u),u.wanted);return Br(g,n)})),a.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 u="All dependencies are up to date!";return r&&n?u=`No ${n}-level updates available for ecosystem "${r}".`:r?u=`No outdated dependencies found for ecosystem "${r}".`:n&&(u=`No ${n}-level updates available.`),{success:!0,message:u}}let i=a.sort((u,g)=>{let f=u.ecosystem.localeCompare(g.ecosystem);return f!==0?f:u.name.localeCompare(g.name)});if(c==="json")return console.log(JSON.stringify(i)),{success:!0,message:"Outdated dependencies listed."};let d=new Set(a.map(u=>u.ecosystem)).size>1&&!r,m=ce({columns:[{header:"Package",accessor:u=>u.name},{header:"",accessor:u=>u.isDevDependency?`${$.grey}(dev)${$.reset}`:" "},{header:"Current",accessor:u=>o(u)},{header:"Wanted",accessor:u=>u.wanted,format:(u,g)=>`${un(o(g),g.wanted)}${u}${$.reset}`},{header:"Latest",accessor:u=>u.latest,format:(u,g)=>`${un(o(g),g.latest)}${u}${$.reset}`},{header:"Ecosystem",accessor:u=>u.ecosystem,visible:d}],data:i});for(let u of m)console.log(u);return{success:!0,message:"Outdated dependencies listed."}}})});var We,Ve,fn=h(()=>{"use strict";ye();We=(s,e="",t=!0,n=!0)=>{let r=[],c=s.children.length>0;if(n)r.push(`${s.name} ${$.grey}${s.version}${$.reset}`);else{let a=c?t?"\u2514\u2500\u252C ":"\u251C\u2500\u252C ":t?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ";r.push(`${e}${a}${s.name} ${$.grey}${s.version}${$.reset}`)}let p=n?"":e+(t?" ":"\u2502 ");for(let a=0;a<s.children.length;a++){let o=s.children[a],i=a===s.children.length-1;r.push(...We(o,p,i,!1))}return r},Ve=(s,e)=>{let t=s.find(n=>n.name===e.name&&n.version===e.version);if(t)for(let n of e.children)Ve(t.children,n);else s.push(e)}});var hn={};C(hn,{depsWhyCommand:()=>Kr});var Kr,yn=h(()=>{"use strict";x();ot();fn();Kr=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(o=>o.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 o of n)c.set(o.name,o);console.log(`${s.name} ${s.path}`),console.log("");let p=[],a=[];for(let o of r.versions){let i=ln(r.name,o.resolved,o.source,c);i&&(c.get(i.name)?.versions.some(m=>rt(m.source))?Ve(a,i):Ve(p,i))}if(p.length>0){console.log("dependencies:");for(let o=0;o<p.length;o++){let i=We(p[o],"",o===p.length-1,!0);for(let l of i)console.log(l)}console.log("")}if(a.length>0){console.log("devDependencies:");for(let o=0;o<a.length;o++){let i=We(a[o],"",o===a.length-1,!0);for(let l of i)console.log(l)}console.log("")}return p.length===0&&a.length===0&&console.log(`Could not determine dependency chain for "${t}".`),{success:!0,message:"Dependency chain shown."}}})});var it=F(require("minimist"),1);ue();Le();Ae();var vn=[{name:"project",description:"The project slug to run against. Defaults to current directory.",required:!1,type:"string",defaultValue:void 0}];async function Zr(){let s=process.argv[2],e=process.argv.slice(2),t=E(),n=process.cwd(),r=(0,it.default)(process.argv.slice(2)).project?.toString()||n.replace(`${t.codeRootDir}/`,"").split("/").slice(0,2).join("/"),c=new J(r),p={outdated:"deps:outdated"};p[s]&&(s=p[s]);let a=["start","stop","restart","status"];if(s==="services"){let S=process.argv[3];S&&a.includes(S)&&(s=`services:${S}`,e=[process.argv[2],...process.argv.slice(4)])}let o=["list","outdated","why"];if(s==="deps"){let S=process.argv[3];S&&o.includes(S)&&(s=`deps:${S}`,e=[process.argv[2],...process.argv.slice(4)])}let i=[...t.quickActions||[],...c?.config?.quickActions||[]].sort();i.includes(s)&&(e=["run",...process.argv.slice(2)],s="run",console.log("> Proxying to denvig run",...process.argv.slice(2)));let{runCommand:l}=await Promise.resolve().then(()=>(gs(),ms)),{configCommand:d}=await Promise.resolve().then(()=>(bs(),vs)),{pluginsCommand:m}=await Promise.resolve().then(()=>(Ss(),Ds)),{versionCommand:u}=await Promise.resolve().then(()=>(Ps(),js)),{infoCommand:g}=await Promise.resolve().then(()=>(ws(),$s)),{servicesCommand:f}=await Promise.resolve().then(()=>(Ws(),Es)),{servicesStartCommand:y}=await Promise.resolve().then(()=>(_s(),Ms)),{servicesStopCommand:v}=await Promise.resolve().then(()=>(Gs(),Js)),{servicesRestartCommand:D}=await Promise.resolve().then(()=>(Hs(),Us)),{servicesStatusCommand:w}=await Promise.resolve().then(()=>(Ks(),Ys)),{logsCommand:R}=await Promise.resolve().then(()=>(en(),Xs)),{internalsResourceHashCommand:T,internalsResourceIdCommand:le}=await Promise.resolve().then(()=>(on(),rn)),{depsListCommand:K}=await Promise.resolve().then(()=>(dn(),pn)),{depsOutdatedCommand:De}=await Promise.resolve().then(()=>(gn(),mn)),{depsWhyCommand:Se}=await Promise.resolve().then(()=>(yn(),hn)),pe={run:l,config:d,plugins:m,version:u,info:g,services:f,"services:start":y,"services:stop":v,"services:restart":D,"services:status":w,logs:R,deps:K,"deps:list":K,"deps:outdated":De,"deps:why":Se,"internals:resource-hash":T,"internals:resource-id":le},je=pe[s],de=(0,it.default)(e),bn=je?.args.reduce((S,j,$e)=>{let we=de._[$e+1];return we!==void 0?S[j.name]=we:j.required&&(console.error(`Missing required argument: ${j.name}`),process.exit(1)),S},{})||{},Dn=de._.slice(je?.args.length+1).map(S=>String(S))||[],ct=[...vn,...je?.flags||[]],Sn=new Set(ct.map(S=>S.name)),jn=ct.reduce((S,j)=>(de[j.name]!==void 0?S[j.name]=de[j.name]:j.defaultValue!==void 0?S[j.name]=j.defaultValue:j.required&&(console.error(`Missing required flag: ${j.name}`),process.exit(1)),S),{}),Pe=[];for(let[S,j]of Object.entries(de))S!=="_"&&!Sn.has(S)&&(j===!0?Pe.push(`--${S}`):j===!1?Pe.push(`--no-${S}`):Pe.push(`--${S}`,String(j)));let Pn=[...Dn,...Pe];if(!s){console.log(`Denvig v${oe()}`),console.log(""),console.log("Usage: denvig <command> [args] [flags]"),console.log(""),console.log("Available commands:"),Object.keys(pe).forEach(j=>{j.startsWith("internals:")||console.log(` - ${pe[j].usage.padEnd(20," ")} ${pe[j].description}`)}),console.log(""),console.log("Quick Actions:");for(let j of i){let $e=(await c?.actions)?.[j];if(!$e){console.log(` - ${j.padEnd(20," ")} not defined`);return}for(let we of $e){let at=we.split(`
|
|
56
|
+
`),$n=at[0],wn=at.slice(1);console.log(` - ${j.padEnd(20," ")} $ ${$n}`);for(let lt of wn)lt.trim()&&console.log(`${" ".repeat(27)}${lt}`)}}console.log(""),console.log("Global flags:"),vn.forEach(j=>{console.log(` --${j.name.padEnd(20," ")} ${j.description}`)}),process.exit(1)}pe[s]||(console.error(`Command "${s}" not found.`),process.exit(1));try{r||console.error("No project provided or detected.");let{success:S}=await je.run(c,bn,jn,Pn);S||process.exit(1)}catch(S){console.error(`Error executing command "${s}":`,S),process.exit(1)}}Zr();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "denvig",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "A CLI tool to consistently manage cross-discipline projects",
|
|
6
6
|
"bin": {
|
|
@@ -15,24 +15,25 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
"build": "rm -rf dist && tsup",
|
|
17
17
|
"check-types": "tsc --noEmit",
|
|
18
|
+
"codegen": "bin/codegen",
|
|
18
19
|
"prepublishOnly": "npm run build",
|
|
19
20
|
"lint": "biome check",
|
|
20
21
|
"lint:fix": "biome check --fix",
|
|
21
|
-
"test": "node --test src/**/*.test.ts",
|
|
22
|
-
"test:ci": "node --test src/**/*.test.ts --reporter=default",
|
|
22
|
+
"test": "node --test --test-skip-pattern='node_modules' src/**/*.test.ts",
|
|
23
|
+
"test:ci": "node --test --test-skip-pattern='node_modules' src/**/*.test.ts --reporter=default",
|
|
23
24
|
"dev": "tsc --watch"
|
|
24
25
|
},
|
|
25
26
|
"dependencies": {
|
|
26
27
|
"minimist": "^1.2.8",
|
|
27
|
-
"yaml": "^2.
|
|
28
|
-
"zod": "^4.
|
|
28
|
+
"yaml": "^2.8.2",
|
|
29
|
+
"zod": "^4.3.5"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
|
-
"@biomejs/biome": "^2.
|
|
32
|
+
"@biomejs/biome": "^2.3.11",
|
|
32
33
|
"@types/minimist": "^1.2.5",
|
|
33
|
-
"@types/node": "^
|
|
34
|
-
"tsup": "^8.5.
|
|
35
|
-
"typescript": "^5.
|
|
34
|
+
"@types/node": "^24",
|
|
35
|
+
"tsup": "^8.5.1",
|
|
36
|
+
"typescript": "^5.9.3"
|
|
36
37
|
},
|
|
37
38
|
"engines": {
|
|
38
39
|
"node": ">=22"
|