@denvig/cli 0.7.0-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ The MIT License (MIT)
2
+ Copyright © 2026 Marc Qualie, https://marcqualie.com
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5
+
6
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
7
+
8
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # Denvig - Developer Environment Envigorator
2
+
3
+ [![npm version](https://img.shields.io/npm/v/denvig?color=yellow)](https://npmjs.com/package/denvig)
4
+ [![install size](https://packagephobia.com/badge?p=denvig)](https://packagephobia.com/result?p=denvig)
5
+
6
+ Denvig is a concept of simplifying development environments across multiple languages and frameworks by creating a small
7
+ set of consistent wrappers to avoid muscle memory and configuration headaches.
8
+
9
+
10
+
11
+ ## Installation
12
+
13
+ ### Homebrew
14
+
15
+ ```shell
16
+ brew install denvig/tap/denvig
17
+ ```
18
+
19
+ ### NPM
20
+
21
+ You can install the CLI tool globally using npm:
22
+
23
+ ```shell
24
+ npm install -g denvig
25
+ ```
26
+
27
+ After installation, the `denvig` command will be available in your terminal.
28
+
29
+
30
+
31
+ ## Commands
32
+
33
+
34
+ ### Actions
35
+
36
+ Executes an action inside the project. Defaults are detected for common languages/frameworks, but you can also
37
+ specify your own actions in the `.denvig.yml` file.
38
+
39
+ ```shell
40
+ denvig run build
41
+ denvig run install
42
+ denvig run test
43
+ denvig run dev
44
+ ```
45
+
46
+ Some actions are common to many frameworks so they have quick access for convenience:
47
+
48
+ ```shell
49
+ denvig build
50
+ denvig test
51
+ denvig install
52
+ denvig lint
53
+ ```
54
+
55
+
56
+ ### Dependencies
57
+
58
+ Inspect and manage project dependencies across multiple ecosystems (npm, pnpm, yarn, Ruby/Bundler, Python/uv):
59
+
60
+ ```shell
61
+ denvig deps. # List all dependencies
62
+ denvig deps list --depth 1 # Include subdependencies
63
+ denvig deps list --ecosystem npm # Filter to specific ecosystem
64
+ denvig deps outdated # Show outdated dependencies
65
+ denvig deps outdated --semver patch # Filter by semver level (patch or minor)
66
+ denvig deps outdated --no-cache # Force fresh data
67
+ denvig deps why <package> # Show why a dependency is installed
68
+ ```
69
+
70
+
71
+ ### Services
72
+
73
+ Manage background services defined in `.denvig.yml`. Services run via launchctl on macOS:
74
+
75
+ ```shell
76
+ denvig services # List all services and their status
77
+ denvig services start api # Start a service
78
+ denvig services stop api # Stop a service
79
+ denvig services restart api # Restart a service
80
+ denvig services status api # Check status of a service
81
+ denvig services logs api # View service logs
82
+ denvig services logs api -n 50 # View last 50 lines
83
+ denvig services logs api -f # Follow logs in real-time
84
+ denvig services teardown # Stop all services in current project
85
+ denvig services teardown --global --remove-logs # Full cleanup
86
+ ```
87
+
88
+ Manage services from other projects using the full path:
89
+
90
+ ```shell
91
+ denvig services start marcqualie/denvig/dev # Start 'dev' service in marcqualie/denvig project
92
+ denvig services status marcqualie/denvig/hello # Check status of 'hello' in marcqualie/denvig project
93
+ ```
94
+
95
+ See [docs/configuration.md](docs/configuration.md) for service configuration options.
96
+
97
+
98
+ ### Projects
99
+
100
+ Discover and manage projects across your system:
101
+
102
+ ```shell
103
+ denvig projects # List all projects
104
+ denvig projects --with-config # Only show projects with .denvig.yml
105
+ ```
106
+
107
+
108
+ ### Configuration
109
+
110
+ View and validate configuration:
111
+
112
+ ```shell
113
+ denvig config # Display current configuration
114
+ denvig config verify # Verify .denvig.yml against schema
115
+ denvig config verify path/to/file.yml
116
+ ```
117
+
118
+
119
+ ### Utilities
120
+
121
+ ```shell
122
+ denvig info # Show information about current project
123
+ denvig plugins # List available plugins and their actions
124
+ denvig version # Show version
125
+ denvig shell completions zsh --install # Install shell completions
126
+ ```
127
+
128
+ Most commands accept `--json` for programmatic output and `--project` to target a different project.
129
+
130
+
131
+
132
+ ## Languages / Frameworks
133
+
134
+ There is a set of core languages and frameworks that Denvig will support out of the box. Any language or framework
135
+ can be supported by using the per project configs.
136
+
137
+ - [x] Node.js (npm, pnpm, yarn)
138
+ - [ ] Bun
139
+ - [ ] Vite
140
+ - [ ] Deno
141
+ - [x] Ruby (rubygems)
142
+ - [x] Python (uv)
143
+
144
+
145
+
146
+ ## Goals
147
+
148
+ - [x] CLI tool to simplify environment setup
149
+ - [x] YAML configuration at ~/.denvig.yml
150
+ - [x] Per project configuration via ./.denvig.yml
151
+ - [x] Consistent API for all languages/frameworks
152
+ - [x] Dependency management across multiple ecosystems
153
+ - [x] Background service management
154
+
155
+
156
+
157
+ ## Troubleshooting
158
+
159
+ For troubleshooting guides including service management, resource identification, and log browsing, see [docs/troubleshooting.md](docs/troubleshooting.md).
160
+
161
+
162
+
163
+ ## SDK
164
+
165
+ Denvig can be used programmatically in TypeScript projects:
166
+
167
+ ```ts
168
+ import { DenvigSDK } from 'denvig'
169
+
170
+ const denvig = new DenvigSDK()
171
+
172
+ // Services
173
+ const services = await denvig.services.list()
174
+ await denvig.services.start('api')
175
+ await denvig.services.stop('api')
176
+
177
+ // Dependencies
178
+ const deps = await denvig.deps.list()
179
+ const outdated = await denvig.deps.outdated({ semver: 'minor' })
180
+
181
+ // Execute in context of another project
182
+ await denvig.deps.outdated({ project: 'marcqualie/denvig' })
183
+ ```
184
+
185
+ All response types are exported for TypeScript consumers:
186
+
187
+ ```ts
188
+ import type { ServiceResponse, Dependency, OutdatedDependency } from 'denvig'
189
+ ```
190
+
191
+
192
+
193
+ ## Building from source
194
+
195
+ You can build from source instead of using the provided methods above:
196
+
197
+ ```shell
198
+ pnpm install
199
+ pnpm build
200
+ ```
201
+
202
+ After building, the CLI will be available at `dist/cli.cjs`. You can link it globally:
203
+
204
+ ```shell
205
+ npm link
206
+ ```
package/dist/cli.cjs ADDED
@@ -0,0 +1,229 @@
1
+ #!/usr/bin/env node
2
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(e&&(t=e(e=0)),t),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let u=require("node:util"),d=require("node:child_process"),f=require("node:fs/promises"),p=require("node:os");p=l(p,1);let m=require("node:path");m=l(m,1);let h=require("yaml"),g=require("semver");g=l(g,1);let _=require("node:crypto"),v=require("node:fs"),y=require("zod"),ee=require("node:net"),te=require("node:readline");var ne,b,x,S=o((()=>{ne=class extends Error{constructor(e){super(e),this.name=`DenvigError`}},b=class extends ne{constructor(e){super(e),this.name=`DenvigValidationError`}},x=class extends ne{details;constructor(e,t){super(e),this.name=`DenvigOperationError`,this.details=t}}})),re,C=o((()=>{re=async(e,t)=>{let{args:n=[],projectSlug:r,cwd:i}=t,a=t.onCommand??(e=>console.log(e)),o=t.interactive??!!(process.stdout.isTTY&&process.stdin.isTTY),s={success:!0};for(let t of e){let e=`${t} ${n.join(` `)}`.trim();a(`$ ${e}`);let c={...process.env,DENVIG_PROJECT:r},l,u;o?process.platform===`darwin`?(l=`script`,u=[`-q`,`/dev/null`,`sh`,`-c`,e]):(l=`script`,u=[`-q`,`-c`,e,`/dev/null`]):(l=`sh`,u=[`-c`,e]);let f=(0,d.spawn)(l,u,{cwd:i,env:c,stdio:`inherit`}),p=await new Promise(e=>{f.on(`close`,t=>{e({success:t===0})})});p.success||(s=p)}return s}})),ie,ae,oe,se,ce,le=o((()=>{ie=()=>process.env.DENVIG_CLI_LOGS_ENABLED!==`0`,ae=()=>process.env.DENVIG_CLI_LOGS_PATH?(0,m.resolve)(process.env.DENVIG_CLI_LOGS_PATH):(0,m.resolve)((0,p.homedir)(),`.denvig`,`logs`,`cli.jsonl`),oe=async()=>{await(0,f.mkdir)((0,m.resolve)(ae(),`..`),{recursive:!0})},se=async e=>{if(ie())try{await oe(),await(0,f.appendFile)(ae(),`${JSON.stringify(e)}\n`,`utf-8`)}catch{}},ce=e=>{let t=Date.now();return{finish:async(n,r)=>{let i={timestamp:new Date().toISOString(),version:e.version,slug:void 0,command:e.command,via:void 0,duration:Date.now()-t,path:e.path,status:n,error:void 0};e.slug!==void 0&&(i.slug=e.slug),e.via!==void 0&&(i.via=e.via),r!==void 0&&(i.error=r),await se(i)}}}}));S(),C(),le();var ue=`0.7.0-alpha.4`;function de(){return ue}var fe=o((()=>{})),w,pe=o((()=>{fe(),w=async(e,t,n,r)=>{let i=ce({version:de(),command:`sdk:${t}`,path:e.cwd,slug:n??void 0,via:`sdk:${e.client}`});try{let e=await r();return await i.finish(0),e}catch(e){let t=e instanceof Error?e.message:String(e);throw await i.finish(1,t.replace(/[\r\n]+/g,` `).trim()),e}}})),T,me=o((()=>{pe(),T=class{_name;_commands;worktree;ctx;constructor(e,t,n,r){this._name=e,this._commands=t,this.worktree=n,this.ctx=r}get name(){return this._name}get commands(){return this._commands}async run(e){return w(this.ctx,`actions.run`,this.worktree.slug,()=>re(this._commands,{args:e?.args,projectSlug:this.worktree.slug,cwd:this.worktree.path}))}}})),he,ge=o((()=>{he=(e,t)=>{for(let[n,r]of Object.entries(t))e[n]||(e[n]=[]),e[n].push(...r);return e}})),_e,ve,ye,be,xe,Se,Ce,we,Te=o((()=>{_e=[`pnpm-lock.yaml:`,`yarn.lock:`,`Gemfile.lock:`,`uv.lock:`,`deno.lock:`],ve=e=>{for(let t of _e)if(e.startsWith(t)){let n=e.slice(t.length).match(/^((?:@[^@/]+\/)?[^@]+)@([^(@]+)/);if(n)return{name:n[1],version:n[2]}}return null},ye=e=>_e.some(t=>e.startsWith(t)),be=(e,t)=>{if(t<=0)return e.filter(e=>e.versions.some(e=>e.source.includes(`#dependencies`)||e.source.includes(`#devDependencies`)));let n=new Map;for(let t of e)for(let e of t.versions){let r=ve(e.source);if(!r)continue;let i=`${r.name}@${r.version}`,a=n.get(i)??new Set;a.add(t.name),n.set(i,a)}let r=new Set,i=[];for(let t of e)for(let e of t.versions)(e.source.includes(`#dependencies`)||e.source.includes(`#devDependencies`))&&(r.has(t.name)||r.add(t.name),i.push({name:t.name,version:e.resolved,depth:0}));let a=new Set;for(;i.length>0;){let o=i.shift();if(!o)break;if(o.depth>=t)continue;let s=`${o.name}@${o.version}`;if(a.has(s))continue;a.add(s);let c=n.get(s);if(c)for(let t of c){r.add(t);let n=e.find(e=>e.name===t);if(n)for(let e of n.versions){let t=ve(e.source);t?.name===o.name&&t.version===o.version&&i.push({name:n.name,version:e.resolved,depth:o.depth+1})}}}return e.filter(e=>r.has(e.name))},xe=e=>e.endsWith(`#dependencies`),Se=e=>e.endsWith(`#devDependencies`),Ce=(e,t,n)=>{let r=new Map;for(let t of e)r.set(t.name,t);let i=[],a=new Set;for(let t of e)if(!(n&&t.ecosystem!==n)){for(let e of t.versions)if(!ye(e.source)){let n=Se(e.source);if(xe(e.source)||n){let r=`${t.name}@${e.resolved}`;a.has(r)||(a.add(r),i.push({dep:t,version:e.resolved,isDevDependency:n,children:[]}))}}}if(t>0){let r=new Map;for(let t of e)if(!(n&&t.ecosystem!==n))for(let e of t.versions){let n=ve(e.source);if(n){let e=`${n.name}@${n.version}`,i=r.get(e)||[];i.some(e=>e.name===t.name)||(i.push(t),r.set(e,i))}}let a=(e,n,i)=>{if(n>=t)return;let o=`${e.dep.name}@${e.version}`;if(i.has(o))return;i.add(o);let s=r.get(o)||[];for(let t of s){let r=t.versions.find(t=>{let n=ve(t.source);return n?.name===e.dep.name&&n?.version===e.version});if(r){let o={dep:t,version:r.resolved,isDevDependency:!1,children:[]};e.children.push(o),a(o,n+1,new Set(i))}}e.children.sort((e,t)=>e.dep.name.localeCompare(t.dep.name))};for(let e of i)a(e,0,new Set)}i.sort((e,t)=>{let n=e.dep.ecosystem.localeCompare(t.dep.ecosystem);return n===0?e.dep.name.localeCompare(t.dep.name):n});let o=[],s=(e,t,n,r)=>{o.push({name:e.dep.name,version:e.version,ecosystem:e.dep.ecosystem,isDevDependency:e.isDevDependency,depth:t,isLast:n,hasChildren:e.children.length>0,parentPath:[...r]});let i=[...r,n];e.children.forEach((n,r)=>{s(n,t+1,r===e.children.length-1,i)})};return i.forEach((e,t)=>{s(e,0,t===i.length-1,[])}),o},we=(e,t,n,r)=>{if(!ye(n))return{name:e,version:t,children:[]};let i=[{name:e,version:t}],a=n,o=0;for(;o<50;){let e=ve(a);if(!e)break;i.unshift({name:e.name,version:e.version});let t=r.get(e.name);if(!t)break;let n=t.versions.find(t=>t.resolved===e.version);if(!n||!ye(n.source))break;a=n.source,o++}if(i.length===0)return null;let s={name:i[0].name,version:i[0].version,children:[]},c=s;for(let e=1;e<i.length;e++){let t={name:i[e].name,version:i[e].version,children:[]};c.children.push(t),c=t}return s}})),Ee,De,Oe,ke,Ae,je,Me,Ne,Pe=o((()=>{Ee=3600*1e3,De=async()=>{let e=`${(0,p.homedir)()}/.cache/denvig/dependencies/npm`;return await(0,f.mkdir)(e,{recursive:!0}),e},Oe=e=>{let t=e.replace(/@/g,`_at_`).replace(/\//g,`__`);return t=t.replace(/[^a-zA-Z0-9\-_.]/g,`_`),t=t.replace(/\.{2,}/g,`_`),t=t.replace(/^\.+/,`_`),t.length===0&&(t=`_empty_`),t.length>200&&(t=t.slice(0,200)),t},ke=async e=>{let t=Oe(e);return`${await De()}/${t}.json`},Ae=async e=>{try{let t=await(0,f.stat)(e);return Date.now()-t.mtimeMs<Ee}catch{return!1}},je=async e=>{let t=await ke(e);if(!await Ae(t))return null;try{let e=await(0,f.readFile)(t,`utf-8`),n=JSON.parse(e);return n.versionDates?n:null}catch{return null}},Me=async(e,t)=>{try{await(0,f.writeFile)(await ke(e),JSON.stringify(t),`utf-8`)}catch{}},Ne=async(e,t=!1)=>{if(!t){let t=await je(e);if(t)return t}try{let t=await fetch(`https://registry.npmjs.com/${encodeURIComponent(e)}`,{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],a={};if(n.time)for(let[e,t]of Object.entries(n.time))e!==`created`&&e!==`modified`&&(a[e]=t);let o={versions:r,latest:i,versionDates:a};return await Me(e,o),o}catch{return null}}})),Fe,Ie,Le,Re,ze,Be,Ve=o((()=>{Te(),Pe(),Fe=e=>{let t=e.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);return t?{major:Number.parseInt(t[1],10),minor:Number.parseInt(t[2],10),patch:Number.parseInt(t[3],10),prerelease:t[4]||``}:null},Ie=(e,t)=>{let n=Fe(e),r=Fe(t);return!n||!r?0:n.major===r.major?n.minor===r.minor?n.patch===r.patch?n.prerelease&&!r.prerelease?-1:!n.prerelease&&r.prerelease?1:0:n.patch-r.patch:n.minor-r.minor:n.major-r.major},Le=(e,t)=>{let n=Fe(e);if(!n||n.prerelease)return!1;if(t.startsWith(`^`)){let r=Fe(t.slice(1));return r?r.major===0?n.major===0&&n.minor===r.minor&&n.patch>=r.patch:n.major===r.major&&Ie(e,t.slice(1))>=0:!1}if(t.startsWith(`~`)){let e=Fe(t.slice(1));return e?n.major===e.major&&n.minor===e.minor&&n.patch>=e.patch:!1}if(t.startsWith(`>=`))return Ie(e,t.slice(2))>=0;if(t.startsWith(`>`)&&!t.startsWith(`>=`))return Ie(e,t.slice(1))>0;let r=Fe(t);return r?n.major===r.major&&n.minor===r.minor&&n.patch===r.patch:!1},Re=(e,t)=>{let n=e.filter(e=>Le(e,t)).sort(Ie);return n.length>0?n[n.length-1]:null},ze=e=>{if(e.versions.length===0)return null;let t=e.versions[0],n=t.source.includes(`#devDependencies`),r=e.versions.find(e=>!e.specifier.startsWith(`catalog:`))?.specifier??t.specifier;return{current:t.resolved,specifier:r,isDevDependency:n}},Be=async(e,t={})=>{let n=t.cache??!0,r=t.depth??0,i=[],a=be(e,r).map(async e=>{let t=ze(e);if(!t)return;let r=await Ne(e.name,!n);if(!r)return;let a=Re(r.versions,t.specifier),o=r.latest,s=a&&a!==t.current,c=o&&o!==t.current;if(s||c){let n=a||t.current;i.push({...e,wanted:n,latest:o,specifier:t.specifier,isDevDependency:t.isDevDependency,currentDate:r.versionDates?.[t.current],wantedDate:r.versionDates?.[n],latestDate:r.versionDates?.[o]})}});return await Promise.all(a),i}})),He,Ue,We,Ge,Ke,qe,Je,Ye=o((()=>{Pe(),He=3600*1e3,Ue=async()=>{let e=`${(0,p.homedir)()}/.cache/denvig/dependencies/jsr`;return await(0,f.mkdir)(e,{recursive:!0}),e},We=async e=>{let t=Oe(e);return`${await Ue()}/${t}.json`},Ge=async e=>{try{let t=await(0,f.stat)(e);return Date.now()-t.mtimeMs<He}catch{return!1}},Ke=async e=>{let t=await We(e);if(!await Ge(t))return null;try{let e=await(0,f.readFile)(t,`utf-8`);return JSON.parse(e)}catch{return null}},qe=async(e,t)=>{try{await(0,f.writeFile)(await We(e),JSON.stringify(t),`utf-8`)}catch{}},Je=async(e,t=!1)=>{if(!t){let t=await Ke(e);if(t)return t}try{let t=await fetch(`https://jsr.io/${e}/meta.json`,{headers:{Accept:`application/json`}});if(!t.ok)return null;let n=await t.json(),r=Object.entries(n.versions).filter(([e,t])=>!t.yanked).map(([e])=>e),i=n.latest,a={};for(let[e,t]of Object.entries(n.versions))t.createdAt&&(a[e]=t.createdAt);let o={versions:r,latest:i,versionDates:Object.keys(a).length>0?a:void 0};return await qe(e,o),o}catch{return null}}})),Xe,Ze=o((()=>{Te(),Ve(),Ye(),Xe=async(e,t={})=>{let n=t.cache??!0,r=t.depth??0,i=[],a=be(e,r).map(async e=>{let t=ze(e);if(!t)return;let r=await Je(e.name,!n);if(!r)return;let a=t.specifier===`*`?r.latest:Re(r.versions,t.specifier),o=r.latest,s=a&&a!==t.current,c=o&&o!==t.current;if(s||c){let n=a||t.current;i.push({...e,wanted:n,latest:o,specifier:t.specifier,isDevDependency:t.isDevDependency,currentDate:r.versionDates?.[t.current],wantedDate:r.versionDates?.[n],latestDate:r.versionDates?.[o]})}});return await Promise.all(a),i}})),Qe,$e=o((()=>{Qe=async e=>{let t=`${e.path}/package.json`;try{let e=await(0,f.readFile)(t,`utf-8`);return JSON.parse(e)}catch{return null}}})),et,tt=o((()=>{et=e=>e})),nt,E,rt,D=o((()=>{nt=async e=>{try{return(await(0,f.readFile)(e,`utf8`)).trim()||null}catch(e){if(e&&typeof e==`object`&&`code`in e&&e.code===`ENOENT`)return null;throw e}},E=async e=>{try{return await(0,f.access)(e),!0}catch{return!1}},rt=async e=>{try{return(await(0,f.stat)(e)).isDirectory()}catch{return!1}}})),it,at,ot,st,ct,lt,ut=o((()=>{ge(),Ze(),Ve(),$e(),tt(),D(),it=new Map,at=e=>{let t=e.match(/^(npm|jsr):(.+)@([^@]+)$/);return t?{ecosystem:t[1],name:t[2],versionRange:t[3]}:null},ot=(e,t)=>{for(let[n,r]of Object.entries(t))if(n===e||n.startsWith(`${e}@`))return{specKey:n,resolved:r};return null},st=(e,t)=>{for(let n of Object.keys(t)){let t=n.lastIndexOf(`@`);if(!(t<=0)&&n.slice(0,t)===e)return n.slice(t+1)}return null},ct=async e=>{try{let t=await(0,f.readFile)(e,`utf-8`);return JSON.parse(t)}catch{return{}}},lt=et({name:`deno`,actions:async e=>{let t=e.rootFiles;if(!(t.includes(`deno.json`)||t.includes(`deno.jsonc`)))return{};let n=(await Qe(e))?.scripts||{},r={...Object.entries(n).map(([e,t])=>[e,`deno ${t}`]).reduce((e,[t,n])=>(e[t]=[n],e),{}),install:[`deno install`],outdated:[`deno outdated`]},i=await E(`${e.path}/deno.json`)?`${e.path}/deno.json`:await E(`${e.path}/deno.jsonc`)?`${e.path}/deno.jsonc`:null,a=(i?await ct(i):{}).tasks||{};return r=he(r,{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((e,[t,n])=>(e[t]=[n.startsWith(`deno`)?n:`deno task ${t}`],e),{}),install:[`deno install`],outdated:[`deno outdated`]}),r},dependencies:async e=>{if(!await E(`${e.path}/deno.lock`))return[];let t=it.get(e.path);if(t)return t;let n=new Map,r=new Set,i=(e,t,r,i,a,o)=>{let s=n.get(e);s?s.versions.push({resolved:i,specifier:o,source:a}):n.set(e,{id:e,name:t,ecosystem:r,versions:[{resolved:i,specifier:o,source:a}]})},a=await(0,f.readFile)(`${e.path}/deno.lock`,`utf-8`),o=JSON.parse(a),s=o.workspace?.dependencies||[];for(let e of s){let t=o.specifiers[e];if(!t)continue;let n=at(e);if(!n)continue;let a=`${n.ecosystem}:${n.name}`;r.add(a),i(a,n.name,n.ecosystem,t,`.#dependencies`,n.versionRange)}if(o.jsr){for(let[e,t]of Object.entries(o.jsr))if(t.dependencies)for(let n of t.dependencies){let t=ot(n,o.specifiers);if(!t)continue;let a=at(t.specKey);if(!a)continue;let s=`${a.ecosystem}:${a.name}`;r.has(s)||i(s,a.name,a.ecosystem,t.resolved,`deno.lock:${e}`,t.resolved)}}if(o.npm)for(let[e,t]of Object.entries(o.npm)){let n=[...t.dependencies||[],...t.optionalDependencies||[]];if(n.length!==0)for(let t of n){let n=`npm:${t}`;if(r.has(n))continue;let a=st(t,o.npm);a&&i(n,t,`npm`,a,`deno.lock:${e}`,a)}}let c=Array.from(n.values()).sort((e,t)=>e.name.localeCompare(t.name));return it.set(e.path,c),c},outdatedDependencies:async(e,t)=>{if(!await E(`${e.path}/deno.lock`))return[];let n=await lt.dependencies?.(e);if(!n)return[];let r=n.filter(e=>e.ecosystem===`npm`),i=n.filter(e=>e.ecosystem===`jsr`),[a,o]=await Promise.all([Be(r,t),Xe(i,t)]);return[...a,...o]}})})),dt,ft=o((()=>{$e(),tt(),dt=et({name:`npm`,actions:async e=>{let t=e.rootFiles,n=t.includes(`package.json`),r=t.includes(`package-lock.json`);if(!(n&&r))return{};let i=(await Qe(e))?.scripts||{};return{...Object.entries(i).map(([e,t])=>[e,`npm run ${e}`]).reduce((e,[t,n])=>(e[t]=[n],e),{}),install:[`npm install`],outdated:[`npm outdated`]}}})})),pt,mt,ht=o((()=>{pt=e=>{let t=0,n=0,r={},i=[];for(let[a,o]of Object.entries(e.dependencies)){let e=Object.keys(o.versions),s=Object.keys(o.optimisedVersions||{});t+=e.length,n+=s.length,e.length!==s.length&&(r[a]=e.filter(e=>!s.includes(e)),i.push({name:a,versions:e,optimisedVersions:s}))}return{totalDependencies:t,optimisedDependencies:n,removals:r,details:i}},mt=async(e,t,n)=>{await(0,f.writeFile)(e,t,`utf-8`),await new Promise((t,r)=>{(0,d.spawn)(n,[`install`],{cwd:(0,m.dirname)(e),stdio:`inherit`,shell:!0}).on(`close`,e=>{e===0?t():r(Error(`${n} install failed with code ${e}`))})})}})),gt,_t,vt=o((()=>{gt=(e,t)=>{let n=`0.0.0`;for(let r of t)(0,g.satisfies)(r,e)&&(n=r);return n===`0.0.0`?t[t.length-1]:n},_t=e=>{let t=Object.keys(e),n=Object.values(e).flat(),r={};for(let e of n){let n=gt(e,t);r[n]||(r[n]=[]),r[n].push(e)}return r}})),yt,bt,xt=o((()=>{vt(),yt=e=>{let t=e.match(/^([^(]+)/);return t?t[1]:e},bt=e=>{let t={},n=(0,h.parse)(e);if(!n.importers)return{dependencies:t};for(let[e,r]of Object.entries(n.importers)){let e=[r.dependencies,r.devDependencies,r.optionalDependencies];for(let n of e)if(n)for(let[e,r]of Object.entries(n)){let{specifier:n,version:i}=r;if(i.startsWith(`link:`))continue;let a=yt(i);t[e]||(t[e]={versions:{}}),t[e].versions[a]||(t[e].versions[a]=[]),t[e].versions[a].includes(n)||t[e].versions[a].push(n),t[e].versions[a]=t[e].versions[a].sort((e,t)=>e.localeCompare(t,void 0,{numeric:!0})),t[e].versions=Object.fromEntries(Object.entries(t[e].versions).sort((e,t)=>e[0].localeCompare(t[0],void 0,{numeric:!0})))}}for(let[e,n]of Object.entries(t))t[e].optimisedVersions=_t(n.versions);return{dependencies:t}}})),St,Ct,wt,Tt,Et,Dt=o((()=>{St=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),Ct=e=>{let t=e.match(/^([^(]+)/);return t?t[1]:e},wt=(e,t)=>{for(let[n,r]of Object.entries(t))if(r.includes(e))return n;return null},Tt=(e,t)=>{let n=St(t),r=RegExp(`^ '?${n}'?:.*\\n(?: .*\\n)*\\n?`,`gm`);return e.replace(r,``)},Et=(e,t,n)=>{let r=(0,h.parse)(e),i=e,a={};if(r.importers&&n)for(let e of Object.values(r.importers)){let r=[e.dependencies,e.devDependencies,e.optionalDependencies];for(let e of r)if(e)for(let[r,i]of Object.entries(e)){let e=i.version,{specifier:o}=i;if(e.startsWith(`link:`))continue;let s=Ct(e);if(t[r]?.includes(s)){let t=n[r];if(t){let n=wt(o,t);n&&n!==s&&(a[e]=e.includes(`(`)?e.replace(/^[^(]+/,n):n)}}}}for(let[e,t]of Object.entries(a)){let n=RegExp(`^(\\s+version: )${St(e)}$`,`gm`);i=i.replace(n,`$1${t}`)}for(let[e,n]of Object.entries(t))for(let t of n){let n=`${e}@${t}`;i=Tt(i,n),i=Tt(i,n)}return i}})),Ot,kt=o((()=>{Ot=e=>{if(/^\d+$/.test(e))return Number.parseInt(e,10)*60*1e3;let t=e.match(/^(\d+)(s|m|h|d|w)$/);if(!t)return null;let n=Number.parseInt(t[1],10);switch(t[2]){case`s`:return n*1e3;case`m`:return n*60*1e3;case`h`:return n*60*60*1e3;case`d`:return n*24*60*60*1e3;case`w`:return n*7*24*60*60*1e3;default:return null}}})),At,jt,Mt,Nt,Pt,Ft=o((()=>{kt(),At=async e=>{try{return(0,h.parse)(await(0,f.readFile)(`${e}/pnpm-workspace.yaml`,`utf-8`))}catch{return null}},jt=async e=>{let t=await At(e);if(!t)return null;let n=t.catalog&&typeof t.catalog==`object`?t.catalog:null,r=t.catalogs&&typeof t.catalogs==`object`?t.catalogs:null;return!n&&!r?null:{default:n??{},named:r??{}}},Mt=(e,t,n)=>{if(!e||!n.startsWith(`catalog:`))return null;let r=n.slice(8).trim(),i=r===``||r==="default"?`default`:r,a=i==="default"?e.default:e.named[i];if(!a)return null;let o=a[t];return o?{specifier:o,catalogName:i}:null},Nt=e=>e==="default"?`pnpm-workspace.yaml$catalog`:`pnpm-workspace.yaml$catalogs.${e}`,Pt=async e=>{try{let t=(0,h.parse)(await(0,f.readFile)(`${e}/pnpm-workspace.yaml`,`utf-8`));if(t?.minimumReleaseAge==null)return null;let n=Ot(String(t.minimumReleaseAge));return n===null?null:{minimumReleaseAgeMs:n,exclude:t.minimumReleaseAgeExclude??[]}}catch{return null}}})),It,Lt,Rt,zt,Bt=o((()=>{ht(),xt(),Dt(),Ve(),$e(),tt(),Ft(),D(),It=new Map,Lt=e=>{let t=e.indexOf(`(`);return t===-1?e:e.slice(0,t)},Rt=e=>{if(/^\d/.test(e))return null;let t=e.match(/^((?:@[^@/]+\/)?[^@]+)@(.+)$/);return t?{name:t[1],version:t[2]}:null},zt=et({name:`pnpm`,actions:async e=>{if(!e.rootFiles.includes(`pnpm-lock.yaml`))return{};let t=(await Qe(e))?.scripts||{},n=e.rootFiles.includes(`pnpm-workspace.yaml`);return{...Object.entries(t).map(([e,t])=>[e,`pnpm --reporter=silent run ${e}`]).reduce((e,[t,n])=>(e[t]=[n],e),{}),install:[`pnpm install`],outdated:[n?`pnpm outdated -r`:`pnpm outdated`]}},dependencies:async e=>{if(!await E(`${e.path}/pnpm-lock.yaml`))return[];let t=It.get(e.path);if(t)return t;let n=new Map,r=(e,t,r,i,a,o)=>{let s=n.get(e);s?s.versions.push({resolved:i,specifier:o,source:a}):n.set(e,{id:e,name:t,ecosystem:r,versions:[{resolved:i,specifier:o,source:a}]})};n.set(`npm:pnpm`,{id:`npm:pnpm`,name:`pnpm`,ecosystem:`system`,versions:[]});let i=(0,h.parse)(await(0,f.readFile)(`${e.path}/pnpm-lock.yaml`,`utf-8`)),a=await jt(e.path),o=new Set,s=(e,t,n)=>{let i=`npm:${e}`,s=Lt(t.version),c=Mt(a,e,t.specifier);if(r(i,e,`npm`,s,n,t.specifier),c){let t=Nt(c.catalogName),n=`${i}@${t}`;o.has(n)||(o.add(n),r(i,e,`npm`,s,t,c.specifier))}};if(i?.importers)for(let[e,t]of Object.entries(i.importers)){let n=e===`.`?`.`:e;if(t.dependencies)for(let[e,r]of Object.entries(t.dependencies))r?.specifier&&r?.version&&s(e,r,`${n}#dependencies`);if(t.devDependencies)for(let[e,r]of Object.entries(t.devDependencies))r?.specifier&&r?.version&&s(e,r,`${n}#devDependencies`)}if(i?.snapshots)for(let[e,t]of Object.entries(i.snapshots)){let n={...t.dependencies};for(let[t,i]of Object.entries(n)){let n=Rt(i),a=n?n.name:t,o=Lt(n?n.version:i),s=`pnpm-lock.yaml:${e}`;r(`npm:${a}`,a,`npm`,o,s,o)}}let c=Array.from(n.values()).sort((e,t)=>e.name.localeCompare(t.name));return It.set(e.path,c),c},outdatedDependencies:async(e,t)=>{if(!await E(`${e.path}/pnpm-lock.yaml`))return[];let n=await zt.dependencies?.(e);return n?Be(n,t):[]},deduplicateDependencies:async(e,t)=>{let n=`${e.path}/pnpm-lock.yaml`;if(!await E(n))return null;let r=await(0,f.readFile)(n,`utf-8`),i=bt(r),a=pt(i),o=t?.dryRun??!1,s=!1;if(!o&&Object.keys(a.removals).length>0){let e={};for(let[t,n]of Object.entries(i.dependencies))a.removals[t]&&n.optimisedVersions&&(e[t]=n.optimisedVersions);await mt(n,Et(r,a.removals,e),`pnpm`),s=!0}return{ecosystem:`pnpm-lock.yaml`,...a,applied:s}}})})),Vt,Ht,Ut,Wt,Gt,Kt,qt,Jt,Yt=o((()=>{Vt=3600*1e3,Ht=async()=>{let e=`${(0,p.homedir)()}/.cache/denvig/dependencies/rubygems`;return await(0,f.mkdir)(e,{recursive:!0}),e},Ut=e=>{let t=e.replace(/[^a-zA-Z0-9\-_.]/g,`_`);return t=t.replace(/\.{2,}/g,`_`),t=t.replace(/^\.+/,`_`),t.length===0&&(t=`_empty_`),t.length>200&&(t=t.slice(0,200)),t},Wt=async e=>{let t=Ut(e);return`${await Ht()}/${t}.json`},Gt=async e=>{try{let t=await(0,f.stat)(e);return Date.now()-t.mtimeMs<Vt}catch{return!1}},Kt=async e=>{let t=await Wt(e);if(!await Gt(t))return null;try{let e=await(0,f.readFile)(t,`utf-8`),n=JSON.parse(e);return n.versionDates?n:null}catch{return null}},qt=async(e,t)=>{try{await(0,f.writeFile)(await Wt(e),JSON.stringify(t),`utf-8`)}catch{}},Jt=async(e,t=!1)=>{if(!t){let t=await Kt(e);if(t)return t}try{let t=await fetch(`https://rubygems.org/api/v1/versions/${encodeURIComponent(e)}.json`,{headers:{Accept:`application/json`}});if(!t.ok)return null;let n=await t.json(),r=n.map(e=>e.number),i=n.filter(e=>!e.prerelease).map(e=>e.number)[0]||r[0],a={};for(let e of n)e.created_at&&(a[e.number]=e.created_at);let o={versions:r,latest:i,versionDates:a};return await qt(e,o),o}catch{return null}}})),Xt,O,Zt,Qt,$t,en,tn=o((()=>{Yt(),Xt=e=>{let t=e.match(/^(\d+)\.(\d+)(?:\.(\d+))?(?:-(.+)|\.(.+))?$/);return t?{major:Number.parseInt(t[1],10),minor:Number.parseInt(t[2],10),patch:t[3]?Number.parseInt(t[3],10):0,prerelease:t[4]||t[5]||``}:null},O=(e,t)=>{let n=Xt(e),r=Xt(t);return!n||!r?0:n.major===r.major?n.minor===r.minor?n.patch===r.patch?n.prerelease&&!r.prerelease?-1:!n.prerelease&&r.prerelease?1:0:n.patch-r.patch:n.minor-r.minor:n.major-r.major},Zt=(e,t)=>{let n=Xt(e);if(!n||n.prerelease)return!1;if(t===`*`)return!0;let r=t.trim();if(r.startsWith(`~>`)){let t=r.slice(2).trim(),i=Xt(t);return i?t.split(`.`).length>=3?n.major===i.major&&n.minor===i.minor&&n.patch>=i.patch:n.major===i.major&&n.minor>=i.minor&&O(e,`${i.major}.${i.minor}.0`)>=0:!1}if(r.startsWith(`>=`))return O(e,r.slice(2).trim())>=0;if(r.startsWith(`>`)&&!r.startsWith(`>=`))return O(e,r.slice(1).trim())>0;if(r.startsWith(`<=`))return O(e,r.slice(2).trim())<=0;if(r.startsWith(`<`)&&!r.startsWith(`<=`))return O(e,r.slice(1).trim())<0;if(r.startsWith(`=`)){let e=Xt(r.slice(1).trim());return e?n.major===e.major&&n.minor===e.minor&&n.patch===e.patch:!1}let i=Xt(r);return i?n.major===i.major&&n.minor===i.minor&&n.patch===i.patch:!1},Qt=(e,t)=>{let n=e.filter(e=>Zt(e,t)).sort(O);return n.length>0?n[n.length-1]:null},$t=e=>{if(e.versions.length===0)return null;let t=e.versions[0],n=t.source.includes(`#devDependencies`);return{current:t.resolved,specifier:t.specifier,isDevDependency:n}},en=async(e,t={})=>{let n=t.cache??!0,r=[],i=e.filter(e=>e.versions.some(e=>e.source.includes(`#dependencies`)||e.source.includes(`#devDependencies`))).map(async e=>{let t=$t(e);if(!t)return;let i=await Jt(e.name,!n);if(!i)return;let a=Qt(i.versions,t.specifier),o=i.latest,s=a&&a!==t.current,c=o&&o!==t.current;if(s||c){let n=a||t.current;r.push({...e,wanted:n,latest:o,specifier:t.specifier,isDevDependency:t.isDevDependency,currentDate:i.versionDates?.[t.current],wantedDate:i.versionDates?.[n],latestDate:i.versionDates?.[o]})}});return await Promise.all(i),r}})),nn,rn,an,on=o((()=>{nn=e=>{let t=[],n=e.split(`
3
+ `),r=`dependencies`,i=0;for(let e of n){let n=e.trim();if(n.startsWith(`#`)||n===``)continue;if(n.startsWith(`group `)){(n.includes(`:development`)||n.includes(`:test`))&&(r=`devDependencies`),n.includes(` do`)&&i++;continue}if(n===`end`){i--,i<=0&&(r=`dependencies`,i=0);continue}let a=n.match(/^gem\s+['"]([^'"]+)['"](?:\s*,\s*['"]([^'"]+)['"])?/);if(a){let e=a[1],n=a[2]||`*`;t.push({name:e,specifier:n,group:r})}}return t},rn=e=>{let t={},n={},r=e.split(`
4
+ `),i=`none`,a=null,o=null;for(let e of r){let r=e.trimEnd();if(r===`GEM`){i=`gem`;continue}if(r===`PLATFORMS`){i=`platforms`;continue}if(r===`DEPENDENCIES`){i=`dependencies`;continue}if(r===`BUNDLED WITH`){i=`none`;continue}if(i===`gem`&&r===` specs:`){i=`specs`;continue}if(i===`specs`){if(r===``)continue;let n=e.match(/^(\s*)/),i=n?n[1].length:0,s=e.trim();if(i===4){let e=s.match(/^([^\s(]+)\s+\(([^)]+)\)/);if(e){let n=e[2],r=n.match(/^[\d.]+/),i=r?r[0]:n;a=e[1],o=i,t[a]||(t[a]={version:i,dependencies:{}})}}else if(i===6&&a&&o){let e=s.match(/^([^\s(]+)(?:\s+\(([^)]+)\))?/);if(e){let n=e[1],r=e[2]||`*`;t[a].dependencies[n]=r}}}if(i===`dependencies`){if(r===``||r.startsWith(` `)===!1)continue;let e=r.match(/^\s+([^\s(!]+)(?:\s+\(([^)]+)\))?/);if(e){let t=e[1].replace(/!$/,``);n[t]=e[2]||`*`}}}return{specs:t,dependencies:n}},an=async e=>{let t=`${e.path}/Gemfile`,n=`${e.path}/Gemfile.lock`,r;try{r=await(0,f.readFile)(t,`utf-8`)}catch{return[]}let i=new Map,a=new Set,o=nn(r),s=(e,t,n,r,a,o)=>{let s=i.get(e);s?s.versions.push({resolved:r,specifier:o,source:a}):i.set(e,{id:e,name:t,ecosystem:n,versions:[{resolved:r,specifier:o,source:a}]})};i.set(`rubygems:bundler`,{id:`rubygems:bundler`,name:`bundler`,ecosystem:`system`,versions:[]});for(let e of o)a.add(e.name);let c=null;try{c=await(0,f.readFile)(n,`utf-8`)}catch{}if(c){let e=rn(c);for(let t of o){let n=e.specs[t.name];n&&s(`rubygems:${t.name}`,t.name,`rubygems`,n.version,`.#${t.group}`,t.specifier)}for(let[t,n]of Object.entries(e.specs))if(!a.has(t)){for(let[r,i]of Object.entries(e.specs))if(i.dependencies[t]){let e=`Gemfile.lock:${r}@${i.version}`,a=i.dependencies[t];s(`rubygems:${t}`,t,`rubygems`,n.version,e,a)}}}else for(let e of o)s(`rubygems:${e.name}`,e.name,`rubygems`,e.specifier,`.#${e.group}`,e.specifier);return Array.from(i.values()).sort((e,t)=>e.name.localeCompare(t.name))}})),sn,cn,ln=o((()=>{tt(),tn(),on(),D(),sn=new Map,cn=et({name:`ruby`,actions:async e=>{let t=e.rootFiles,n=t.includes(`Gemfile`),r=t.includes(`Rakefile`),i=t.includes(`config.ru`),a=await E(`${e.path}/config/application.rb`);if(!(n||r))return{};let o={install:[`bundle install`],update:[`bundle update`],outdated:[`bundle outdated`]};return a&&(o.dev=[`bundle exec rails server`],o.repl=[`bundle exec rails console`]),i&&!a&&(o.dev=[`bundle exec rackup`]),o},dependencies:async e=>{if(!e.rootFiles.includes(`Gemfile`))return[];let t=sn.get(e.path);if(t)return t;let n=await an(e);return sn.set(e.path,n),n},outdatedDependencies:async(e,t)=>{if(!e.rootFiles.includes(`Gemfile`))return[];let n=await cn.dependencies?.(e);return n?en(n,t):[]}})})),un,dn,fn,pn,mn,hn,gn,_n,vn=o((()=>{un=3600*1e3,dn=async()=>{let e=`${(0,p.homedir)()}/.cache/denvig/dependencies/pypi`;return await(0,f.mkdir)(e,{recursive:!0}),e},fn=e=>{let t=e.toLowerCase().replace(/[-_.]+/g,`-`);return t=t.replace(/[^a-zA-Z0-9-]/g,`_`),t=t.replace(/\.{2,}/g,`_`),t=t.replace(/^\.+/,`_`),t.length===0&&(t=`_empty_`),t.length>200&&(t=t.slice(0,200)),t},pn=async e=>{let t=fn(e);return`${await dn()}/${t}.json`},mn=async e=>{try{let t=await(0,f.stat)(e);return Date.now()-t.mtimeMs<un}catch{return!1}},hn=async e=>{let t=await pn(e);if(!await mn(t))return null;try{let e=await(0,f.readFile)(t,`utf-8`),n=JSON.parse(e);return n.versionDates?n:null}catch{return null}},gn=async(e,t)=>{try{await(0,f.writeFile)(await pn(e),JSON.stringify(t),`utf-8`)}catch{}},_n=async(e,t=!1)=>{let n=e.toLowerCase().replace(/_/g,`-`);if(!t){let e=await hn(n);if(e)return e}try{let e=await fetch(`https://pypi.org/pypi/${encodeURIComponent(n)}/json`,{headers:{Accept:`application/json`}});if(!e.ok)return null;let t=await e.json(),r=Object.entries(t.releases).filter(([,e])=>e.length>0).map(([e])=>e),i=t.info?.version||r[r.length-1],a={};for(let[e,n]of Object.entries(t.releases))n.length>0&&n[0].upload_time_iso_8601&&(a[e]=n[0].upload_time_iso_8601);let o={versions:r,latest:i,versionDates:a};return await gn(n,o),o}catch{return null}}})),k,yn,bn,xn,Sn,Cn,wn,Tn=o((()=>{vn(),k=e=>{let t=e.match(/^(\d+)\.(\d+)(?:\.(\d+))?(?:\.(\d+))?(.*)$/);return t?{major:Number.parseInt(t[1],10),minor:Number.parseInt(t[2],10),patch:t[3]?Number.parseInt(t[3],10):0,prerelease:t[5]||``}:null},yn=(e,t)=>{let n=k(e),r=k(t);return!n||!r?0:n.major===r.major?n.minor===r.minor?n.patch===r.patch?n.prerelease&&!r.prerelease?-1:!n.prerelease&&r.prerelease?1:0:n.patch-r.patch:n.minor-r.minor:n.major-r.major},bn=e=>/[a-zA-Z]/.test(e),xn=(e,t)=>{let n=k(e);if(!n||bn(e))return!1;if(t===`*`)return!0;if(t.startsWith(`~=`)){let e=t.slice(2).trim(),r=k(e);return r?e.split(`.`).length>=3?n.major===r.major&&n.minor===r.minor&&n.patch>=r.patch:n.major===r.major&&n.minor>=r.minor:!1}if(t.startsWith(`>=`))return yn(e,t.slice(2).trim())>=0;if(t.startsWith(`>`)&&!t.startsWith(`>=`))return yn(e,t.slice(1).trim())>0;if(t.startsWith(`<=`))return yn(e,t.slice(2).trim())<=0;if(t.startsWith(`<`)&&!t.startsWith(`<=`))return yn(e,t.slice(1).trim())<0;if(t.startsWith(`!=`))return yn(e,t.slice(2).trim())!==0;if(t.startsWith(`==`)){let r=t.slice(2).trim();if(r.endsWith(`.*`)){let t=r.slice(0,-2);return e.startsWith(t)}let i=k(r);return i?n.major===i.major&&n.minor===i.minor&&n.patch===i.patch:!1}let r=k(t);return r?n.major===r.major&&n.minor===r.minor&&n.patch===r.patch:!1},Sn=(e,t)=>{let n=e.filter(e=>xn(e,t)).sort(yn);return n.length>0?n[n.length-1]:null},Cn=e=>{if(e.versions.length===0)return null;let t=e.versions[0],n=t.source.includes(`#devDependencies`);return{current:t.resolved,specifier:t.specifier,isDevDependency:n}},wn=async(e,t={})=>{let n=t.cache??!0,r=[],i=e.filter(e=>e.versions.some(e=>e.source.includes(`#dependencies`)||e.source.includes(`#devDependencies`))).map(async e=>{let t=Cn(e);if(!t)return;let i=await _n(e.name,!n);if(!i)return;let a=Sn(i.versions,t.specifier),o=i.latest,s=a&&a!==t.current,c=o&&o!==t.current;if(s||c){let n=a||t.current;r.push({...e,wanted:n,latest:o,specifier:t.specifier,isDevDependency:t.isDevDependency,currentDate:i.versionDates?.[t.current],wantedDate:i.versionDates?.[n],latestDate:i.versionDates?.[o]})}});return await Promise.all(i),r}})),En,Dn,On,kn,An,jn,Mn,Nn=o((()=>{En=e=>{let t=e.trim();return t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`)?t.slice(1,-1):t},Dn=e=>{let t=e.trim();return t===`true`?!0:t===`false`?!1:/^-?\d+$/.test(t)?Number.parseInt(t,10):/^-?\d+\.\d+$/.test(t)?Number.parseFloat(t):En(t)},On=e=>{let t={},n=e.slice(1,-1).trim();if(!n)return t;let r=[],i=``,a=0,o=!1,s=``;for(let e=0;e<n.length;e++){let t=n[e];if(!o&&(t===`"`||t===`'`)?(o=!0,s=t):o&&t===s&&n[e-1]!==`\\`&&(o=!1),!o){if(t===`{`||t===`[`)a++;else if(t===`}`||t===`]`)a--;else if(t===`,`&&a===0){r.push(i.trim()),i=``;continue}}i+=t}i.trim()&&r.push(i.trim());for(let e of r){let n=e.indexOf(`=`);if(n===-1)continue;let r=e.slice(0,n).trim(),i=e.slice(n+1).trim();i.startsWith(`{`)?t[r]=On(i):i.startsWith(`[`)?t[r]=kn(i):t[r]=Dn(i)}return t},kn=e=>{let t=[],n=e.slice(1,-1).trim();if(!n)return t;let r=[],i=``,a=0,o=!1,s=``;for(let e=0;e<n.length;e++){let t=n[e];if(!o&&(t===`"`||t===`'`)?(o=!0,s=t):o&&t===s&&n[e-1]!==`\\`&&(o=!1),!o){if(t===`{`||t===`[`)a++;else if(t===`}`||t===`]`)a--;else if(t===`,`&&a===0){r.push(i.trim()),i=``;continue}}i+=t}i.trim()&&r.push(i.trim());for(let e of r){let n=e.trim();n.startsWith(`{`)?t.push(On(n)):n.startsWith(`[`)?t.push(kn(n)):t.push(Dn(n))}return t},An=(e,t,n)=>{let r=e;for(let e=0;e<t.length-1;e++){let n=t[e];(!(n in r)||typeof r[n]!=`object`)&&(r[n]={}),r=r[n]}r[t[t.length-1]]=n},jn=(e,t)=>{let n=e;for(let e of t)(!(e in n)||typeof n[e]!=`object`)&&(n[e]={}),n=n[e];return n},Mn=e=>{let t={},n=e.split(`
5
+ `),r=[],i=null,a=null,o=null,s=null;for(let e=0;e<n.length;e++){let c=n[e];if(o!==null&&s!==null){if(o+=c,c.includes(`]`)){let e=0,n=-1;for(let t=0;t<o.length;t++)if(o[t]===`[`)e++;else if(o[t]===`]`&&(e--,e===0)){n=t;break}if(n!==-1){let e=kn(o.slice(0,n+1));a?a[s]=e:An(t,[...r,s],e),o=null,s=null}}continue}let l=c.indexOf(`#`);if(l!==-1){let e=!1,t=``;for(let n=0;n<l;n++){let r=c[n];!e&&(r===`"`||r===`'`)?(e=!0,t=r):e&&r===t&&c[n-1]!==`\\`&&(e=!1)}e||(c=c.slice(0,l))}if(c=c.trim(),!c)continue;if(c.startsWith(`[[`)&&c.endsWith(`]]`)){if(a&&i){let e=jn(t,i.slice(0,-1)),n=i[i.length-1];Array.isArray(e[n])||(e[n]=[]),e[n].push(a)}i=c.slice(2,-2).split(`.`),a={},r=[];continue}if(c.startsWith(`[`)&&c.endsWith(`]`)){if(a&&i){let e=jn(t,i.slice(0,-1)),n=i[i.length-1];Array.isArray(e[n])||(e[n]=[]),e[n].push(a),a=null,i=null}r=c.slice(1,-1).split(`.`),jn(t,r);continue}let u=c.indexOf(`=`);if(u===-1)continue;let d=c.slice(0,u).trim(),f=c.slice(u+1).trim();if(f.startsWith(`[`)&&!f.endsWith(`]`)){o=f,s=d;continue}let p;p=f.startsWith(`{`)?On(f):f.startsWith(`[`)?kn(f):Dn(f),a?a[d]=p:An(t,[...r,d],p)}if(a&&i){let e=jn(t,i.slice(0,-1)),n=i[i.length-1];Array.isArray(e[n])||(e[n]=[]),e[n].push(a)}return t}})),Pn,Fn,In,Ln,Rn,zn=o((()=>{Nn(),Pn=e=>e.toLowerCase().replace(/_/g,`-`),Fn=e=>{let t=e.match(/^([a-zA-Z0-9_-]+(?:\[[^\]]+\])?)(.*)$/);return t?{name:t[1].replace(/\[.*\]$/,``),specifier:t[2].trim()||`*`}:{name:e,specifier:`*`}},In=e=>{let t=[];try{let n=Mn(e);if(n.project?.dependencies)for(let e of n.project.dependencies){let{name:n,specifier:r}=Fn(e);t.push({name:n,specifier:r,group:`dependencies`})}if(n.tool?.uv?.[`dev-dependencies`])for(let e of n.tool.uv[`dev-dependencies`]){let{name:n,specifier:r}=Fn(e);t.push({name:n,specifier:r,group:`devDependencies`})}if(n.project?.[`optional-dependencies`])for(let e of Object.values(n.project[`optional-dependencies`]))for(let n of e){let{name:e,specifier:r}=Fn(n);t.push({name:e,specifier:r,group:`devDependencies`})}}catch{}return t},Ln=e=>{let t={},n=null;try{let r=Mn(e);if(r.package)for(let e of r.package){let r=Pn(e.name);e.source?.virtual&&(n=r);let i=e.dependencies?.map(e=>Pn(e.name))||[];t[r]={name:e.name,version:e.version,dependencies:i}}}catch{}return{packages:t,projectName:n}},Rn=async e=>{let t=`${e.path}/pyproject.toml`,n=`${e.path}/uv.lock`,r;try{r=await(0,f.readFile)(t,`utf-8`)}catch{return[]}let i=new Map,a=new Set,o=(e,t,n,r,a,o)=>{let s=i.get(e);s?s.versions.push({resolved:r,specifier:o,source:a}):i.set(e,{id:e,name:t,ecosystem:n,versions:[{resolved:r,specifier:o,source:a}]})};i.set(`pypi:uv`,{id:`pypi:uv`,name:`uv`,ecosystem:`system`,versions:[]});let s=In(r);for(let e of s)a.add(Pn(e.name));let c=null;try{c=await(0,f.readFile)(n,`utf-8`)}catch{}if(c){let e=Ln(c);for(let t of s){let n=Pn(t.name),r=e.packages[n];r&&o(`pypi:${n}`,r.name,`pypi`,r.version,`.#${t.group}`,t.specifier)}for(let[t,n]of Object.entries(e.packages))if(!(t===e.projectName||a.has(t))){for(let[,r]of Object.entries(e.packages))if(r.dependencies.includes(t)){let e=`uv.lock:${r.name}@${r.version}`;o(`pypi:${t}`,n.name,`pypi`,n.version,e,`*`)}}}else for(let e of s)o(`pypi:${Pn(e.name)}`,e.name,`pypi`,e.specifier,`.#${e.group}`,e.specifier);return Array.from(i.values()).sort((e,t)=>e.name.localeCompare(t.name))}})),Bn,Vn,Hn=o((()=>{tt(),Tn(),zn(),Bn=new Map,Vn=et({name:`uv`,actions:async e=>{let t=e.rootFiles,n=t.includes(`pyproject.toml`);return t.includes(`uv.lock`)||n?{install:[`uv sync`]}:{}},dependencies:async e=>{let t=e.rootFiles.includes(`pyproject.toml`),n=e.rootFiles.includes(`uv.lock`);if(!t&&!n)return[];let r=Bn.get(e.path);if(r)return r;let i=await Rn(e);return Bn.set(e.path,i),i},outdatedDependencies:async(e,t)=>{if(!e.rootFiles.includes(`pyproject.toml`))return[];let n=await Vn.dependencies?.(e);return n?wn(n,t):[]}})})),Un,Wn,Gn=o((()=>{vt(),Un=e=>{let t=e.split(`
6
+
7
+ `),n={};for(let e of t){let t=e.split(`
8
+ `);if(t.length<3)continue;let r=t[0].split(`,`).map(e=>e.trim().replace(/"|:/g,``)),i=t[1]?.match(/version "(.+)"/)?.[1],a=t[2]?.match(/resolved "(.+)"/)?.[1];if(!(!i||!a))for(let e of r)e&&(n[e]={version:i,resolved:a})}return{type:`success`,object:n}},Wn=e=>{let t={},n=Un(e);for(let[e,r]of Object.entries(n.object)){let[,n,i]=e.match(/^(@?.+)@(.+)$/)||[];t[n]||(t[n]={versions:{}}),t[n].versions[r.version]||(t[n].versions[r.version]=[]),t[n].versions[r.version]=[...t[n].versions[r.version],i].sort((e,t)=>e.localeCompare(t,void 0,{numeric:!0})),t[n].versions=Object.fromEntries(Object.entries(t[n].versions).sort((e,t)=>e[0].localeCompare(t[0],void 0,{numeric:!0})))}for(let[e,n]of Object.entries(t))t[e].optimisedVersions=_t(n.versions);return{dependencies:t}}})),Kn,qn=o((()=>{Kn=(e,t)=>{let n=[],r=e.split(`
9
+
10
+ `);for(let e of r){let r=e.split(`
11
+ `);if(r.length<3){n.push(e);continue}let i=r[0].split(`,`).map(e=>e.trim().replace(/"|:/g,``)),a=r[1]?.match(/version "(.+)"/)?.[1],o=r[2]?.match(/resolved "(.+)"/)?.[1],s=/^(@?.+)@(.+)$/;if(!a||!o||i.length===0){n.push(e);continue}let[,c]=i[0].match(s)||[];t[c]?.includes(a)||n.push(e)}return n.join(`
12
+
13
+ `)}})),Jn,Yn,Xn=o((()=>{Jn=e=>{let t=e.split(`
14
+
15
+ `),n={};for(let e of t){let t=e.split(`
16
+ `);if(t.length<3)continue;let r=t[0].split(`,`).map(e=>e.trim().replace(/"|:/g,``)),i=t[1]?.match(/version "(.+)"/)?.[1],a=t[2]?.match(/resolved "(.+)"/)?.[1];if(!i||!a)continue;let o={},s=!1;for(let e=3;e<t.length;e++){let n=t[e];if(n.trim()===`dependencies:`){s=!0;continue}if(s&&n.startsWith(` `)){let e=n.trim().match(/^"?([^"\s]+)"?\s+"?([^"]+)"?$/);e&&(o[e[1]]=e[2])}else s&&!n.startsWith(` `)&&(s=!1)}for(let e of r)e&&(n[e]={version:i,resolved:a,dependencies:Object.keys(o).length>0?o:void 0})}return{type:`success`,object:n}},Yn=e=>{let t={},n=Jn(e),r=new Map;for(let[e,t]of Object.entries(n.object)){let[,n,i]=e.match(/^(@?.+)@(.+)$/)||[];n&&(r.has(n)||r.set(n,[]),r.get(n)?.push({version:t.version,specifier:i,deps:t.dependencies}))}for(let[e,n]of r.entries()){t[e]||(t[e]={versions:{}});for(let r of n)t[e].versions[r.version]||(t[e].versions[r.version]={}),t[e].versions[r.version][`yarn.lock`]=r.specifier;t[e].versions=Object.fromEntries(Object.entries(t[e].versions).sort((e,t)=>e[0].localeCompare(t[0],void 0,{numeric:!0})))}for(let[e,n]of r.entries())for(let i of n){if(!i.deps)continue;let n=`${e}@${i.version}`;for(let[e,a]of Object.entries(i.deps)){t[e]||(t[e]={versions:{}});let i=r.get(e);if(!i)continue;let o=i.find(e=>e.specifier===a)?.version||i[0]?.version;if(o){t[e].versions[o]||(t[e].versions[o]={});let r=`yarn.lock:${n}`;t[e].versions[o][r]=a}}}return{dependencies:t}}}));function Zn(e){return e.includes(`__metadata:`)}function Qn(e){let t=e.match(/^(.+)@npm:/);if(t)return t[1];let n=e.lastIndexOf(`@`);return n>0?e.slice(0,n):e}var $n,er,tr=o((()=>{ht(),Gn(),qn(),Ve(),$e(),Xn(),tt(),D(),$n=new Map,er=et({name:`yarn`,actions:async e=>{let t=e.rootFiles.includes(`package.json`),n=e.rootFiles.includes(`yarn.lock`);if(!(t&&n))return{};let r=(await Qe(e))?.scripts||{};return{...Object.entries(r).map(([e,t])=>[e,`yarn run ${e}`]).reduce((e,[t,n])=>(e[t]=[n],e),{}),install:[`yarn install`],outdated:[`yarn outdated`]}},dependencies:async e=>{let t=`${e.path}/yarn.lock`,n=`${e.path}/package.json`;if(!await E(t)||!await E(n))return[];let r=$n.get(e.path);if(r)return r;let i=new Map,a=new Set,o=(e,t,n,r,a,o)=>{let s=i.get(e);s?s.versions.push({resolved:r,specifier:o,source:a}):i.set(e,{id:e,name:t,ecosystem:n,versions:[{resolved:r,specifier:o,source:a}]})};i.set(`npm:yarn`,{id:`npm:yarn`,name:`yarn`,ecosystem:`system`,versions:[]});let s=await(0,f.readFile)(t,`utf-8`),c=Zn(s),l=new Map,u=new Map,d=null;if(c){let e=(0,h.parse)(s);for(let[t,n]of Object.entries(e)){if(t===`__metadata`||!n?.version||typeof n.version!=`string`)continue;let e=Qn(t),r=n;l.has(e)||l.set(e,new Map);let i=t.match(/@npm:(.+)$/);i&&l.get(e)?.set(i[1],n.version),r.dependencies&&u.set(`${e}@${r.version}`,r.dependencies)}}else{d=Yn(s);for(let[e,t]of Object.entries(d.dependencies)){l.has(e)||l.set(e,new Map);for(let[n,r]of Object.entries(t.versions)){let t=r[`yarn.lock`];t&&l.get(e)?.set(t,n)}}}let p=[n],m=await e.findFilesByName(`package.json`);p.push(...m);for(let t of p)try{let r=await(0,f.readFile)(t,`utf-8`),i=JSON.parse(r),s=`.`;t!==n&&(s=t.replace(`${e.path}/`,``).replace(`/package.json`,``));let c=(e,t)=>{if(e)for(let[n,r]of Object.entries(e)){a.add(n);let e=l.get(n),i=r;if(e){let t=e.get(r);if(t)i=t;else{let t=e.values().next().value;t&&(i=t)}}o(`npm:${n}`,n,`npm`,i,`${s}#${t}`,r)}};c(i.dependencies,`dependencies`),c(i.devDependencies,`devDependencies`)}catch{}if(c){for(let[e,t]of u.entries())for(let[n,r]of Object.entries(t))if(!a.has(n)){let t=l.get(n),i=r;if(t){let e=t.get(r);if(e)i=e;else{let e=t.values().next().value;e&&(i=e)}}let a=`yarn.lock:${e}`;o(`npm:${n}`,n,`npm`,i,a,r)}}else if(d){for(let[e,t]of Object.entries(d.dependencies))if(!a.has(e))for(let[n,r]of Object.entries(t.versions))for(let[t,i]of Object.entries(r))t.startsWith(`yarn.lock:`)&&o(`npm:${e}`,e,`npm`,n,t,i)}let g=Array.from(i.values()).sort((e,t)=>e.name.localeCompare(t.name));return $n.set(e.path,g),g},outdatedDependencies:async(e,t)=>{if(!await E(`${e.path}/yarn.lock`))return[];let n=await er.dependencies?.(e);return n?Be(n,t):[]},deduplicateDependencies:async(e,t)=>{let n=`${e.path}/yarn.lock`;if(!await E(n))return null;let r=await(0,f.readFile)(n,`utf-8`),i=pt(Wn(r)),a=t?.dryRun??!1,o=!1;return!a&&Object.keys(i.removals).length>0&&(await mt(n,Kn(r,i.removals),`yarn`),o=!0),{ecosystem:`yarn.lock`,...i,applied:o}}})})),nr,rr=o((()=>{ut(),ft(),Bt(),ln(),Hn(),tr(),nr={deno:lt,npm:dt,pnpm:zt,ruby:cn,uv:Vn,yarn:er}})),ir,ar,or=o((()=>{rr(),ir=async e=>{let t=[];if(e.config.actions)for(let[n,r]of Object.entries(e.config.actions))t.push({name:n,ecosystem:`project`,commands:[r.command]});for(let[n,r]of Object.entries(nr)){let i=await r.actions(e);for(let[e,a]of Object.entries(i))t.push({name:e,ecosystem:r.name??n,commands:a})}return t},ar=(e,t,n)=>{let r=t,i=n,a=t.indexOf(`:`);a!==-1&&!e.some(e=>e.name===t)&&(i=t.slice(0,a),r=t.slice(a+1));let o=e.filter(e=>e.name===r);if(o.length===0)throw new b(`Action "${t}" not found.`);if(i){let e=o.find(e=>e.ecosystem===i);if(!e)throw new b(`Action "${r}" not found for ecosystem "${i}".`);return e}return{name:r,ecosystem:o[0].ecosystem,commands:o.flatMap(e=>e.commands)}}}));function sr(){return`gui/${process.getuid?.()??501}`}async function cr(e){try{let{stdout:t,stderr:n}=await A(`launchctl bootstrap ${sr()} "${e}"`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function lr(e){try{let{stdout:t,stderr:n}=await A(`launchctl bootout ${sr()}/${e}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function ur(e){try{let{stdout:t,stderr:n}=await A(`launchctl start ${e}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function dr(e){try{let{stdout:t,stderr:n}=await A(`launchctl stop ${e}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function fr(e){try{let{stdout:t,stderr:n}=await A(`launchctl enable ${sr()}/${e}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function pr(e){try{let{stdout:t,stderr:n}=await A(`launchctl disable ${sr()}/${e}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function mr(e){try{let{stdout:t}=await A(`launchctl print ${sr()}/${e}`),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:e,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 hr(e){try{let{stdout:t}=await A(`launchctl list`),n=t.trim().split(`
17
+ `).slice(1).map(e=>{let t=e.trim().split(/\s+/);return t.length<3?null:{pid:t[0]===`-`?`-`:parseInt(t[0],10),status:parseInt(t[1],10),label:t[2]}}).filter(e=>e!==null);return e?n.filter(t=>t.label.includes(e)):n}catch{return[]}}var A,j,gr=o((()=>{A=(0,u.promisify)(d.exec),j={bootstrap:cr,bootout:lr,enable:fr,disable:pr,start:ur,stop:dr,print:mr,list:hr,getUserDomain:sr}})),_r,vr,yr,br,M,xr,N,Sr,Cr,wr,Tr,Er,Dr,P,Or,kr,Ar,jr,F,Mr,Nr,Pr,Fr,Ir,Lr,Rr,zr=o((()=>{D(),vr=async()=>(_r||=(await import(`node-forge`)).default,_r),yr=process.env.HOME||``,br=()=>(0,m.resolve)(`${yr}/.denvig/ca`),M=()=>(0,m.resolve)(`${yr}/.denvig/certs`),xr=()=>(0,m.resolve)(br(),`rootCA-key.pem`),N=()=>(0,m.resolve)(br(),`rootCA.pem`),Sr=e=>{let t=e.replace(/^\*/,`_wildcard`);return(0,m.resolve)(M(),t)},Cr=async()=>{let e=await vr(),[t,n]=await Promise.all([(0,f.readFile)(N(),`utf-8`),(0,f.readFile)(xr(),`utf-8`)]);return{cert:e.pki.certificateFromPem(t),key:e.pki.privateKeyFromPem(n)}},wr=async()=>{let e=await vr(),t=e.pki.rsa.generateKeyPair(2048),n=e.pki.createCertificate();n.publicKey=t.publicKey,n.serialNumber=await Ir();let r=new Date;n.validity.notBefore=r,n.validity.notAfter=new Date(r.getFullYear()+10,r.getMonth(),r.getDate());let i=[{name:`organizationName`,value:`denvig.com`},{name:`commonName`,value:`Denvig Local CA`}];return n.setSubject(i),n.setIssuer(i),n.setExtensions([{name:`basicConstraints`,cA:!0,critical:!0},{name:`keyUsage`,keyCertSign:!0,cRLSign:!0,critical:!0}]),n.sign(t.privateKey,e.md.sha256.create()),{cert:n,key:t.privateKey,certPem:e.pki.certificateToPem(n),keyPem:e.pki.privateKeyToPem(t.privateKey)}},Tr=async(e,t,n)=>{let r=await vr(),i=r.pki.rsa.generateKeyPair(2048),a=r.pki.createCertificate();a.publicKey=i.publicKey,a.serialNumber=await Ir();let o=new Date;a.validity.notBefore=o,a.validity.notAfter=new Date(o.getTime()+720*24*60*60*1e3),a.setSubject([{name:`commonName`,value:e}]),a.setIssuer(t.subject.attributes),a.setExtensions([{name:`basicConstraints`,cA:!1},{name:`keyUsage`,digitalSignature:!0,keyEncipherment:!0,critical:!0},{name:`extKeyUsage`,serverAuth:!0},{name:`subjectAltName`,altNames:[{type:2,value:e}]}]),a.sign(n,r.md.sha256.create());let s=r.pki.certificateToPem(a),c=r.pki.certificateToPem(t);return{privkey:r.pki.privateKeyToPem(i.privateKey),fullchain:s+c}},Er=e=>{(0,d.execSync)(`sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${e}`,{stdio:`inherit`})},Dr=e=>{(0,d.execSync)(`sudo security remove-trusted-cert -d ${e}`,{stdio:`inherit`})},P=e=>{let t=e.match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/);return t?t[0]:e},Or=e=>{let t=new _.X509Certificate(P(e)),n=[],r=t.subjectAltName;if(r)for(let e of r.split(`,`)){let t=e.trim();t.startsWith(`DNS:`)&&n.push(t.slice(4))}if(n.length===0){let e=t.subject.match(/CN=([^,\n]+)/);e&&n.push(e[1])}return n},kr=e=>{let t=new _.X509Certificate(P(e));return new Date(t.validTo)},Ar=async(e,t)=>{await(0,f.mkdir)(br(),{recursive:!0}),await Promise.all([(0,f.writeFile)(xr(),t,{mode:384}),(0,f.writeFile)(N(),e)])},jr=async(e,t,n)=>{let r=Sr(e);return await(0,f.mkdir)(r,{recursive:!0}),await Promise.all([(0,f.writeFile)((0,m.resolve)(r,`privkey.pem`),t,{mode:384}),(0,f.writeFile)((0,m.resolve)(r,`fullchain.pem`),n)]),r},F=async()=>{let[e,t]=await Promise.all([E(N()),E(xr())]);return e&&t},Mr=async()=>{let e=N();return await E(e)?(0,d.spawnSync)(`security`,[`verify-cert`,`-c`,e],{stdio:`pipe`}).status===0:!1},Nr=(e,t)=>{try{let n=new _.X509Certificate(P(e)),r=new _.X509Certificate(P(t));return n.checkIssued(r)&&n.verify(r.publicKey)}catch{return!1}},Pr=e=>{try{let t=new _.X509Certificate(P(e));return t.issuer.includes(`CN=Denvig Local CA`)&&t.issuer.includes(`O=denvig.com`)}catch{return!1}},Fr=e=>{try{let t=new _.X509Certificate(P(e)).issuer.match(/CN=([^,\n]+)/);return t?t[1]:null}catch{return null}},Ir=async()=>{let e=await vr();return e.util.bytesToHex(e.random.getBytesSync(16))},Lr=e=>{let t=(0,m.resolve)(e,`fullchain.pem`),n=(0,m.resolve)(e,`cert.pem`);try{return(0,v.statSync)(t),t}catch{}try{return(0,v.statSync)(n),n}catch{}return null},Rr=(e,t=new Date)=>{let n=M(),r;try{r=(0,v.readdirSync)(n).filter(e=>{try{return(0,v.statSync)((0,m.resolve)(n,e)).isDirectory()}catch{return!1}})}catch{return 0}let i=t.getTime()+e,a=0;for(let e of r){let t=Lr((0,m.resolve)(n,e));if(t)try{kr((0,v.readFileSync)(t,`utf-8`)).getTime()<=i&&a++}catch{}}return a}}));function Br(e,t){return!!(e===t||t.startsWith(`*.`)&&e.endsWith(t.slice(1))&&!e.slice(0,-t.length+1).includes(`.`))}async function Vr(e){let t=M();if(!await E(t))return null;let n;try{n=(await(0,f.readdir)(t,{withFileTypes:!0})).filter(e=>e.isDirectory()).map(e=>e.name)}catch{return null}for(let r of n){let n=(0,m.resolve)(t,r,`fullchain.pem`);if(await E(n))try{if(Or(await(0,f.readFile)(n,`utf-8`)).some(t=>Br(e,t)))return(0,m.resolve)(t,r)}catch{}}return null}function Hr(e){let t=e.split(`.`);return t.length<=2?e:t.slice(1).join(`.`)}function Ur(e){let t=new Map;for(let n of e){let e=Hr(n);t.has(e)||t.set(e,[]),t.get(e)?.push(n)}let n=new Map;for(let[e,r]of t)if(r.some(t=>t!==e)&&r.length>=2)n.set(`*.${e}`,r);else for(let e of r)n.set(e,[e]);return n}async function Wr(e){let t=new Map,n=[];for(let r of e){let e=await Vr(r);e?t.set(r,e):n.push(r)}if(n.length===0||!await F())return t;let{cert:r,key:i}=await Cr(),a=Ur(n);for(let[e,n]of a){let{privkey:a,fullchain:o}=await Tr(e,r,i),s=await jr(e,a,o);for(let e of n)t.set(e,s)}return t}async function Gr(e){let t=(0,m.resolve)(e,`fullchain.pem`),n=(0,m.resolve)(e,`privkey.pem`),[r,i]=await Promise.all([E(t),E(n)]);return r&&i?{sslCertPath:t,sslKeyPath:n}:null}var Kr=o((()=>{zr(),D()})),qr,Jr,Yr,Xr,Zr,Qr,$r=o((()=>{qr=[`build`,`check-types`,`dev`,`install`,`lint`,`outdated`,`test`],Jr=y.z.string().max(64,`Service name must be 64 characters or less`).regex(/^[a-z]([a-z0-9-]*[a-z0-9])?$/,`Service name must start with a letter, contain only lowercase alphanumeric and hyphens, and not end with a hyphen`),Yr=y.z.object({cwd:y.z.string().optional().describe(`Working directory for the service (relative to project root)`),command:y.z.string().describe(`Shell command to execute`),http:y.z.object({port:y.z.number().optional().describe(`Port number the service listens on`),domain:y.z.string().optional().describe(`Domain to use for the service URL`),cnames:y.z.array(y.z.string()).optional().describe(`Additional hosts that can be used via gateway`),secure:y.z.boolean().optional().describe(`Use HTTPS instead of HTTP`)}).optional().describe(`HTTP configuration for the service URL`),envFiles:y.z.array(y.z.string()).optional().describe(`Paths to .env files (relative to service cwd)`),env:y.z.record(y.z.string(),y.z.string()).optional().describe(`Environment variables`),keepAlive:y.z.boolean().optional().describe(`Restart service if it exits`),startOnBoot:y.z.boolean().optional().describe(`Start service automatically when system boots`)}),Xr=y.z.record(Jr,Yr).optional().describe(`Services that can be managed`),Zr=y.z.object({projectPaths:y.z.array(y.z.string()).optional().default([`~/src/*/*`,`~/.dotfiles`]).describe(`Paths or patterns where projects are located`),quickActions:y.z.array(y.z.string()).default(qr).optional().describe(`Quick actions that are available for all projects`),services:Xr.describe(`Global services that can be managed from any directory`),experimental:y.z.object({gateway:y.z.object({enabled:y.z.boolean(),handler:y.z.enum([`nginx`]).default(`nginx`),configsPath:y.z.string().default(`/opt/homebrew/etc/nginx/servers`)}).optional()}).optional()}),Qr=y.z.object({name:y.z.string().optional().describe(`Display name for the project`),actions:y.z.record(y.z.string().describe(`Name of the action`),y.z.object({command:y.z.string().describe(`Shell command to run for the action`)})).optional().describe(`Actions that can be run against the project`),quickActions:y.z.array(y.z.string()).optional().describe(`Actions that are available on the CLI root for quick access`),services:Xr})})),ei,ti,ni,ri,ii,ai,I,oi,L=o((()=>{$r(),D(),ei=(0,m.resolve)(`${process.env.HOME}/.denvig/config.yml`),ti={projectPaths:[`~/src/*/*`,`~/.dotfiles`],quickActions:void 0},ni=e=>e.startsWith(`~/`)?`${process.env.HOME}${e.slice(1)}`:e,ri=()=>{let e={},t=process.env.DENVIG_PROJECT_PATHS;t!==void 0&&(e.projectPaths=t.split(`,`).map(e=>e.trim()).filter(e=>e.length>0));let n=process.env.DENVIG_QUICK_ACTIONS;return n!==void 0&&(n===``?e.quickActions=[]:e.quickActions=n.split(`,`).map(e=>e.trim()).filter(e=>e.length>0)),e},ii=(e,t)=>{let n=[],r={};if(e)try{let i=(0,h.parse)(e)||{};r={...r,...i},n.push(t)}catch(e){console.error(`Error parsing global config at ${t}:`,e),process.exit(1)}let i=ri();return r={...r,...i},{...Zr.parse({...ti,...r}),$sources:n}},ai=()=>{let e=process.env.DENVIG_GLOBAL_CONFIG_PATH;return e?(0,m.resolve)(e):ei},I=async()=>{let e=ai();return ii(await nt(e),e)},oi=async e=>{let t=`${e}/.denvig.yml`,n=await nt(t);if(n)try{return{...Qr.parse((0,h.parse)(n)),$sources:[t]}}catch{}return{$sources:[]}}})),R,z=o((()=>{R=(e,t,n={})=>new Promise(r=>{let i=(0,d.spawn)(e,t,{cwd:n.cwd,stdio:n.stdio??`inherit`});i.on(`close`,e=>r(e===0)),i.on(`error`,()=>r(!1))})})),si,ci,li,ui,di,fi,pi,mi,hi,gi,_i,vi,yi,bi=o((()=>{z(),si=(0,u.promisify)(d.execFile),ci=e=>{let t=e.match(/^git@github\.com:([^/\s]+)\/([^/\s]+?)(?:\.git)?$/);if(t)return`${t[1]}/${t[2]}`;let n=e.match(/^https:\/\/github\.com\/([^/\s]+)\/([^/\s]+?)(?:\.git)?$/);return n?`${n[1]}/${n[2]}`:null},li=async e=>{let t=m.default.join(e,`.git`,`config`);try{let e=await(0,f.readFile)(t,`utf-8`);for(let t of[`origin`,`github`]){let n=e.match(RegExp(`\\[remote "${t}"\\][^[]*url\\s*=\\s*([^\\s\\n]+)`));if(n){let e=ci(n[1]);if(e)return e}}return null}catch{return null}},ui=(e,t)=>R(`git`,[`clone`,e,t]),di=e=>R(`git`,[`pull`],{cwd:e}),fi=async e=>{try{let{stdout:t}=await si(`git`,[`status`,`--porcelain`],{cwd:e});return t.trim().length>0}catch{return!1}},pi=e=>{let t=e.replace(/\.git$/,``),n=t.match(/^[a-z][a-z0-9+.-]*:\/\/(?:[^@/]+@)?([^/]+)\/(.+)$/i);if(n)return`${n[1]}/${n[2]}`;let r=t.match(/^(?:[^@\s/]+@)?([^:\s/]+):(.+)$/);return r?`${r[1]}/${r[2]}`:null},mi=e=>{let t=e?.match(/^github\.com\/(.+\/.+)$/);return t?t[1]:null},hi=e=>{let t=(0,m.resolve)(e);for(;;){let e=(0,m.resolve)(t,`.git`);try{return(0,v.statSync)(e).isFile()?t:null}catch{}let n=(0,m.resolve)(t,`..`);if(n===t)return null;t=n}},gi=e=>{let t=_i((0,m.resolve)(e));if(!t)return[];let n=`${t.primaryGitDir}/worktrees`,r;try{r=(0,v.readdirSync)(n,{withFileTypes:!0})}catch{return[]}let i=[];for(let e of r){if(!e.isDirectory())continue;let t=`${n}/${e.name}`,r=vi(t);if(!r)continue;let a;try{a=(0,v.readFileSync)(`${t}/gitdir`,`utf-8`).trim()}catch{continue}let o=a.replace(/\/\.git$/,``);i.push({path:o,branch:r})}return i.sort((e,t)=>e.path.localeCompare(t.path))},_i=e=>{let t=(0,m.resolve)(e,`.git`),n;try{n=(0,v.statSync)(t)}catch{return null}let r,i;if(n.isFile()){let e;try{e=(0,v.readFileSync)(t,`utf-8`).trim()}catch{return null}let n=e.match(/^gitdir:\s*(.+)\/\.git\/worktrees\/([^/]+)$/);if(!n)return null;let a=n[1],o=`${a}/.git/worktrees/${n[2]}`;r=`${a}/.git`;let s=vi(o);if(!s)return null;i={primaryPath:a,branch:s}}else if(n.isDirectory()){let n;try{n=(0,v.realpathSync)(e)}catch{n=e}r=t,i={primaryPath:n,branch:`main`}}else return null;return{primaryGitDir:r,remotes:yi(`${r}/config`),worktree:i}},vi=e=>{try{let t=(0,v.readFileSync)(`${e}/HEAD`,`utf-8`).trim().match(/^ref:\s*refs\/heads\/(.+)$/);return t?t[1]:null}catch{return null}},yi=e=>{let t={},n;try{n=(0,v.readFileSync)(e,`utf-8`)}catch{return t}for(let e of n.matchAll(/\[remote\s+"([^"]+)"\][^[]*?url\s*=\s*(\S+)/g))e[1]in t||(t[e[1]]=e[2]);return t}})),xi,Si,Ci=o((()=>{bi(),xi=e=>{let t=[],n=(0,m.resolve)(e),r=_i(n),i=r?.remotes.origin??null,a=i?pi(i):null,o=r?.remotes.github??null,s=mi(a)??mi(o?pi(o):null);s&&t.push(`github:${s}`),a&&r?.worktree&&t.push(`git:${a}+${r.worktree.branch}`),t.push(`local:${n}`);let c=(0,_.createHash)(`sha1`).update(t.join(`
18
+ `)).digest(`hex`);return t.push(`id:${c}`),t},Si=e=>{let t=xi(e);return t.find(e=>e.startsWith(`github:`))||t.find(e=>e.startsWith(`local:`))}})),wi,Ti=o((()=>{rr(),ge(),wi=async e=>{let t={};e.config.actions&&(t={...Object.entries(e.config.actions).reduce((e,[t,n])=>(e[t]=[n.command],e),{})});for(let[n,r]of Object.entries(nr)){let n=await r.actions(e);t=he(t,n)}return t}})),Ei,Di,Oi,ki,Ai=o((()=>{rr(),Ei=y.z.object({resolved:y.z.string().describe(`The resolved version of the dependency`),specifier:y.z.string().describe(`The version constraint/specifier used`),source:y.z.string().describe(`The source file/path of the dependency`),wanted:y.z.string().describe(`The wanted version based on semver rules`).optional(),latest:y.z.string().describe(`The latest available version of the dependency`).optional()}),Di=y.z.object({id:y.z.string().describe(`Unique identifier for the ecosystem / dependency`),name:y.z.string().describe(`Name of the dependency`),versions:y.z.array(Ei).describe(`Map of resolved versions to sources. Each source maps a package path to its version specifier.`),ecosystem:y.z.string().describe(`Ecosystem of the dependency (e.g., npm, rubygems, pip)`)}),Di.extend({wanted:y.z.string().describe(`Latest version compatible with the specifier (semver)`),latest:y.z.string().describe(`Absolute latest version available`),specifier:y.z.string().describe(`The version specifier from package manifest`),isDevDependency:y.z.boolean().describe(`Whether this is a dev dependency`),currentDate:y.z.string().optional().describe(`ISO date when the current version was published`),wantedDate:y.z.string().optional().describe(`ISO date when the wanted version was published`),latestDate:y.z.string().optional().describe(`ISO date when the latest version was published`)}),Oi=e=>{let t=new Map;for(let n of e){let e=t.get(n.id);e?t.set(n.id,{...e,versions:[...e.versions,...n.versions]}):t.set(n.id,n)}return Array.from(t.values())},ki=async e=>Oi((await Promise.all(Object.values(nr).map(t=>t.dependencies?t.dependencies(e):Promise.resolve([])))).flat())})),ji,Mi=o((()=>{Ti(),L(),Ai(),rr(),Ci(),ji=class e{path;branch;isPrimary;refs;slug;id;config;_rootFilesCache=null;constructor(e,t,n,r,i){this.path=e,this.branch=t,this.isPrimary=n,this.refs=xi(e);let a=this.refs.find(e=>e.startsWith(`github:`)),o=this.refs.find(e=>e.startsWith(`local:`)),s=this.refs.find(e=>e.startsWith(`id:`));this.slug=a??o,this.id=s.slice(3),this.config=r,i&&(this._rootFilesCache=i)}static async retrieve(t,n,r){let[i,a]=await Promise.all([oi(t),(0,f.readdir)(t).catch(()=>[])]);return new e(t,n,r,i,a)}get name(){return this.config.name??this.path.split(`/`).pop()??`unknown`}get rootFiles(){return this._rootFilesCache??[]}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 ki(this)}async outdatedDependencies(e){return(await Promise.all(Object.values(nr).map(t=>t.outdatedDependencies?t.outdatedDependencies(this,e):Promise.resolve([])))).flat()}async deduplicateDependencies(e){return(await Promise.all(Object.values(nr).map(t=>t.deduplicateDependencies?t.deduplicateDependencies(this,e):Promise.resolve(null)))).filter(e=>e!==null)}get actions(){return wi(this)}get services(){return this.config.services||{}}async findFilesByName(e){let t=[],n=async r=>{let i=await(0,f.readdir)(r,{withFileTypes:!0});for(let a of i)a.isDirectory()?a.name!==`node_modules`&&await n(`${r}/${a.name}`):a.name===e&&t.push(`${r}/${a.name}`)};return await n(this.path),t}}})),B,Ni=o((()=>{bi(),Mi(),B=class e{primaryWorktree;worktrees;activeWorktree;constructor(e,t){this.primaryWorktree=e,this.worktrees=t,this.activeWorktree=e}static async retrieve(t){let n=_i(t);if(!n){let n=await ji.retrieve(t,`main`,!0);return new e(n,[n])}let r=n.worktree.primaryPath,i=gi(t),[a,...o]=await Promise.all([ji.retrieve(r,`main`,!0),...i.map(e=>ji.retrieve(e.path,e.branch,!1))]),s=[a,...o],c=new e(a,s);return c.activeWorktree=s.find(e=>e.path===t)??a,c}worktree(e){return e===`main`?this.primaryWorktree:this.worktrees.find(t=>t.branch===e)??null}get id(){return this.primaryWorktree.id}get slug(){return this.primaryWorktree.slug}get refs(){return this.primaryWorktree.refs}get name(){return this.primaryWorktree.name}get path(){return this.primaryWorktree.path}}})),Pi,V,Fi,Ii=o((()=>{L(),Ci(),Ni(),D(),Pi=async e=>{let t=ni(e).split(`/`),n=[``];for(let e of t){if(e===``){n=n.map(e=>`${e}/`);continue}if(e===`*`){let e=[];for(let t of n){let n=t||`/`;if(await E(n))try{let r=await(0,f.readdir)(n,{withFileTypes:!0});for(let n of r)n.isDirectory()&&(n.name.startsWith(`.`)||e.push(`${t}${n.name}`))}catch{}}n=e}else n=n.map(t=>`${t}${e}`);n=n.map(e=>`${e}/`)}let r=[];for(let e of n){let t=e.replace(/\/$/,``);await rt(t)&&r.push(t)}return r},V=async e=>{let t=(await I()).projectPaths,n=e?.withConfig??!1,r=await Promise.all(t.map(Pi)),i=new Set,a=[];for(let e of r.flat())i.has(e)||(i.add(e),a.push(e));return(await Promise.all(a.map(async e=>n&&!await E(`${e}/.denvig.yml`)?null:{slug:Si(e),path:e}))).filter(e=>e!==null).sort((e,t)=>e.slug.localeCompare(t.slug))},Fi=async()=>{let e=await V({withConfig:!0}),t=new Map;return await Promise.all(e.map(async e=>{let n=await B.retrieve(e.path);for(let e of n.worktrees)t.set(e.id,{slug:e.slug,path:e.path})})),t}}));async function Li(){let e=await I(),t=(0,m.resolve)((0,p.homedir)(),`.denvig`),n=e.services;if(n){let e={};for(let[r,i]of Object.entries(n))i.cwd?e[r]=i:e[r]={...i,cwd:(0,m.resolve)(t,`services`,`${Vi}.${r}`,`cwd`)};n=e}return{id:Vi,slug:Bi,name:`Global`,path:(0,p.homedir)(),config:{services:n}}}async function Ri(){return new W(await Li())}function zi(e){return e===Bi}var Bi,Vi,Hi=o((()=>{L(),Ha(),Bi=`global`,Vi=(0,_.createHash)(`sha1`).update(`denvig-global`).digest(`hex`)})),Ui,Wi,Gi,Ki,qi,Ji,Yi,Xi,Zi,H,U,Qi,$i,ea,ta,na,ra,ia,aa,oa,sa,ca=o((()=>{Ui=y.z.object({id:y.z.string(),slug:y.z.string(),name:y.z.string(),path:y.z.string()}),Wi=y.z.object({command:y.z.string(),env:y.z.record(y.z.string(),y.z.string()).optional(),envFiles:y.z.array(y.z.string()).optional(),http:y.z.object({port:y.z.number().optional(),domain:y.z.string().optional(),cnames:y.z.array(y.z.string()).optional(),secure:y.z.boolean().optional()}).optional(),keepAlive:y.z.boolean().optional(),startOnBoot:y.z.boolean().optional()}),Gi=y.z.object({cwd:y.z.string(),port:y.z.number().int().positive().optional(),domains:y.z.array(y.z.string()).default([]),desiredStatus:y.z.enum([`running`,`stopped`]).default(`running`),project:Ui.optional(),serviceName:y.z.string().optional(),config:Wi.optional()}),Ki=y.z.object({project:y.z.string(),service:y.z.string(),port:y.z.number().int().positive(),defaultService:y.z.boolean().default(!0),secure:y.z.boolean().default(!1),desiredStatus:y.z.enum([`running`,`stopped`]).default(`running`),cert:y.z.string().optional()}),qi=y.z.object({dir:y.z.string(),certPath:y.z.string(),keyPath:y.z.string(),domains:y.z.array(y.z.string()).default([])}),Ji=y.z.object({services:y.z.record(y.z.string(),Gi).default({}),gatewayRoutes:y.z.record(y.z.string(),Ki).default({}),certs:y.z.record(y.z.string(),qi).default({})}),Yi=()=>(0,m.resolve)((0,p.homedir)(),`.denvig`,`state.json`),Xi=()=>({services:{},gatewayRoutes:{},certs:{}}),Zi=(e,t)=>`id:${e}:${t}`,H=async()=>{try{let e=await(0,f.readFile)(Yi(),`utf-8`),t=Ji.safeParse(JSON.parse(e));return t.success?t.data:Xi()}catch{return Xi()}},U=async e=>{let t=Yi();await(0,f.mkdir)((0,m.dirname)(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;await(0,f.writeFile)(n,`${JSON.stringify(e,null,2)}\n`,`utf-8`),await(0,f.rename)(n,t)},Qi=async(e,t)=>(await H()).services[Zi(e,t)]??null,$i=async(e,t,n)=>{let r=await H(),i=Zi(e,t),a=r.services[i];r.services[i]={cwd:n.cwd,port:n.port??a?.port,domains:n.domains??a?.domains??[],desiredStatus:n.desiredStatus??a?.desiredStatus??`running`,project:n.project??a?.project,serviceName:n.serviceName??a?.serviceName??t,config:n.config??a?.config},await U(r)},ea=async(e,t)=>{let n=await H(),r=Zi(e,t),i=n.services[r];i&&(n.services[r]={...i,desiredStatus:`stopped`},await U(n))},ta=async(e,t)=>{let n=await H(),r=Zi(e,t);r in n.services&&(delete n.services[r],await U(n))},na=e=>{let t=new Set;for(let n of Object.values(e.services))n.desiredStatus===`running`&&n.port!==void 0&&t.add(n.port);return t},ra=async e=>(await H()).gatewayRoutes[e]??null,ia=async(e,t)=>{let n=await H();n.gatewayRoutes[e]=t,await U(n)},aa=async(e,t)=>{let n=await H(),r=!1;for(let[i,a]of Object.entries(n.gatewayRoutes))a.project===e&&a.service===t&&(n.gatewayRoutes[i]={...a,desiredStatus:`stopped`},r=!0);r&&await U(n)},oa=async(e,t)=>{let n=await H(),r=!1;for(let[i,a]of Object.entries(n.gatewayRoutes))a.project===e&&a.service===t&&(delete n.gatewayRoutes[i],r=!0);r&&await U(n)},sa=async(e,t)=>{let n=await H();n.certs[e]=t,await U(n)}}));function la(){return(0,m.resolve)((0,p.homedir)(),`.denvig`,`gateway`,`html`)}async function ua(){let e=la(),t=(0,m.resolve)(e,`errors`);await(0,f.mkdir)(t,{recursive:!0}),await(0,f.writeFile)((0,m.resolve)(e,`index.html`),da,`utf-8`),await(0,f.writeFile)((0,m.resolve)(t,`404.html`),fa,`utf-8`),await(0,f.writeFile)((0,m.resolve)(t,`504.html`),pa,`utf-8`)}var da,fa,pa,ma=o((()=>{da=`<!DOCTYPE html>
19
+ <html lang="en">
20
+ <head>
21
+ <meta charset="utf-8">
22
+ <meta name="viewport" content="width=device-width, initial-scale=1">
23
+ <title>Denvig Gateway</title>
24
+ <style>
25
+ * { margin: 0; padding: 0; box-sizing: border-box; }
26
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0a0a0a; color: #e0e0e0; display: flex; align-items: center; justify-content: center; min-height: 100vh; }
27
+ .container { text-align: center; max-width: 480px; padding: 2rem; }
28
+ h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.75rem; color: #fff; }
29
+ p { font-size: 0.95rem; line-height: 1.6; color: #888; margin-bottom: 1.5rem; }
30
+ a { color: #6ea4f7; text-decoration: none; }
31
+ a:hover { text-decoration: underline; }
32
+ code { background: #1a1a1a; padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.85rem; color: #ccc; }
33
+ </style>
34
+ </head>
35
+ <body>
36
+ <div class="container">
37
+ <h1>Denvig Gateway</h1>
38
+ <p>This nginx server is managed by <a href="https://denvig.com">Denvig</a>.</p>
39
+ <p>Configure services with <code>http.domain</code> in your <code>.denvig.yml</code> to route traffic here.</p>
40
+ </div>
41
+ </body>
42
+ </html>
43
+ `,fa=`<!DOCTYPE html>
44
+ <html lang="en">
45
+ <head>
46
+ <meta charset="utf-8">
47
+ <meta name="viewport" content="width=device-width, initial-scale=1">
48
+ <title>404 - Not Found</title>
49
+ <style>
50
+ * { margin: 0; padding: 0; box-sizing: border-box; }
51
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0a0a0a; color: #e0e0e0; display: flex; align-items: center; justify-content: center; min-height: 100vh; }
52
+ .container { text-align: center; max-width: 480px; padding: 2rem; }
53
+ .code { font-size: 3rem; font-weight: 700; color: #555; margin-bottom: 0.5rem; }
54
+ h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.75rem; color: #fff; }
55
+ p { font-size: 0.95rem; line-height: 1.6; color: #888; margin-bottom: 1rem; }
56
+ a { color: #6ea4f7; text-decoration: none; }
57
+ a:hover { text-decoration: underline; }
58
+ code { background: #1a1a1a; padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.85rem; color: #ccc; }
59
+ </style>
60
+ </head>
61
+ <body>
62
+ <div class="container">
63
+ <div class="code">404</div>
64
+ <h1>Service Not Found</h1>
65
+ <p>No service is configured for this domain. The project may not exist or the domain is not set up in <code>.denvig.yml</code>.</p>
66
+ <p>Check your configuration with <code>denvig gateway status</code></p>
67
+ <p><a href="https://denvig.com">denvig.com</a></p>
68
+ </div>
69
+ </body>
70
+ </html>
71
+ `,pa=`<!DOCTYPE html>
72
+ <html lang="en">
73
+ <head>
74
+ <meta charset="utf-8">
75
+ <meta name="viewport" content="width=device-width, initial-scale=1">
76
+ <title>504 - Service Unavailable</title>
77
+ <style>
78
+ * { margin: 0; padding: 0; box-sizing: border-box; }
79
+ body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0a0a0a; color: #e0e0e0; display: flex; align-items: center; justify-content: center; min-height: 100vh; }
80
+ .container { text-align: center; max-width: 480px; padding: 2rem; }
81
+ .code { font-size: 3rem; font-weight: 700; color: #555; margin-bottom: 0.5rem; }
82
+ h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.75rem; color: #fff; }
83
+ p { font-size: 0.95rem; line-height: 1.6; color: #888; margin-bottom: 1rem; }
84
+ a { color: #6ea4f7; text-decoration: none; }
85
+ a:hover { text-decoration: underline; }
86
+ code { background: #1a1a1a; padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.85rem; color: #ccc; }
87
+ </style>
88
+ </head>
89
+ <body>
90
+ <div class="container">
91
+ <div class="code">504</div>
92
+ <h1>Service Unavailable</h1>
93
+ <p>This service is configured but does not appear to be running. Start it with <code>denvig services start</code>.</p>
94
+ <p>Check service status with <code>denvig services</code></p>
95
+ <p><a href="https://denvig.com">denvig.com</a></p>
96
+ </div>
97
+ </body>
98
+ </html>
99
+ `}));function ha(e){let{projectId:t,projectPath:n,projectSlug:r,serviceName:i,port:a,domain:o,cnames:s,sslCertPath:c,sslKeyPath:l}=e,u=`denvig-${t}--${i}`,d=[o,...s||[]].join(` `),f=!!(c&&l),p=f?`
100
+ ssl_certificate ${c};
101
+ ssl_certificate_key ${l};
102
+ ssl_protocols TLSv1.2 TLSv1.3;
103
+ ssl_ciphers HIGH:!aNULL:!MD5;`:``;return`# denvig:
104
+ # slug: ${r}
105
+ # path: ${n}
106
+ # service: ${i}
107
+ upstream ${u} { server 127.0.0.1:${a} max_fails=0 fail_timeout=30; }
108
+ server {
109
+ ${f?` listen 80;
110
+ listen 443 ssl;
111
+ http2 on;`:` listen 80;`}
112
+ server_name ${d};
113
+ root ${n}/public;
114
+ index index.html;
115
+ client_max_body_size 100M;
116
+ ${p}
117
+
118
+ error_page 502 503 504 /denvig-errors/504.html;
119
+ location /denvig-errors/ {
120
+ alias ${la()}/errors/;
121
+ internal;
122
+ }
123
+
124
+ location / {
125
+ proxy_pass http://${u};
126
+ proxy_set_header Host $host;
127
+ proxy_set_header X-Forwarded-Host $host;
128
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
129
+ proxy_redirect off;
130
+ proxy_buffering off;
131
+
132
+ proxy_http_version 1.1;
133
+ proxy_set_header Upgrade $http_upgrade;
134
+ proxy_set_header Connection "upgrade";
135
+ }
136
+ }
137
+ `}function ga(e){return(0,m.resolve)(e,`..`,`nginx.conf`)}function _a(e){let t=la();return`# Managed by denvig — do not edit manually
138
+ # https://denvig.com
139
+
140
+ worker_processes 4;
141
+
142
+ events {
143
+ worker_connections 1024;
144
+ }
145
+
146
+ http {
147
+ include ${(0,m.resolve)(e,`..`)}/mime.types;
148
+ default_type application/octet-stream;
149
+
150
+ sendfile on;
151
+ keepalive_timeout 65;
152
+
153
+ server {
154
+ listen 80 default_server;
155
+ server_name _;
156
+
157
+ root ${t};
158
+ index index.html;
159
+
160
+ error_page 404 /errors/404.html;
161
+ }
162
+
163
+ include ${e}/*;
164
+ }
165
+ `}async function va(e){try{return await(0,f.writeFile)(ga(e),_a(e),`utf-8`),{success:!0}}catch(e){return{success:!1,message:`Failed to write nginx.conf: ${e instanceof Error?e.message:`Unknown error`}`}}}function ya(e,t,n){return(0,m.resolve)(n,`denvig.${e}.${t}.conf`)}async function ba(e,t){try{let n=ya(e.projectId,e.serviceName,t);return await(0,f.mkdir)((0,m.dirname)(n),{recursive:!0}),await(0,f.writeFile)(n,ha(e),`utf-8`),{success:!0}}catch(e){return{success:!1,message:`Failed to write nginx config: ${e instanceof Error?e.message:`Unknown error`}`}}}async function xa(){try{return await Ca(`/opt/homebrew/bin/nginx -s reload`),{success:!0}}catch(e){return{success:!1,message:`Failed to reload nginx: ${e instanceof Error?e.message:`Unknown error`}`}}}async function Sa(e){try{let t=(await(0,f.readdir)(e)).filter(e=>e.startsWith(`denvig.`)&&e.endsWith(`.conf`));return await Promise.all(t.map(t=>(0,f.rm)((0,m.resolve)(e,t),{force:!0}))),{success:!0,removed:t}}catch(e){return{success:!1,removed:[],message:`Failed to remove nginx configs: ${e instanceof Error?e.message:`Unknown error`}`}}}var Ca,wa=o((()=>{ma(),Ca=(0,u.promisify)(d.exec)}));async function Ta(){let e=(await I()).experimental?.gateway;if(!e?.enabled)return null;let t=e.configsPath;await ua();let n=await va(t);if(!n.success)return{success:!1,removed:[],services:[],nginxReload:!1,message:n.message||`Failed to write nginx.conf`};let r=await Sa(t);if(!r.success)return{success:!1,removed:[],services:[],nginxReload:!1,message:r.message||`Failed to remove existing configs`};let i=await Fi(),a=await Li();i.set(a.id,{slug:a.slug,path:a.path});let o=await H(),s=new Map;for(let[e,t]of Object.entries(o.gatewayRoutes)){if(t.desiredStatus!==`running`)continue;let n=`${t.project}.${t.service}`,r=s.get(n);r?(r.domains.push(e),!r.certKey&&t.cert&&(r.certKey=t.cert)):s.set(n,{projectId:t.project,serviceName:t.service,port:t.port,secure:t.secure,domains:[e],certKey:t.cert})}let c=[];for(let e of s.values()){let n=i.get(e.projectId);if(!n)continue;let[r,...a]=e.domains,s=e.secure,l,u,d=`not_configured`,f,p;if(s){let t=e.certKey?o.certs[e.certKey]:void 0;t?(l=t.certPath,u=t.keyPath,d=`valid`,f=t.dir):(d=`missing`,p=e.certKey?`cert "${e.certKey}" referenced by route is not in state.certs`:`route has no cert reference; restart the service to refresh state.certs`)}let m={projectSlug:n.slug,serviceName:e.serviceName,domain:r,cnames:a,port:e.port,certStatus:d,certDir:f,certMessage:p,configStatus:`written`},h=await ba({projectId:e.projectId,projectPath:n.path,projectSlug:n.slug,serviceName:e.serviceName,port:e.port,domain:r,cnames:a,sslCertPath:l,sslKeyPath:u},t);h.success||(m.configStatus=`error`,m.configMessage=h.message),c.push(m)}let l=await xa(),u=c.some(e=>e.configStatus===`error`||e.certStatus===`missing`);return{success:!u,removed:r.removed,services:c,nginxReload:l.success,nginxReloadMessage:l.message,message:u?`Some services have errors or missing certificates`:`Gateway configured successfully`}}var Ea=o((()=>{L(),Ii(),Hi(),ca(),ma(),wa()}));function Da(e){let t={},n=e.split(`
166
+ `);for(let e=0;e<n.length;e++){let r=n[e].trim();if(!r||r.startsWith(`#`))continue;let i=r.indexOf(`=`);if(i===-1)continue;let a=r.slice(0,i).trim(),o=r.slice(i+1).trim(),s=o.startsWith(`"`),c=o.startsWith(`'`);if(s||c){let e=s?`"`:`'`,t=o.indexOf(e,1);if(t!==-1)o=o.slice(1,t);else{let e=o.indexOf(`#`);e!==-1&&(o=o.slice(0,e).trim())}}else{let e=o.indexOf(`#`);e!==-1&&(o=o.slice(0,e).trim())}a&&(t[a]=o)}return t}async function Oa(e){try{return Da(await(0,f.readFile)(e,`utf-8`))}catch(t){let n=t;throw n.code===`ENOENT`?Error(`Environment file not found: ${e}`):Error(`Failed to read environment file: ${n.message||`Unknown error`}`)}}async function ka(e,t){let n={},r=t?.skipMissing??!1;for(let t of e){if(r)try{await(0,f.access)(t)}catch{continue}let e=await Oa(t);Object.assign(n,e)}return n}var Aa,ja=o((()=>{Aa=[`.env.development`,`.env.local`]}));function Ma(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}function Na(e){return`{ ${e.trim()}; } 2>&1 | while IFS= read -r line; do printf '[%s] %s\\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$line"; done`}function Pa(e){return e.replace(/'/g,`'\\''`)}function Fa(e){let t=Na(e.command);return`#!/bin/bash
167
+ #
168
+ # Denvig service wrapper
169
+ # Service: ${e.serviceName}
170
+ # Project: ${e.projectSlug}
171
+ # Path: ${e.projectPath}
172
+ # Command: ${e.command}
173
+ # Workdir: ${e.workingDirectory}
174
+ #
175
+ exec /bin/zsh -l -c '${Pa(t)}'
176
+ `}function Ia(e){let{label:t,programPath:n,workingDirectory:r,environmentVariables:i={},standardOutPath:a,keepAlive:o,runAtLoad:s}=e,c=Object.entries(i).map(([e,t])=>` <key>${Ma(e)}</key>
177
+ <string>${Ma(t)}</string>`).join(`
178
+ `);return`<?xml version="1.0" encoding="UTF-8"?>
179
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
180
+ <plist version="1.0">
181
+ <dict>
182
+ <key>Label</key>
183
+ <string>${Ma(t)}</string>
184
+
185
+ <key>ProgramArguments</key>
186
+ <array>
187
+ <string>${Ma(n)}</string>
188
+ </array>
189
+
190
+ <key>WorkingDirectory</key>
191
+ <string>${Ma(r)}</string>
192
+
193
+ <key>EnvironmentVariables</key>
194
+ <dict>
195
+ ${c}
196
+ </dict>
197
+
198
+ <key>StandardOutPath</key>
199
+ <string>${Ma(a)}</string>
200
+
201
+ <key>KeepAlive</key>
202
+ <${o?`true`:`false`}/>
203
+
204
+ <key>RunAtLoad</key>
205
+ <${s?`true`:`false`}/>
206
+ </dict>
207
+ </plist>
208
+ `}var La=o((()=>{})),Ra,za,Ba,Va=o((()=>{ca(),Ra={min:8e3,max:9999},za=e=>new Promise(t=>{let n=(0,ee.createServer)();n.unref(),n.once(`error`,e=>{t(e.code===`EADDRINUSE`)}),n.once(`listening`,()=>{n.close(()=>t(!1))}),n.listen(e)}),Ba=async e=>{let t=e?.range??Ra,n=await H(),r=new Set([...na(n),...e?.excludePorts??[]]),i=async e=>r.has(e)?!1:!await za(e);if(e?.preferredPort&&await i(e.preferredPort))return e.preferredPort;let a=t.max-t.min+1,o=Math.min(a,200);for(let e=0;e<o;e++){let e=t.min+Math.floor(Math.random()*a);if(await i(e))return e;r.add(e)}return null}})),W,Ha=o((()=>{Kr(),Ea(),ja(),gr(),La(),Va(),ca(),W=class{project;constructor(e){this.project=e}async listServices(){let e=this.project.config.services||{};return Object.entries(e).map(([e,t])=>({name:e,cwd:t.cwd||`.`,command:t.command,http:t.http,startOnBoot:t.startOnBoot}))}async buildServiceEnvironment(e,t){let n=this.getServiceConfig(e);if(!n)return{success:!1,message:`Service "${e}" not found in configuration`};let r=this.resolveServiceCwd(n),i={DENVIG_PROJECT:this.project.slug,DENVIG_SERVICE:e},a=n.envFiles??Aa;if(a.length>0)try{let e=await ka(a.map(e=>(0,m.resolve)(r,e)),{skipMissing:!0});Object.assign(i,e)}catch(e){return{success:!1,message:`Failed to load environment file: ${e instanceof Error?e.message:`Unknown error`}`}}n.env&&Object.assign(i,n.env);let o=t?.port??n.http?.port;return o!==void 0&&(i.PORT=o.toString()),{success:!0,env:i}}async resolveServicePort(e,t){let n=this.getServiceConfig(e);if(!n)return{success:!1,message:`Service "${e}" not found in configuration`};let r=n.http?.port,i=await Qi(this.project.id,e);if(t?.forceRandom){let e=await Ba({preferredPort:i?.port});return{success:!0,port:e??void 0,source:e===null?`none`:`allocated`,conflict:!1,configPort:r}}if(i?.port!==void 0)return{success:!0,port:i.port,source:`state`,conflict:!1,configPort:r};if(r!==void 0){if(!await za(r))return{success:!0,port:r,source:`config`,conflict:!1,configPort:r};let e=await Ba();return{success:!0,port:e??void 0,source:e===null?`none`:`allocated`,conflict:!0,configPort:r}}let a=await Ba();return{success:!0,port:a??void 0,source:a===null?`none`:`allocated`,conflict:!1,configPort:r}}async startService(e,t){let n=this.getServiceConfig(e);if(!n)return{name:e,success:!1,message:`Service "${e}" not found in configuration`};let r=t?.port;if(!t?.portResolved){let t=await this.resolveServicePort(e);if(!t.success)return{name:e,success:!1,message:t.message};if(t.conflict&&t.source===`none`)return{name:e,success:!1,message:`Port ${t.configPort} is in use and no free port could be allocated`};r=t.port}let i=await this.buildServiceEnvironment(e,{port:r});if(!i.success)return{name:e,success:!1,message:i.message};let a=this.getServiceLabel(e),o=await j.print(a),s=o!==null,c=o!==null&&o.pid!==void 0&&o.state===`running`,l=n.http?.domain?[n.http.domain,...n.http.cnames??[]]:[];if(await $i(this.project.id,e,{cwd:this.resolveServiceCwd(n),port:r,domains:l,desiredStatus:`running`,project:{id:this.project.id,slug:this.project.slug,name:this.project.name,path:this.project.path},serviceName:e,config:{command:n.command,env:n.env,envFiles:n.envFiles,http:n.http,keepAlive:n.keepAlive,startOnBoot:n.startOnBoot}}),r!==void 0&&l.length>0){let i=n.http?.secure??!1,a;if(i){let e=await Vr(l[0]);if(e){let t=await Gr(e);t&&(a=(0,m.basename)(e),await sa(a,{dir:e,certPath:t.sslCertPath,keyPath:t.sslKeyPath,domains:l}))}}for(let n of l){let o=await ra(n),s=o?.project===this.project.id&&o?.service===e,c=o!==null&&!s&&o.desiredStatus===`stopped`;!o||s||c?await ia(n,{project:this.project.id,service:e,port:r,secure:i,defaultService:s?o?.defaultService??!0:!0,desiredStatus:`running`,cert:a}):t?.claimDomain===!0&&await ia(n,{project:this.project.id,service:e,port:r,secure:i,defaultService:!1,desiredStatus:`running`,cert:a})}}await this.ensureDenvigDirectories();let u=await this.createLogFile(e),d=this.getPlistPath(e),p=this.resolveServiceCwd(n);await(0,f.mkdir)(p,{recursive:!0});let h=this.getServiceScriptPath(e),g=Fa({command:n.command,serviceName:e,projectPath:this.project.path,projectSlug:this.project.slug,workingDirectory:p}),_=null;try{_=await(0,f.readFile)(h,`utf-8`)}catch{}_!==g&&(await(0,f.writeFile)(h,g,`utf-8`),await(0,f.chmod)(h,493));let v=Ia({label:a,programPath:h,workingDirectory:p,environmentVariables:i.env,standardOutPath:this.getStableLogPath(e),keepAlive:n.keepAlive??!0,runAtLoad:n.startOnBoot??!1}),y=null;try{y=await(0,f.readFile)(d,`utf-8`)}catch{}let ee=y!==v;if(ee&&await(0,f.writeFile)(d,v,`utf-8`),await j.enable(a),!s){let t=await j.bootstrap(d);if(!t.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${t.output}`}}else if(ee||t?.reviveIfNotRunning!==!1&&!c){let t=await j.bootout(a);if(!t.success)return{name:e,success:!1,message:`Failed to bootout service: ${t.output}`};await new Promise(e=>setTimeout(e,1e3));let n=await j.bootstrap(d);if(!n.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${n.output}`}}else return{name:e,success:!0,message:`Service already running with current config`};try{await(0,f.appendFile)(u,`[${new Date().toISOString()}] Service Started\n`,`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`};let r=!1;if(t.startOnBoot){let t=await j.stop(n);if(!t.success)return{name:e,success:!1,message:`Failed to stop service: ${t.output}`}}else{let t=await j.bootout(n);if(!t.success)return{name:e,success:!1,message:`Failed to stop service: ${t.output}`};await j.disable(n),r=!0}try{let t=new Date().toISOString();await(0,f.appendFile)(this.getLogPath(e),`[${t}] Service Stopped\n`,`utf-8`)}catch{}return await ea(this.project.id,e),await aa(this.project.id,e),r&&await this.reconfigureGateway(),{name:e,success:!0,message:`Service stopped successfully`}}async restartService(e,t){if(!this.getServiceConfig(e))return{name:e,success:!1,message:`Service "${e}" not found in configuration`};if(await this.isServiceBootstrapped(e)){let t=await this.stopService(e);if(!t.success)return t}return await this.startService(e,t)}async getServiceStatus(e){let t=this.getServiceConfig(e);if(!t)return null;let n=this.getServiceLabel(e),r=await j.print(n);if(!r)return{name:e,running:!1,command:t.command,cwd:this.resolveServiceCwd(t),logPath:this.getLogPath(e)};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),lastExitCode:r.lastExitCode}}async startAll(){let e=this.project.config.services||{},t=Object.keys(e);return await Promise.all(t.map(e=>this.startService(e)))}async stopAll(){let e=this.project.config.services||{},t=Object.keys(e),n=(await Promise.all(t.map(async e=>({name:e,isBootstrapped:await this.isServiceBootstrapped(e)})))).filter(e=>e.isBootstrapped).map(e=>e.name);return await Promise.all(n.map(e=>this.stopService(e)))}async restartAll(){let e=this.project.config.services||{},t=Object.keys(e),n=(await Promise.all(t.map(async e=>({name:e,isBootstrapped:await this.isServiceBootstrapped(e)})))).filter(e=>e.isBootstrapped).map(e=>e.name);return await Promise.all(n.map(e=>this.restartService(e)))}async teardownAll(e){let t=[],n=`denvig.${this.project.id}.`,r=[],i=await j.list(n);for(let e of i){let i=await j.bootout(e.label),a=e.label.replace(n,``);i.success?(r.push(e.label),t.push({name:a,success:!0,message:`Service removed from launchctl`})):t.push({name:a,success:!1,message:`Failed to bootout: ${i.output}`})}let a=(0,m.resolve)((0,p.homedir)(),`Library`,`LaunchAgents`);if(await Promise.all(r.map(async e=>{try{await(0,f.unlink)((0,m.resolve)(a,`${e}.plist`))}catch{}})),e?.removeLogs&&r.length>0){let e=this.getDenvigHomeDir(),t=(0,m.resolve)(e,`logs`),n=r.map(e=>e.replace(`denvig.`,``));await Promise.all(n.flatMap(n=>[(0,f.rm)((0,m.resolve)(e,`services`,n),{recursive:!0,force:!0}).catch(()=>{}),(0,f.unlink)((0,m.resolve)(t,`${n}.log`)).catch(()=>{}),(0,f.unlink)((0,m.resolve)(t,`${n}.error.log`)).catch(()=>{})]))}return await Promise.all(r.flatMap(e=>{let t=e.replace(n,``);return[ta(this.project.id,t),oa(this.project.id,t)]})),await this.reconfigureGateway(),t}async isServiceBootstrapped(e){let t=this.getServiceLabel(e);return await j.print(t)!==null}normalizeForLabel(e){return e.replace(/\//g,`__`).replace(/:/g,`-`).replace(/[^a-zA-Z0-9_.-]/g,`_`)}getServiceLabel(e){let t=this.normalizeForLabel(e);return`denvig.${this.project.id}.${t}`}getDenvigHomeDir(){return(0,m.resolve)((0,p.homedir)(),`.denvig`)}getPlistPath(e){let t=this.getServiceLabel(e);return(0,m.resolve)((0,p.homedir)(),`Library`,`LaunchAgents`,`${t}.plist`)}getServiceDir(e){let t=this.normalizeForLabel(e),n=`${this.project.id}.${t}`;return(0,m.resolve)(this.getDenvigHomeDir(),`services`,n)}getServiceLogDir(e){return(0,m.resolve)(this.getServiceDir(e),`logs`)}getServiceScriptPath(e){let t=this.normalizeForLabel(e),n=this.project.slug,r=n.startsWith(`github:`)?`${n.replace(`github:`,``).replace(`/`,`-`)}-`:``;return(0,m.resolve)(this.getServiceDir(e),`denvig-${r}${t}`)}getStableLogPath(e){return(0,m.resolve)(this.getServiceLogDir(e),`latest.log`)}getLogPath(e,t){let n=(0,p.hostname)();return(0,m.resolve)(this.getServiceLogDir(e),`latest.${n}.log`)}async createLogFile(e){let t=this.getServiceLogDir(e);await(0,f.mkdir)(t,{recursive:!0});let n=`${Math.floor(Date.now()/1e3)}.log`,r=(0,m.resolve)(t,n);await(0,f.writeFile)(r,``,`utf-8`);let i=this.getStableLogPath(e),a=this.getLogPath(e);return await Promise.all([i,a].map(async e=>{try{await(0,f.unlink)(e)}catch{}await(0,f.symlink)(n,e)})),r}async ensureDenvigDirectories(){await(0,f.mkdir)((0,m.resolve)(this.getDenvigHomeDir(),`logs`),{recursive:!0})}async getRecentLogs(e,t){try{return(await(0,f.readFile)(this.getLogPath(e),`utf-8`)).trim().split(`
209
+ `).slice(-t)}catch{return[]}}resolveServiceCwd(e){return(0,m.resolve)(this.project.path,e.cwd||`.`)}getServiceConfig(e){return this.project.config.services?.[e]}async reconfigureGateway(){let e=await Ta();e&&!e.success&&console.warn(`[gateway] ${e.message}`)}async getServiceUrl(e){let t=this.getServiceConfig(e);if(!t)return null;if(t.http?.domain){let n=await ra(t.http.domain);if(n?.project===this.project.id&&n?.service===e&&n?.desiredStatus===`running`)return`${t.http.secure?`https`:`http`}://${t.http.domain}`}return await this.getServiceLocalUrl(e)}async getServiceLocalUrl(e){let t=await this.getEffectivePort(e);return t===void 0?null:`http://localhost:${t}`}async getEffectivePort(e){let t=await Qi(this.project.id,e);return t?.port===void 0?this.getServiceConfig(e)?.http?.port:t.port}async plistExists(e){try{return await(0,f.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`,a=null,o=null;if(t?.launchctlList){let e=t.launchctlList.find(e=>e.label===r);e&&(a=e.pid===`-`?null:e.pid,o=e.status,i=a===null?o===0?`stopped`:`error`:o===0?`running`:`error`)}else if(await this.plistExists(e)){let e=await j.print(r);e&&(a=e.pid??null,o=e.lastExitCode??null,e.state===`running`&&(i=o!==null&&o!==0?`error`:`running`))}let s=await this.getEffectivePort(e),c={name:e,project:{id:this.project.id,slug:this.project.slug,name:this.project.name,path:this.project.path},status:i,pid:a,url:await this.getServiceUrl(e),localUrl:await this.getServiceLocalUrl(e),port:s??null,configPort:n.http?.port??null,command:n.command,cwd:this.resolveServiceCwd(n),logPath:this.getLogPath(e),envFiles:(n.envFiles??Aa).map(e=>(0,m.resolve)(this.resolveServiceCwd(n),e)),lastExitCode:o};return t?.includeLogs&&(c.logs=await this.getRecentLogs(e,t.logLines??20)),c}}})),Ua,Wa=o((()=>{gr(),Ha(),Ua=async(e,t)=>{let n=e.activeWorktree,r=n.config.$sources.length>0,i=t?.includeServiceStatus??!0,{$sources:a,...o}=n.config,s=`none`;if(i){let e=n.config.services||{},r=Object.keys(e);if(r.length>0){let e=t?.launchctlList??await j.list(`denvig.`),i=new W(n),a=!1;for(let t of r)if((await i.getServiceResponse(t,{launchctlList:e}))?.status===`running`){a=!0;break}s=a?`running`:`stopped`}}return{id:n.id,slug:n.slug,name:n.name,path:n.path,refs:n.refs,worktrees:e.worktrees.filter(e=>!e.isPrimary).map(e=>({path:e.path,branch:e.branch})),config:r?o:null,serviceStatus:s}}})),Ga,Ka,qa=o((()=>{Ga=e=>{let{project:t,workspace:n=`root`,resource:r}=e;if(!r.startsWith(`action/`)&&!r.startsWith(`service/`))throw Error(`Invalid resource format: ${r}. Must start with "action/" or "service/".`);return`@${t.slug}|${n}|${r}`},Ka=e=>{let t=Ga(e);return{id:t,hash:(0,_.createHash)(`sha256`).update(t).digest(`hex`)}}})),Ja,Ya,Xa,Za=o((()=>{Ni(),Ii(),Ja=e=>{if(e.startsWith(`id:`)){let t=e.slice(3),n=t.indexOf(`/`);return n===-1?{type:`id`,value:t}:{type:`id`,value:t.slice(0,n),serviceName:t.slice(n+1)}}if(e.startsWith(`github:`)){let t=e.slice(7),n=t.split(`/`);return n.length<=2?{type:`github`,value:t}:{type:`github`,value:`${n[0]}/${n[1]}`,serviceName:n.slice(2).join(`/`)}}if(e.startsWith(`local:`))return{type:`local`,value:e.slice(6)};if(e.startsWith(`/`)||e.startsWith(`~`))return{type:`path`,value:e};let t=e.split(`/`);return t.length<=2?{type:`github`,value:e}:{type:`github`,value:`${t[0]}/${t[1]}`,serviceName:t.slice(2).join(`/`)}},Ya=async(e,t)=>{let n=await V();switch(e.type){case`id`:for(let t of n){let n=await B.retrieve(t.path);if(n.id===e.value||n.id.startsWith(e.value))return t.path}return null;case`github`:{let t=n.find(t=>t.slug===`github:${e.value}`);return t?t.path:null}case`local`:{let r=t(e.value),i=n.find(e=>e.path===r);return i?i.path:r}case`path`:return t(e.value)}},Xa=async(e,t)=>{let n=Ja(e);return{path:await Ya(n,t),serviceName:n.serviceName}}})),Qa,$a,eo,to,no=o((()=>{L(),Ni(),Za(),Ii(),Hi(),Ha(),Qa=(e,t)=>{if(e.startsWith(`global:`))return{projectSlug:`global`,serviceName:e.slice(7)};if(!e.includes(`/`))return{projectSlug:t,serviceName:e};let n=Ja(e);if(n.serviceName!==void 0)return n.type===`id`?{projectSlug:``,projectId:n.value,serviceName:n.serviceName}:{projectSlug:n.type===`local`?`local:${n.value}`:`github:${n.value}`,serviceName:n.serviceName};if(n.type===`path`||n.type===`local`)return{projectSlug:n.type===`local`?`local:${n.value}`:n.value,serviceName:``};let r=e.split(`/`),i=r.pop();return{projectSlug:r.join(`/`),serviceName:i}},$a=async e=>{let t=await V({withConfig:!0}),n=t.find(t=>t.slug===e);if(n)return n.path;let r=t.find(t=>t.slug.replace(/^(github|local):/,``)===e);return r?r.path:null},eo=async e=>{let t=await V({withConfig:!0});for(let n of t){let t=await B.retrieve(n.path);if(t.id===e||t.id.startsWith(e))return n.path}return null},to=async(e,t)=>{if(e.startsWith(`global:`)){let t=e.slice(7);return{project:await Li(),manager:await Ri(),serviceName:t}}let n=Ja(e);if(n.serviceName!==void 0&&n.serviceName!==``){let e=await Ya(n,ni);if(e){let t=(await B.retrieve(e)).activeWorktree;return{project:t,manager:new W(t),serviceName:n.serviceName}}}let{projectSlug:r,projectId:i,serviceName:a}=Qa(e,t.slug),o;if(zi(r))return{project:await Li(),manager:await Ri(),serviceName:a};if(i)if(t.id===i||t.id.startsWith(i))o=t.activeWorktree;else{let e=await eo(i);if(e)o=(await B.retrieve(e)).activeWorktree;else throw Error(`Project with ID "${i}" not found`)}else if(r===t.slug)o=t.activeWorktree;else{let e=await $a(r);o=e?(await B.retrieve(e)).activeWorktree:(await B.retrieve(r)).activeWorktree}let s=new W(o);return{project:o,manager:s,serviceName:a}}})),ro,io=o((()=>{ro=(e,t)=>{let n=e.worktree(t);if(!n){let n=e.worktrees.filter(e=>!e.isPrimary).map(e=>e.branch),r=n.length?` Available worktrees: ${n.join(`, `)}`:``;throw Error(`Worktree with branch "${t}" not found.${r}`)}return n}}));async function ao(e){let t=[],n=[],r=await j.list(`denvig.`);for(let e of r){let r=await j.bootout(e.label);r.success?(n.push(e.label),t.push({name:e.label,success:!0,message:`Service removed from launchctl`})):t.push({name:e.label,success:!1,message:`Failed to bootout: ${r.output}`})}let i=(0,m.resolve)((0,p.homedir)(),`Library`,`LaunchAgents`);try{let e=(await(0,f.readdir)(i)).filter(e=>e.startsWith(`denvig.`)&&e.endsWith(`.plist`));await Promise.all(e.map(async e=>{try{await(0,f.unlink)((0,m.resolve)(i,e))}catch{}}))}catch{}if(e?.removeLogs){let e=(0,m.resolve)((0,p.homedir)(),`.denvig`),t=(0,m.resolve)(e,`logs`);try{let e=await(0,f.readdir)(t);await Promise.all(e.map(async e=>{try{await(0,f.unlink)((0,m.resolve)(t,e))}catch{}}))}catch{}let n=(0,m.resolve)(e,`services`);try{let e=await(0,f.readdir)(n);await Promise.all(e.filter(e=>e.startsWith(`denvig.`)||e.includes(`.`)).map(async e=>{try{await(0,f.rm)((0,m.resolve)(n,e,`logs`),{recursive:!0,force:!0})}catch{}}))}catch{}}try{await(0,f.writeFile)((0,m.resolve)((0,p.homedir)(),`.denvig`,`state.json`),`${JSON.stringify({services:{},gatewayRoutes:{}},null,2)}\n`,`utf-8`)}catch{}return{success:!0,services:t,logsRemoved:e?.removeLogs??!1}}async function oo(e,t){let n=e.activeWorktree,r=await new W(n).teardownAll({removeLogs:t?.removeLogs});return{success:!0,project:n.slug,services:r,logsRemoved:t?.removeLogs??!1}}var so=o((()=>{gr(),Ha()})),co,lo,uo,fo=o((()=>{co=(e,t)=>{if(e===t)return null;try{let n=g.default.diff(e,t);return n?n===`major`||n===`premajor`?`major`:n===`minor`||n===`preminor`?`minor`:n===`patch`||n===`prepatch`||n===`prerelease`?`patch`:null:null}catch{return null}},lo=(e,t)=>e===null?!1:t===`patch`?e===`patch`:t===`minor`?e===`patch`||e===`minor`:t===`major`?e===`major`:!1,uo=(e,t)=>lo(co(e.currentVersion,e.wantedVersion),t)?!0:lo(co(e.currentVersion,e.latestVersion),t)})),po,mo,ho,go,_o,vo=o((()=>{S(),kt(),Ye(),Pe(),Ft(),Yt(),fo(),vn(),po={npm:async(e,t)=>{let n=await Ne(e,t);return n?{ecosystem:`npm`,name:e,...n}:null},jsr:async(e,t)=>{let n=await Je(e,t);return n?{ecosystem:`jsr`,name:e,...n}:null},pypi:async(e,t)=>{let n=await _n(e,t);return n?{ecosystem:`pypi`,name:e,...n}:null},rubygems:async(e,t)=>{let n=await Jt(e,t);return n?{ecosystem:`rubygems`,name:e,...n}:null}},mo=async(e,t={})=>{let n=e.indexOf(`:`);if(n<=0)throw new b(`Invalid dependency identifier "${e}". Expected "<ecosystem>:<name>" (e.g. "npm:redis").`);let r=e.slice(0,n),i=e.slice(n+1),a=po[r];if(!a)throw new b(`Unsupported ecosystem "${r}". Supported: ${Object.keys(po).join(`, `)}.`);if(!i)throw new b(`Invalid dependency identifier "${e}". Missing package name.`);return a(i,t.noCache)},ho=e=>e.dependencies(),go=e=>e.versions[0]?.resolved||``,_o=async(e,t={})=>{let{semver:n,ecosystem:r}=t,i=t.cache??!0;if(n&&n!==`patch`&&n!==`minor`&&n!==`major`)throw new b(`Invalid semver value: "${n}". Must be "patch", "minor", or "major".`);let a=await e.outdatedDependencies({cache:i});r&&(a=a.filter(e=>e.ecosystem===r)),n&&(a=a.filter(e=>uo({currentVersion:go(e),wantedVersion:e.wanted,latestVersion:e.latest},n)));let o=null,s=[],c=t.releaseLatency??`auto`;if(c===`0`)o=null;else if(c===`auto`){let t=await Pt(e.path);t?(o=t.minimumReleaseAgeMs,s=t.exclude):o=1440*60*1e3}else if(o=Ot(c),o===null)throw new b(`Invalid releaseLatency value: "${c}". Use a duration like "3h", "7d", "2w", or "auto".`);if(o!==null){let e=o,t=Date.now();a=a.filter(n=>{if(s.includes(n.name))return!0;let r=go(n),i=n.wanted!==r,a=n.latest!==r,o=i&&n.wantedDate?t-new Date(n.wantedDate).getTime()>=e:!1,c=a&&n.latestDate?t-new Date(n.latestDate).getTime()>=e:!1;return i&&n.wantedDate||a&&n.latestDate?o||c:!0})}return a.sort((e,t)=>{let n=e.ecosystem.localeCompare(t.ecosystem);return n===0?e.name.localeCompare(t.name):n})}})),yo,bo=o((()=>{rr(),yo=async e=>{let t={};for(let[n,r]of Object.entries(nr)){let i=await r.actions(e);t[n]={name:r.name,actions:i}}return t}})),xo,So,Co,wo,To,Eo,Do,Oo,ko,Ao=o((()=>{S(),Ni(),Ii(),Hi(),no(),gr(),Ha(),io(),xo=new Set([`running`,`stopped`,`error`]),So=e=>{if(!e)return null;let t=(Array.isArray(e)?e:e.split(`,`)).map(e=>e.trim().toLowerCase()),n=t.filter(e=>!xo.has(e));if(n.length>0)throw new b(`Invalid status value(s): ${n.join(`, `)}. Allowed: running, stopped, error.`);return t},Co=async(e,t,n={})=>{let r=!!n.all,i=!!n.global,a=!!n.worktrees,o=n.worktree??null,s=So(n.status);if((r||i)&&o!==null)throw new b(`worktree cannot be combined with all or global.`);if(a&&(i||o!==null))throw new b(`worktrees cannot be combined with global or worktree.`);if(r&&i)throw new b(`Cannot combine all and global. Choose one.`);if(!r&&!i&&(!e||!t))throw new b(`No project provided or detected.`);let c=t;o!==null&&e&&(c=ro(e,o));let l=await j.list(`denvig.`),u=async(e,t,n,r)=>{let i=await e.listServices();i.sort((e,t)=>e.name.localeCompare(t.name));for(let a of i){let i=await e.getServiceResponse(a.name,{launchctlList:l});i&&r.push({service:i,depth:t,label:n})}},d=async e=>{let t=new Map;for(let n of await e.listServices()){let r=await e.getServiceResponse(n.name,{launchctlList:l});r&&t.set(n.name,r)}return t},f=async(e,t)=>{let n=e.primaryWorktree,r=await d(new W(n));if(!a){for(let e of[...r.keys()].sort()){let i=r.get(e);i&&t.push({service:i,depth:0,label:n.slug})}return}let i=[];for(let t of e.worktrees.filter(e=>!e.isPrimary))i.push({branch:t.branch,services:await d(new W(t))});let o=new Set(r.keys());for(let e of i)for(let t of e.services.keys())o.add(t);for(let e of[...o].sort()){let a=r.get(e);a&&t.push({service:a,depth:0,label:n.slug});for(let n of i){let r=n.services.get(e);r&&t.push({service:r,depth:1,label:n.branch})}}},p=async e=>{let t=new Map;for(let n of e){let e=await B.retrieve(n),r=e.primaryWorktree.path;t.has(r)||t.set(r,e)}return[...t.values()].sort((e,t)=>e.primaryWorktree.slug.localeCompare(t.primaryWorktree.slug))},m=[];if(i){let e=await Li();Object.keys(e.config.services||{}).length>0&&await u(new W(e),0,e.slug,m)}else if(r){let e=await p((await V()).map(e=>e.path));for(let t of e)await f(t,m);let t=await Li();Object.keys(t.config.services||{}).length>0&&await u(new W(t),0,t.slug,m)}else if(a)await f(e,m);else{let e=c;await u(new W(e),0,e.slug,m)}return s?m.filter(e=>s.includes(e.service.status)):m},wo=async(e,t,n)=>(n&&(e.activeWorktree=ro(e,n)),to(t,e)),To=async(e,t,n={})=>{let{manager:r,serviceName:i}=await wo(e,t,n.worktree),a=await r.getServiceResponse(i,{includeLogs:n.includeLogs??!1});if(!a)throw new b(`Service "${i}" not found in configuration.`);return a},Eo=2e3,Do=()=>new Promise(e=>setTimeout(e,Eo)),Oo=async(e,t,n={})=>{let{manager:r,serviceName:i,project:a}=await wo(e,t,n.worktree),o=await r.resolveServicePort(i,{}),s=await r.startService(i,{port:o.success?o.port:void 0,portResolved:!0});if(!s.success)throw new x(s.message,{service:i,project:a.slug});await Do();let c=await r.getServiceResponse(i,{includeLogs:!0});if(c?.status===`running`&&await r.reconfigureGateway(),!c)throw new x(`Service failed to start.`,{service:i,project:a.slug});return c},ko=async(e,t,n={})=>{let{manager:r,serviceName:i,project:a}=await wo(e,t,n.worktree),o=await r.stopService(i);if(!o.success)throw new x(o.message,{service:i,project:a.slug});let s=await r.getServiceResponse(i);if(!s)throw new x(`Service "${i}" not found after stopping.`,{service:i,project:a.slug});return s}})),jo,Mo=o((()=>{Ao(),pe(),jo=class{project;serviceName;worktreeName;ctx;constructor(e,t,n,r){this.project=e,this.serviceName=t,this.worktreeName=n,this.ctx=r}get name(){return this.serviceName}async start(){return w(this.ctx,`services.start`,this.project.slug,()=>Oo(this.project,this.serviceName,{worktree:this.worktreeName}))}async stop(){return w(this.ctx,`services.stop`,this.project.slug,()=>ko(this.project,this.serviceName,{worktree:this.worktreeName}))}async status(){return w(this.ctx,`services.status`,this.project.slug,()=>To(this.project,this.serviceName,{worktree:this.worktreeName,includeLogs:!0}))}}})),No,Po=o((()=>{No=class{_internal;constructor(e){this._internal=e}get internal(){return this._internal}get name(){return this._internal.name}get branch(){return this._internal.branch}get path(){return this._internal.path}get slug(){return this._internal.slug}get id(){return this._internal.id}get isPrimary(){return this._internal.isPrimary}get config(){return this._internal.config}get services(){return this._internal.services}get actions(){return this._internal.actions}dependencies(){return this._internal.dependencies()}outdatedDependencies(e){return this._internal.outdatedDependencies(e)}deduplicateDependencies(e){return this._internal.deduplicateDependencies(e)}}})),Fo,Io=o((()=>{or(),Te(),S(),Wa(),qa(),no(),io(),so(),vo(),bo(),Ao(),me(),pe(),Mo(),Po(),Fo=class{internal;ctx;constructor(e,t){this.internal=e,this.ctx=t}get id(){return this.internal.id}get slug(){return this.internal.slug}get name(){return this.internal.name}get path(){return this.internal.path}get refs(){return this.internal.refs}get activeWorktree(){return new No(this.internal.activeWorktree)}get primaryWorktree(){return new No(this.internal.primaryWorktree)}worktreeFor(e){return e?ro(this.internal,e):this.internal.activeWorktree}selectWorktree(e){let t=ro(this.internal,e);return this.internal.activeWorktree=t,new No(t)}info(e){return w(this.ctx,`projects.info`,this.internal.slug,()=>Ua(this.internal,e))}plugins(){return w(this.ctx,`plugins.list`,this.internal.slug,()=>yo(this.internal.activeWorktree))}teardown(e){return w(this.ctx,`projects.teardown`,this.internal.slug,()=>oo(this.internal,e))}resourceId(e){return Ga({project:this.internal,...e})}resourceHash(e){return Ka({project:this.internal,...e})}worktrees={list:()=>this.internal.worktrees.map(e=>new No(e)),retrieve:e=>new No(ro(this.internal,e))};actions={retrieve:async(e,t)=>{let n=this.worktreeFor(t?.worktree),r=ar(await ir(n),e,t?.ecosystem);return new T(r.name,r.commands,n,this.ctx)}};services={retrieve:async(e,t)=>new jo(this.internal,e,t?.worktree,this.ctx),list:e=>w(this.ctx,`services.list`,this.internal.slug,()=>Co(this.internal,this.internal.activeWorktree,e)),context:async e=>{let{manager:t,serviceName:n,project:r}=await to(e,this.internal);return{manager:t,serviceName:n,target:r}}};dependencies={list:()=>w(this.ctx,`dependencies.list`,this.internal.slug,()=>ho(this.internal.activeWorktree)),tree:e=>w(this.ctx,`dependencies.tree`,this.internal.slug,async()=>Ce(await ho(this.internal.activeWorktree),e?.depth??0,e?.ecosystem)),info:(e,t)=>w(this.ctx,`dependencies.info`,this.internal.slug,()=>mo(e,t)),retrieve:async e=>{let t=(await ho(this.internal.activeWorktree)).find(t=>t.id===e);if(!t)throw new b(`Dependency "${e}" not found.`);return t},outdated:e=>{let t=this.worktreeFor(e?.worktree);return w(this.ctx,`dependencies.outdated`,this.internal.slug,()=>_o(t,{ecosystem:e?.ecosystem,semver:e?.semver,releaseLatency:e?.releaseLatency,cache:e?.noCache?!1:void 0}))}};config={retrieve:()=>Promise.resolve(this.internal.activeWorktree.config)}}})),Lo,Ro=o((()=>{L(),bi(),Ni(),Za(),Ii(),Lo=async({cwd:e,project:t})=>{let n=null;if(t)n=(await Xa(t,ni)).path;else{let t=hi(e);if(t)n=t;else{let t=(await V()).find(t=>e===t.path||e.startsWith(`${t.path}/`));n=t?t.path:e}}let r=n?await B.retrieve(n):null,i=n?await li(n):null;return{project:r,projectPath:n,slug:i}}})),zo,Bo,Vo,Ho,Uo,Wo,Go,Ko,qo,Jo=o((()=>{zr(),S(),zo=async(e={})=>{let t=M(),n;try{n=(0,v.readdirSync)(t).filter(e=>{try{return(0,v.statSync)((0,m.resolve)(t,e)).isDirectory()}catch{return!1}})}catch{n=[]}if(n.length===0)return[];let r=await F(),i=r?(0,v.readFileSync)(N(),`utf-8`):null,a=r?await Mr():!1,o=new Date,s=[];for(let e of n){let n=Lr((0,m.resolve)(t,e));if(n)try{let t=(0,v.readFileSync)(n,`utf-8`),r=Or(t),c=kr(t),l=i?Nr(t,i):Pr(t),u=Fr(t),d;d=c<=o?`expired`:l&&!a?`untrusted`:`valid`,s.push({name:e,domains:r.length>0?r:[e],issuer:u,expires:c.toISOString(),status:d,signedByLocalCa:l,caTrusted:a})}catch{}}if(e.domain){let t=e.domain;return s.filter(e=>e.domains.includes(t))}return s},Bo=e=>{if(e.name)return(0,m.resolve)(M(),e.name);if(e.domain)return Sr(e.domain);throw new b("A certificate `domain` or `name` is required.")},Vo=async e=>{let t=Bo(e);return!(0,v.existsSync)(t)||!(0,v.statSync)(t).isDirectory()?null:{name:(0,m.basename)(t),path:t,files:(0,v.readdirSync)(t)}},Ho=async e=>{let{domain:t,force:n}=e;if(!await F())throw new b("The local CA is not configured. Run `ca.configure()` first.");let r=Sr(t);if((0,v.existsSync)(r)&&!n)throw new b(`A certificate already exists for "${t}". Pass force to overwrite.`);let{cert:i,key:a}=await Cr(),{privkey:o,fullchain:s}=await Tr(t,i,a);return await jr(t,o,s),{domain:t,name:(0,m.basename)(r),privkey:(0,m.resolve)(r,`privkey.pem`),fullchain:(0,m.resolve)(r,`fullchain.pem`)}},Uo=async e=>{let t=await Vo(e);if(!t)throw new b(`Certificate "${e.name??e.domain}" not found.`);return(0,v.rmSync)(t.path,{recursive:!0}),{name:t.name,files:t.files}},Wo=async e=>{let t=(0,m.resolve)(e.keyPath),n=(0,m.resolve)(e.certPath),r;try{r=(0,v.readFileSync)(n,`utf-8`)}catch{throw new b(`Could not read certificate file: ${n}`)}let i=Or(r);if(i.length===0)throw new b(`Could not determine a domain from the certificate.`);let a=e.name?.replace(/^\*\./,`_wildcard.`),o=a??i[0],s=a?(0,m.resolve)(M(),a):Sr(o);(0,v.mkdirSync)(s,{recursive:!0});let c=(0,m.resolve)(s,`privkey.pem`),l=(0,m.resolve)(s,`fullchain.pem`);return(0,v.copyFileSync)(t,c),(0,v.chmodSync)(c,384),(0,v.copyFileSync)(n,l),{domain:o,name:(0,m.basename)(s),privkey:c,fullchain:l}},Go=async()=>{let e=N();if(!await F())return{initialized:!1,trusted:!1,path:e};let t=await Mr(),n=new _.X509Certificate((0,v.readFileSync)(e,`utf-8`));return{initialized:!0,trusted:t,path:e,subject:n.subject,issuer:n.issuer,validFrom:n.validFrom,validTo:n.validTo,serialNumber:n.serialNumber,fingerprint256:n.fingerprint256}},Ko=async()=>{let e=N();if(await F())return Er(e),{created:!1,path:e};let{certPem:t,keyPem:n}=await wr();return await Ar(t,n),Er(e),{created:!0,path:e}},qo=async()=>{let e=N();if(!await F())throw new b("The local CA is not configured. Run `ca.configure()` first.");return Dr(e),{path:e}}})),Yo,Xo,Zo,Qo,$o=o((()=>{Ea(),Ii(),Hi(),gr(),Ha(),ca(),Yo=`denvig.`,Xo=e=>{if(!e.startsWith(Yo))return null;let t=e.slice(7),n=t.indexOf(`.`);return n===-1?null:{projectId:t.slice(0,n),serviceName:t.slice(n+1)}},Zo=e=>!e.project||!e.serviceName||!e.config?null:{id:e.project.id,slug:e.project.slug,name:e.project.name,path:e.project.path,config:{services:{[e.serviceName]:{cwd:e.cwd,command:e.config.command,env:e.config.env,envFiles:e.config.envFiles,http:e.config.http,keepAlive:e.config.keepAlive,startOnBoot:e.config.startOnBoot}}}},Qo=async()=>{let e=await H(),t=await j.list(Yo),n={actions:[],errors:[]},r=new Map;for(let e of t){let t=Xo(e.label);t&&r.set(e.label,t)}let i=new Set,a=e=>{if(!e.startsWith(`id:`))return null;let t=e.slice(3),n=t.indexOf(`:`);return n===-1?null:`${Yo}${t.slice(0,n)}.${t.slice(n+1)}`},o=await Fi(),s=new Set(o.keys());s.add((await Li()).id);let c=!1;for(let[t,r]of Object.entries(e.services)){if(!r.project||!r.serviceName||s.has(r.project.id))continue;c=!0;let o=Zo(r),l;if(o){let e=new W(o);l=e.getServiceLabel(r.serviceName),await(0,f.unlink)(e.getPlistPath(r.serviceName)).catch(()=>{})}else l=a(t);l&&(await j.bootout(l),i.add(l)),await ta(r.project.id,r.serviceName),await oa(r.project.id,r.serviceName),delete e.services[t],n.actions.push({type:`stopped`,project:r.project.slug,service:r.serviceName,reason:`checkout no longer exists; removed orphaned service`})}for(let[,t]of Object.entries(e.gatewayRoutes))s.has(t.project)||(c=!0,await oa(t.project,t.service));for(let[t,o]of Object.entries(e.services)){if(o.desiredStatus!==`running`)continue;let e=Zo(o);if(!e||!o.serviceName){let e=a(t);e&&i.add(e);continue}let s=new W(e),c=s.getServiceLabel(o.serviceName);i.add(c);try{let t=await s.startService(o.serviceName,{port:o.port,portResolved:!0,reviveIfNotRunning:!1});if(!t.success){n.errors.push({project:e.slug,service:o.serviceName,message:t.message});continue}t.message===`Service already running with current config`?n.actions.push({type:`skipped`,project:e.slug,service:o.serviceName,reason:`already running with current config`}):r.has(c)?n.actions.push({type:`restarted`,project:e.slug,service:o.serviceName,reason:`config changed since last bootstrap`}):n.actions.push({type:`started`,project:e.slug,service:o.serviceName,reason:`desiredStatus is running but service was not bootstrapped`})}catch(t){n.errors.push({project:e.slug,service:o.serviceName,message:t instanceof Error?t.message:String(t)})}}for(let e of t){if(i.has(e.label))continue;let t=await j.bootout(e.label),r=Xo(e.label),a=r?.projectId.slice(0,8)??`unknown`,o=r?.serviceName??e.label;t.success?n.actions.push({type:`stopped`,project:a,service:o,reason:`no matching entry in state.json`}):n.errors.push({project:a,service:o,message:`Failed to bootout: ${t.output}`})}return c&&await Ta(),n}})),es,ts,ns,rs=o((()=>{L(),Ro(),Kr(),Ea(),wa(),D(),$o(),es=()=>{try{let e=(0,d.execSync)(`brew services info nginx --json`,{stdio:[`pipe`,`pipe`,`pipe`],encoding:`utf-8`}),t=JSON.parse(e),n=Array.isArray(t)?t[0]:t;return{running:n.running??!1,pid:n.pid??null,status:n.status??null}}catch{return{running:!1,pid:null,status:null}}},ts=async(e={})=>{let t=(await I()).experimental?.gateway,n=t?.enabled??!1,r=[],{project:i}=await Lo({cwd:e.cwd??process.cwd()});if(i){let e=i.activeWorktree,n=e.config.services||{};for(let[i,a]of Object.entries(n)){let n=a.http?.domain;if(!n)continue;let o=a.http?.secure??!1,s=o?await Vr(n):null,c=s?await Gr(s):null,l=t?.enabled?ya(e.id,i,t.configsPath):null;r.push({name:i,domain:n,cnames:a.http?.cnames||[],port:a.http?.port,secure:o,certFound:!!c,certDir:s,nginxConfigPath:l,nginxConfigExists:l?await E(l):!1})}}return{enabled:n,handler:t?.handler??`nginx`,configsPath:t?.configsPath??null,nginxConf:t?.configsPath?ga(t.configsPath):null,nginx:es(),services:r}},ns=async()=>({reconcile:await Qo(),gateway:await Ta()})})),is,as,os=o((()=>{L(),Ro(),S(),Ni(),Ii(),fe(),Jo(),rs(),pe(),Io(),is=/^[a-z]([a-z0-9-]*[a-z0-9])?$/,as=class{ctx;constructor(e){if(!is.test(e.client))throw Error(`Invalid client name "${e.client}". Must start with a letter, contain only lowercase alphanumeric and hyphens, and not end with a hyphen.`);this.ctx={client:e.client,cwd:e.cwd??process.cwd()}}version(){return de()}projects={retrieve:async e=>{let t=await Lo({cwd:this.ctx.cwd,project:e});if(!t.project)throw new b(`Project "${e}" could not be resolved.`);return new Fo(t.project,this.ctx)},list:e=>w(this.ctx,`projects.list`,null,async()=>{let t=await V(e),n=new Map;for(let{path:e}of t){let t=await B.retrieve(e),r=t.primaryWorktree.path;n.has(r)||(t.activeWorktree=t.primaryWorktree,n.set(r,new Fo(t,this.ctx)))}return[...n.values()].sort((e,t)=>e.path.localeCompare(t.path))}),detect:async e=>{let t=await Lo({cwd:this.ctx.cwd,project:e});return{project:t.project?new Fo(t.project,this.ctx):null,projectPath:t.projectPath,slug:t.slug}}};certs={list:e=>w(this.ctx,`certs.list`,null,()=>zo(e)),retrieve:e=>w(this.ctx,`certs.retrieve`,null,()=>Vo(e)),create:e=>w(this.ctx,`certs.create`,null,()=>Ho(e)),remove:e=>w(this.ctx,`certs.remove`,null,()=>Uo(e)),import:e=>w(this.ctx,`certs.import`,null,()=>Wo(e)),ca:{status:()=>w(this.ctx,`certs.ca.status`,null,()=>Go()),configure:()=>w(this.ctx,`certs.ca.configure`,null,()=>Ko()),remove:()=>w(this.ctx,`certs.ca.remove`,null,()=>qo())}};gateway={status:()=>w(this.ctx,`gateway.status`,null,()=>ts({cwd:this.ctx.cwd})),configure:()=>w(this.ctx,`gateway.configure`,null,()=>ns())};config={retrieve:async e=>{if(!e?.project)return I();let t=await Lo({cwd:this.ctx.cwd,project:e.project});if(!t.project)throw new b(`Project "${e.project}" could not be resolved.`);return t.project.activeWorktree.config}}}})),ss=o((()=>{S(),me(),Io(),Mo(),Po(),$r(),os()})),cs,ls,us,ds,fs=o((()=>{z(),cs=(0,u.promisify)(d.execFile),ls=()=>R(`brew`,[`update`],{stdio:`ignore`}),us=()=>R(`brew`,[`upgrade`]),ds=async()=>{try{let{stdout:e}=await cs(`brew`,[`outdated`,`--json=v2`]);return JSON.parse(e)}catch{return null}}})),ps,ms=o((()=>{ps=(e,t)=>new Promise(n=>{let r=(0,d.spawn)(`denvig`,t,{cwd:e,stdio:`inherit`});r.on(`close`,e=>n(e===0)),r.on(`error`,()=>n(!1))})})),G,hs=o((()=>{G=e=>e.replace(process.env.HOME||`/root`,`~`)})),K,gs,_s,vs,ys=o((()=>{hs(),bi(),D(),ms(),K=m.default.join((0,p.homedir)(),`.dotfiles`),gs=()=>rt(K),_s=e=>`https://github.com/${e}/dotfiles`,vs=async e=>{if(await gs()){let t=await li(K),n=ci(e);if(t&&n&&t.toLowerCase()===n.toLowerCase())console.warn(`Warning: ${G(K)} already exists for ${t}, skipping clone`);else{let e=t??`(unknown remote)`;return{success:!1,message:`${G(K)} already exists with a different repository (${e})`}}}else if(console.log(`Cloning ${e} into ${G(K)}...`),!await ui(e,K))return{success:!1,message:`Failed to clone dotfiles repo`};return console.log(``),console.log(`Running denvig setup in ${G(K)}...`),await ps(K,[`run`,`setup`])?{success:!0,message:`Dotfiles installed`}:{success:!1,message:`Setup action failed`}}})),bs,xs,Ss,Cs=o((()=>{z(),bs=(0,u.promisify)(d.execFile),xs=async()=>{try{let{stdout:e}=await bs(`fdesetup`,[`status`]);return/FileVault is On/i.test(e)}catch{return!1}},Ss=()=>R(`sudo`,[`fdesetup`,`enable`])})),ws,Ts,Es,Ds,Os=o((()=>{z(),ws=(0,u.promisify)(d.execFile),Ts=async e=>{try{let{stdout:t}=await ws(`git`,[`config`,`--global`,e]);return t.trim()||null}catch{return null}},Es=async()=>{let[e,t]=await Promise.all([Ts(`user.name`),Ts(`user.email`)]);return!e||!t?null:{name:e,email:t}},Ds=async(e,t)=>await R(`git`,[`config`,`--global`,`user.name`,e])?R(`git`,[`config`,`--global`,`user.email`,t]):!1})),ks,As,js,Ms,Ns=o((()=>{D(),z(),ks=`/opt/homebrew/bin/brew`,As=`https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh`,js=()=>E(ks),Ms=()=>R(`sh`,[`-c`,`/bin/bash -c "$(curl -fsSL ${As})"`])})),Ps,Fs,Is,Ls=o((()=>{D(),z(),Ps=`/opt/homebrew/bin/skills`,Fs=()=>E(Ps),Is=()=>R(Ps,[`update`,`-g`])})),Rs,zs,Bs,Vs,Hs,Us=o((()=>{D(),z(),Rs=`/etc/pam.d/sudo_local`,zs=`/etc/pam.d/sudo`,Bs=/^\s*auth\s+sufficient\s+pam_tid\.so/m,Vs=async()=>{for(let e of[Rs,zs]){let t=await nt(e);if(t&&Bs.test(t))return!0}return!1},Hs=()=>R(`sh`,[`-c`,`echo 'auth sufficient pam_tid.so' | sudo tee -a ${Rs} > /dev/null`])})),Ws,Gs,Ks,qs=o((()=>{z(),Ws=(0,u.promisify)(d.execFile),Gs=async()=>{try{return await Ws(`xcode-select`,[`-p`]),!0}catch{return!1}},Ks=()=>R(`xcode-select`,[`--install`])})),q=o((()=>{zr(),le(),L(),Te(),Kr(),wa(),bi(),gr(),Ha(),$o(),ca(),fs(),ms(),ys(),Cs(),Os(),Ns(),Ls(),Us(),qs(),so()}));ss(),q();const Js=[{name:`project`,description:`The project slug to run against. Defaults to current directory.`,required:!1,type:`string`,defaultValue:void 0},{name:`json`,description:`Output in JSON format`,required:!1,type:`boolean`,defaultValue:!1}],Ys=new Set([`internals:resource-hash`,`internals:resource-id`,`shell:__complete__`]);function Xs(e,t){let n=[];n.push(`Denvig v${t}`),n.push(``),n.push(`Commands:`);let r=Object.keys(e).filter(e=>!Ys.has(e)&&!e.startsWith(`internals:`)),i=r.map(t=>`denvig ${e[t].usage}`),a=Math.max(...i.map(e=>e.length))+2;for(let t of r){let r=`denvig ${e[t].usage}`;n.push(` ${r.padEnd(a,` `)} ${e[t].description}`)}return n.push(``),n.push(`Options:`),n.push(` -h, --help Show help`),n.push(` -v, --version Show version number`),n}function Zs(e,t){for(let n of Xs(e,t))console.log(n)}function Qs(e,t=Js){let n=[];if(n.push(`Usage: denvig ${e.usage}`),n.push(``),n.push(e.description),e.args.length>0){n.push(``),n.push(`Arguments:`);for(let t of e.args){let e=t.required?``:` (optional)`;n.push(` ${t.name}${e}`),n.push(` ${t.description}`)}}let r=[...t,...e.flags];if(r.length>0){n.push(``),n.push(`Options:`);let e=r.map(e=>`--${e.name}`),t=Math.max(...e.map(e=>e.length))+2;for(let e of r){let r=`--${e.name}`;n.push(` ${r.padEnd(t,` `)} ${e.description}`)}}if(e.example){n.push(``),n.push(`Example:`);let t=e.example.startsWith(`denvig `)?e.example:`denvig ${e.example}`;n.push(` ${t}`)}return n}function $s(e,t=Js){for(let n of Qs(e,t))console.log(n)}function ec(e){let t=[];t.push(`Usage: denvig ${e.usage}`),t.push(``),t.push(e.description),t.push(``),t.push(`Subcommands:`);let n=Object.entries(e.subcommands).filter(([e])=>!e.startsWith(`__`)),r=Math.max(...n.map(([e])=>e.length))+2;for(let[e,i]of n)t.push(` ${e.padEnd(r,` `)} ${i.description}`);return t}function tc(e){for(let t of ec(e))console.log(t)}var J,Y=o((()=>{J=class{name;description;usage;example;args;flags;handler;completions;subcommands;defaultSubcommand;acceptsExtraArgs;get hasSubcommands(){return Object.keys(this.subcommands).length>0}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,this.subcommands=e.subcommands??{},this.defaultSubcommand=e.defaultSubcommand,this.acceptsExtraArgs=e.acceptsExtraArgs??!1}async run(e,t,n,r,i){try{return await this.handler({sdk:e,project:t,worktree:t.activeWorktree,args:n,flags:r,extraArgs:i})}catch(e){return console.error(`Error executing command "${this.name}":`,e),{success:!1,message:`fail`}}}}})),nc=s({runCommand:()=>rc}),rc,ic=o((()=>{Y(),rc=new J({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:[],acceptsExtraArgs:!0,completions:async({project:e})=>{let t=await e.activeWorktree.actions;return Object.keys(t)},handler:async({sdk:e,project:t,worktree:n,args:r,flags:i,extraArgs:a=[]})=>{if(!r.action){let t=await n.actions;if(i.json)return console.log(JSON.stringify({actions:t})),{success:!0,message:`Actions listed.`};console.log(`Denvig v${e.version()}`),console.log(``),console.log(`Usage: denvig run [action] [...actionArgs]`),console.log(``),console.log(`Available actions:`);for(let e in t){if(!t[e])continue;let n=t[e];for(let t of n){let n=t.split(`
210
+ `),r=n[0],i=n.slice(1);console.log(` ${e}: ${r}`);for(let t of i)t.trim()&&console.log(`${` `.repeat(e.length+4)}${t}`)}}return{success:!0,message:`No action specified.`}}let o;try{o=await t.actions.retrieve(r.action)}catch{return console.error(`Action "${r.action}" not found in project ${n.name}.`),{success:!1,message:`Action "${r.action}" not found.`}}return{success:(await o.run({args:a})).success}}})})),ac=o((()=>{hs(),fo()})),oc=o((()=>{D()})),sc,cc=o((()=>{oc(),Y(),sc=new J({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:async({worktree:e,args:t,flags:n})=>{let r=(0,m.resolve)(e.path,t.path?.toString()||`.denvig.yml`),i=await nt(r);if(!i)return n.json?console.log(JSON.stringify({valid:!1,path:r,error:`Config file not found.`})):console.error(`Config file not found: ${r}`),{success:!1,message:`Config file not found.`};let a;try{a=(0,h.parse)(i)}catch(e){let t=e instanceof Error?e.message:`Unknown error`;return n.json?console.log(JSON.stringify({valid:!1,path:r,error:`Invalid YAML syntax: ${t}`})):(console.error(`Failed to parse YAML at ${r}:`),console.error(` ${t}`)),{success:!1,message:`Invalid YAML syntax.`}}let o=Qr.safeParse(a);if(!o.success){if(n.json)console.log(JSON.stringify({valid:!1,path:r,errors:o.error.issues.map(e=>({path:e.path.length>0?e.path.join(`.`):`(root)`,message:e.message}))}));else{console.error(`Config validation failed for ${r}:`);for(let e of o.error.issues){let t=e.path.length>0?e.path.join(`.`):`(root)`;console.error(` - ${t}: ${e.message}`)}}return{success:!1,message:`Config validation failed.`}}return n.json?console.log(JSON.stringify({valid:!0,path:r})):console.log(`Config is valid: ${r}`),{success:!0,message:`Config is valid.`}}})})),lc=s({configCommand:()=>dc}),uc,dc,fc=o((()=>{ac(),Y(),cc(),uc=e=>{(0,h.stringify)(Object.fromEntries(Object.entries({...e,$sources:void 0}).filter(([e,t])=>t!==void 0)),{indent:2,lineWidth:80}).trim().split(`
211
+ `).map(e=>console.log(` ${G(e)}`))},dc=new J({name:`config`,description:`Display the current global and project configuration.`,usage:`config`,example:`config`,args:[],flags:[],subcommands:{verify:sc},handler:async({sdk:e,project:t,worktree:n,flags:r})=>{let i=await e.config.retrieve(),a=await t.config.retrieve();if(r.json){let{$sources:e,...t}=i,{$sources:r,...o}=a;return console.log(JSON.stringify({global:{sources:e,config:t},project:{slug:n.slug,sources:r,config:o}})),{success:!0,message:`Configuration displayed.`}}return console.log(`Denvig Config`),console.log(``),console.log(`Global: ${i.$sources.map(e=>G(e)).join(`, `)||`default`}`),uc(i),console.log(``),console.log(`Project: ${n.config.$sources.map(e=>G(e)).join(`, `)||`default`}`),console.log(` slug: ${n.slug}`),uc(a),{success:!0,message:`Configuration displayed.`}}})})),pc=s({pluginsCommand:()=>mc}),mc,hc=o((()=>{Y(),mc=new J({name:`plugins`,description:`Show a list of available plugins and their actions`,usage:`plugins`,example:`denvig plugins`,args:[],flags:[],handler:async({project:e,flags:t})=>{let n=await e.plugins();if(t.json)return console.log(JSON.stringify(n)),{success:!0};for(let[e,t]of Object.entries(n)){let e=Object.keys(t.actions);console.log(`${t.name}: ${e.length} actions`);for(let n of e)console.log(` - ${n}: ${t.actions[n].join(` && `)}`)}return{success:!0}}})})),gc=s({versionCommand:()=>_c}),_c,vc=o((()=>{Y(),_c=new J({name:`version`,description:`Show the current version of Denvig`,usage:`version`,example:`denvig version`,args:[],flags:[],handler:({sdk:e,flags:t})=>{let n=e.version();return t.json?console.log(JSON.stringify({version:n})):console.log(`v${n}`),{success:!0}}})})),yc=s({infoCommand:()=>xc}),bc,xc,Sc=o((()=>{ac(),Y(),bc=e=>{switch(e){case`running`:return`🟢`;case`stopped`:return`◯`;default:return``}},xc=new J({name:`info`,description:`Show information about the current project`,usage:`info`,example:`denvig info`,args:[],flags:[],handler:async({project:e,flags:t})=>{let n=await e.info();if(t.json)return console.log(JSON.stringify(n)),{success:!0};let r=bc(n.serviceStatus),i=r?`${r} `:``;if(console.log(`${i}${n.config?.name||n.slug}`),console.log(` Path: ${G(n.path)}`),console.log(` Slug: ${n.slug}`),console.log(` ID: ${n.id}`),n.refs.length>0){console.log(` Refs: ${n.refs[0]}`);for(let e of n.refs.slice(1))console.log(` ${e}`)}if(n.worktrees.length>0){let e=e=>`${e.path} (${e.branch})`;console.log(` `),console.log(` Worktrees:`);for(let t of n.worktrees)console.log(` ${e(t)}`)}return{success:!0}}})})),X,Z,Cc,wc,Tc,Ec,Q=o((()=>{X=()=>process.env.NO_COLOR===void 0?process.env.FORCE_COLOR===void 0?process.stdout.isTTY===!0:!0:!1,Z={get reset(){return X()?`\x1B[0m`:``},get white(){return X()?`\x1B[37m`:``},get grey(){return X()?`\x1B[90m`:``},get green(){return X()?`\x1B[32m`:``},get yellow(){return X()?`\x1B[33m`:``},get red(){return X()?`\x1B[31m`:``},get bold(){return X()?`\x1B[1m`:``}},Cc=e=>e.replace(/\x1b\[[0-9;:]*m/g,``).replace(/\x1b]8;;.*?(?:\x07|\x1b\\)/g,``),wc=(e,t)=>X()?`\x1b]8;;${t}\x1b\\\x1b[4:4m${e}\x1b[4:0m\x1b]8;;\x1b\\`:e,Tc=e=>{if(e.depth===0)return``;let t=``;for(let n=0;n<e.parentPath.length-1;n++)t+=e.parentPath[n]?` `:`│ `;return e.hasChildren?t+=e.isLast?`└─┬ `:`├─┬ `:t+=e.isLast?`└── `:`├── `,t},Ec=e=>{let{columns:t,data:n,tree:r}=e,i=t.filter(e=>e.visible!==!1);if(n.length===0||i.length===0)return[];let a=i.map((e,t)=>{let i=e.header.length,a=Math.max(...n.map(n=>{let i=e.accessor(n);return r&&t===0&&(i=Tc({depth:r.getDepth(n),isLast:r.getIsLast(n),hasChildren:r.getHasChildren(n),parentPath:r.getParentPath(n)})+Cc(i)),Cc(i).length}));return Math.max(i,a)}),o=[],s=i.map((e,t)=>e.header.padEnd(a[t]));o.push(s.join(` `));let c=a.reduce((e,t)=>e+t,0)+(i.length-1)*2;o.push(`-`.repeat(c));for(let e of n){let t=(r?r.getDepth(e):0)>0,n=i.map((n,i)=>{let o=n.accessor(e),s=a[i];if(r&&i===0)o=Tc({depth:r.getDepth(e),isLast:r.getIsLast(e),hasChildren:r.getHasChildren(e),parentPath:r.getParentPath(e)})+(t?`${Z.grey}${Cc(o)}${Z.reset}`:o);else if(t&&!n.format){let e=Cc(o);e.trim()&&(o=`${Z.grey}${e}${Z.reset}`)}let c=s-Cc(o).length;if(n.format){let t=Cc(o).padEnd(s);return n.format(t,e)}return o+` `.repeat(Math.max(0,c))});o.push(n.join(` `))}return o}})),Dc,Oc,kc=o((()=>{ss(),Y(),Q(),Dc=e=>{switch(e){case`running`:return`🟢`;case`error`:return`🔴`;default:return`◯`}},Oc=new J({name:`services:list`,description:`List services for the current project`,usage:`services list [--all] [--worktrees] [--global] [--worktree <branch>] [--status <status>]`,example:`services list`,args:[],flags:[{name:`all`,description:`List services across all projects and global services`,required:!1,type:`boolean`,defaultValue:!1},{name:`worktrees`,description:`Nest each project's worktree services beneath it. Pair with --all to show worktrees for every project.`,required:!1,type:`boolean`,defaultValue:!1},{name:`global`,description:`List only global services`,required:!1,type:`boolean`,defaultValue:!1},{name:`worktree`,description:`List services for a sibling git worktree by branch name (use "main" for the primary checkout). Pair with the global --project flag to target a worktree of another project.`,required:!1,type:`string`},{name:`status`,description:`Filter by runtime status. Accepts a single value or a comma-separated list (running, stopped, error).`,required:!1,type:`string`}],completions:()=>[],handler:async({project:e,flags:t})=>{let n=t.all,r=t.global,i=t.worktrees,a=typeof t.worktree==`string`?t.worktree:void 0,o=typeof t.status==`string`?t.status:void 0,s;try{s=await e.services.list({all:n,global:r,worktrees:i,worktree:a,status:o})}catch(e){if(e instanceof b){let n=e.message;return t.json?console.log(JSON.stringify({success:!1,message:n})):console.error(n),{success:!1,message:n}}throw e}let c=o?o.split(`,`).map(e=>e.trim().toLowerCase()):null;if(s.length===0)return t.json?console.log(JSON.stringify([])):console.log(c?`No services matching status: ${c.join(`, `)}.`:r?`No global services configured.`:n?`No services configured across any project.`:`No services configured for ${e.slug}.`),{success:!0,message:`No services configured.`};if(t.json)return console.log(JSON.stringify(s.map(e=>e.service))),{success:!0,message:`Services listed successfully.`};let l=new Set(s.filter(e=>e.depth===0).map(e=>e.label)).size,u=n||r||i,d=e=>e.url?e.localUrl&&e.localUrl!==e.url&&(e.configPort===null||e.configPort!==e.port)?`${e.url} ${e.localUrl}`:e.url:`-`,f=Ec({columns:[{header:``,accessor:e=>Dc(e.service.status)},...u?[{header:`Project`,accessor:e=>e.depth>0?`└ ${e.label}`:e.label}]:[],{header:`Name`,accessor:e=>e.service.name},{header:`URL`,accessor:e=>d(e.service)}],data:s});for(let e of f)console.log(e);console.log(``);let p=s.length,m=c?` (filtered by status: ${c.join(`, `)})`:``;return console.log(n?`${p} service${p===1?``:`s`} configured across ${l} project${l===1?``:`s`}${m}`:r?`${p} global service${p===1?``:`s`} configured${m}`:`${p} service${p===1?``:`s`} configured for ${e.slug}${m}`),{success:!0,message:`Services listed successfully.`}}})})),Ac,jc=o((()=>{Ac=async(e,t)=>{let n=[];for(let t of Object.keys(e.activeWorktree.services))n.push(t);let r=await t.config.retrieve();for(let e of Object.keys(r.services??{}))n.push(`global:${e}`);let i=await t.projects.list({withConfig:!0});for(let e of i){let t=e.slug.replace(/^(github|local):/,``),r=e.id.slice(0,8);for(let i of Object.keys(e.activeWorktree.services))n.push(`${t}/${i}`),n.push(`id:${r}/${i}`)}return n}})),Mc,Nc=o((()=>{Y(),jc(),Mc=new J({name:`services:logs`,description:`Show logs for a service`,usage:`services logs <name> [-n <lines>] [--follow] [--worktree <branch>]`,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,short:`n`},{name:`follow`,description:`Follow the log output`,required:!1,type:`boolean`,defaultValue:!1},{name:`worktree`,description:`Target the service in a sibling git worktree by branch name (use "main" for the primary checkout)`,required:!1,type:`string`}],completions:({project:e,sdk:t})=>Ac(e,t),handler:async({project:e,args:t,flags:n})=>{let r=t.name;if(typeof n.worktree==`string`)try{e.selectWorktree(n.worktree)}catch(e){let t=e instanceof Error?e.message:String(e);return n.json?console.log(JSON.stringify({success:!1,message:t})):console.error(t),{success:!1,message:t}}let{manager:i,serviceName:a}=await e.services.context(r),o=n.lines??10,s=!!n.follow,c=i.getLogPath(a);if(s)return n.json?(console.log(JSON.stringify({success:!1,error:`JSON format is not supported with --follow`})),{success:!1,message:`JSON format not supported with follow`}):((0,d.spawn)(`tail`,[`-n`,`${o}`,`-f`,c],{stdio:`inherit`}),new Promise(()=>{}));try{let e=(await(0,f.readFile)(c,`utf-8`)).trim().split(`
212
+ `).filter(Boolean).slice(-o);if(n.json)return console.log(JSON.stringify({service:a,logPath:c,lines:e})),{success:!0};for(let t of e)console.log(t);return{success:!0}}catch(e){let t=e instanceof Error?e.message:String(e);return n.json?console.log(JSON.stringify({success:!1,service:a,error:t})):console.error(`Failed to read logs for ${a}:`,t),{success:!1,message:`failed to read logs`}}}})})),$,Pc,Fc=o((()=>{$=e=>{let t=(0,te.createInterface)({input:process.stdin,output:process.stdout});return new Promise(n=>{t.question(`${e} [y/N] `,e=>{t.close(),n(e.toLowerCase()===`y`)})})},Pc=e=>{let t=(0,te.createInterface)({input:process.stdin,output:process.stdout});return new Promise(n=>{t.question(`${e}: `,e=>{t.close(),n(e.trim())})})}}));async function Ic(e,t,n){let r=t.http;if(!r?.secure||!r.domain)return;let i=r.domain,a=[i,...r.cnames??[]],o=[];for(let e of a)await Vr(e)||o.push(e);if(o.length!==0){if(!await F()){if(n.json){console.error(`Warning: No local CA found. Skipping cert generation for ${e}.`);return}if(!await $(`No local CA found. Generate and install one?`)){console.log(`Skipping certificate setup.`);return}let{certPem:t,keyPem:r}=await wr();await Ar(t,r),Er(N())}if(n.json){console.error(`Warning: No TLS certificate for ${o.join(`, `)}. Skipping cert generation.`);return}if(!await $(`Generate TLS certificate for ${i}?`)){console.log(`Skipping certificate generation.`);return}await Wr(o)}}var Lc=o((()=>{Fc()})),Rc,zc=o((()=>{q(),Rc=async e=>{try{let t=await Qo();if(e.json)return;let n=t.actions.filter(e=>e.type!==`skipped`);for(let e of n){let t=e.type===`started`?`▶`:e.type===`stopped`?`■`:e.type===`restarted`?`↻`:`·`;console.log(`${t} ${e.type} ${e.project}/${e.service} — ${e.reason}`)}for(let e of t.errors)console.error(`reconcile: ${e.project}/${e.service}: ${e.message}`)}catch(t){if(e.json)return;console.error(`reconcile failed: ${t instanceof Error?t.message:String(t)}`)}}})),Bc,Vc,Hc,Uc=o((()=>{q(),Fc(),Bc=e=>!e.json&&process.stdin.isTTY===!0&&process.stdout.isTTY===!0&&!e[`random-port`],Vc=e=>`${e.project.slice(0,8)}/${e.service}`,Hc=async(e,t,n,r)=>{let i=!!n[`random-port`],a=await e.resolveServicePort(t,{forceRandom:i});if(!a.success)return n.json?console.log(JSON.stringify({success:!1,service:t,message:a.message})):console.error(a.message),null;let o=a.port,s=a.source===`allocated`;if(a.conflict){if(Bc(n)){if(!await $(s&&o!==void 0?`Port ${a.configPort} is already in use. Start ${t} on random port ${o} instead?`:`Port ${a.configPort} is already in use and no random port could be allocated. Continue anyway?`))return console.error(`Aborted: ${t} not started.`),null;if(a.source===`none`)return null}else if(n.json||(s&&o!==void 0?console.log(`Port ${a.configPort} is in use; using random port ${o} instead.`):console.error(`Port ${a.configPort} is in use and no free port could be allocated.`)),a.source===`none`)return null}let c=null;if(n[`claim-domain`])c=!0;else if(n[`no-claim-domain`])c=!1;else if(s){let i=e.getServiceConfig(t)?.http?.domain;if(i){let e=await ra(i);e!==null&&!(e.project===r.id&&e.service===t)&&(Bc(n)?c=await $(`Domain ${i} is currently routed to ${Vc(e)}. Override it to point at this start (port ${o})?`):(c=!1,n.json||console.log(`Domain ${i} is currently routed to ${Vc(e)}; leaving the route untouched. Use --claim-domain to override.`)))}}return{port:o,claimDomain:c}}})),Wc,Gc=o((()=>{Y(),Lc(),zc(),Uc(),jc(),Wc=new J({name:`services:restart`,description:`Restart a service`,usage:`services restart <name> [--worktree <branch>] [--random-port] [--claim-domain]`,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:`worktree`,description:`Target the service in a sibling git worktree by branch name (use "main" for the primary checkout)`,required:!1,type:`string`},{name:`random-port`,description:`Skip the config port and start on a randomly allocated dev port`,required:!1,type:`boolean`,defaultValue:!1},{name:`claim-domain`,description:`Override the existing gateway route so the configured domain points at this start`,required:!1,type:`boolean`,defaultValue:!1},{name:`no-claim-domain`,description:`Leave the existing gateway route untouched even when the config port is busy`,required:!1,type:`boolean`,defaultValue:!1}],completions:({project:e,sdk:t})=>Ac(e,t),handler:async({project:e,worktree:t,args:n,flags:r})=>{let i=y.z.string().parse(n.name),a=t;if(typeof r.worktree==`string`)try{a=e.selectWorktree(r.worktree)}catch(e){let t=e instanceof Error?e.message:String(e);return r.json?console.log(JSON.stringify({success:!1,message:t})):console.error(t),{success:!1,message:t}}let{manager:o,serviceName:s,target:c}=await e.services.context(i),l=c,u=l.slug===a.slug?``:`${l.slug}/`,d=l.config.services?.[s];d&&await Ic(s,d,{json:!!r.json});let f=await Hc(o,s,r,l);if(f===null)return{success:!1,message:`Port resolution aborted.`};r.json||console.log(`Restarting ${u}${s}...`);let p=await o.restartService(s,{port:f.port,portResolved:!0,claimDomain:f.claimDomain??void 0});if(!p.success)return r.json?console.log(JSON.stringify({success:!1,service:s,project:l.slug,message:p.message})):console.error(`✗ Failed to restart ${u}${s}: ${p.message}`),{success:!1,message:p.message};await new Promise(e=>setTimeout(e,2e3));let m=await o.getServiceResponse(s,{includeLogs:!0});if(m?.status===`running`){if(await o.reconfigureGateway(),await Rc({json:!!r.json}),r.json)console.log(JSON.stringify(m));else{let e=m.url?` → ${m.url}`:``;console.log(`✓ ${u}${s} restarted successfully${e}`),m.localUrl&&m.localUrl!==m.url&&(m.configPort===null||m.configPort!==m.port)&&console.log(` ↳ direct: ${m.localUrl}`)}return{success:!0,message:`Service restarted successfully.`}}if(r.json)console.log(JSON.stringify(m));else if(console.error(`✗ ${u}${s} failed to restart`),m?.logs&&m.logs.length>0){console.error(``),console.error(`Recent logs:`);for(let e of m.logs)console.error(` ${e}`)}return{success:!1,message:`Service failed to restart.`}}})})),Kc,qc=o((()=>{Y(),Lc(),zc(),Uc(),jc(),Kc=new J({name:`services:start`,description:`Start a service`,usage:`services start <name> [--worktree <branch>] [--random-port] [--claim-domain]`,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:`worktree`,description:`Target the service in a sibling git worktree by branch name (use "main" for the primary checkout)`,required:!1,type:`string`},{name:`random-port`,description:`Skip the config port and start on a randomly allocated dev port`,required:!1,type:`boolean`,defaultValue:!1},{name:`claim-domain`,description:`Override the existing gateway route so the configured domain points at this start`,required:!1,type:`boolean`,defaultValue:!1},{name:`no-claim-domain`,description:`Leave the existing gateway route untouched even when the config port is busy`,required:!1,type:`boolean`,defaultValue:!1}],completions:({project:e,sdk:t})=>Ac(e,t),handler:async({project:e,worktree:t,args:n,flags:r})=>{let i=y.z.string().parse(n.name),a=t;if(typeof r.worktree==`string`)try{a=e.selectWorktree(r.worktree)}catch(e){let t=e instanceof Error?e.message:String(e);return r.json?console.log(JSON.stringify({success:!1,message:t})):console.error(t),{success:!1,message:t}}let{manager:o,serviceName:s,target:c}=await e.services.context(i),l=c,u=l.slug===a.slug?``:`${l.slug}/`,d=l.config.services?.[s];d&&await Ic(s,d,{json:!!r.json});let f=await Hc(o,s,r,l);if(f===null)return{success:!1,message:`Port resolution aborted.`};r.json||console.log(`Starting ${u}${s}...`);let p=await o.startService(s,{port:f.port,portResolved:!0,claimDomain:f.claimDomain??void 0});if(!p.success)return r.json?console.log(JSON.stringify({success:!1,service:s,project:l.slug,message:p.message})):console.error(`✗ Failed to start ${u}${s}: ${p.message}`),{success:!1,message:p.message};await new Promise(e=>setTimeout(e,2e3));let m=await o.getServiceResponse(s,{includeLogs:!0});if(m?.status===`running`){if(await o.reconfigureGateway(),await Rc({json:!!r.json}),r.json)console.log(JSON.stringify(m));else{let e=m.url?` → ${m.url}`:``;console.log(`✓ ${u}${s} started successfully${e}`),m.localUrl&&m.localUrl!==m.url&&(m.configPort===null||m.configPort!==m.port)&&console.log(` ↳ direct: ${m.localUrl}`)}return{success:!0,message:`Service started successfully.`}}if(r.json)console.log(JSON.stringify(m));else if(console.error(`✗ ${u}${s} failed to start`),m?.logs&&m.logs.length>0){console.error(``),console.error(`Recent logs:`);for(let e of m.logs)console.error(` ${e}`)}return{success:!1,message:`Service failed to start.`}}})})),Jc,Yc=o((()=>{oc(),q(),Y(),jc(),Jc=new J({name:`services:status`,description:`Show status of a specific service`,usage:`services status <name> [--worktree <branch>]`,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:`worktree`,description:`Target the service in a sibling git worktree by branch name (use "main" for the primary checkout)`,required:!1,type:`string`}],completions:({project:e,sdk:t})=>Ac(e,t),handler:async({project:e,worktree:t,args:n,flags:r})=>{let i=y.z.string().parse(n.name),a=t;if(typeof r.worktree==`string`)try{a=e.selectWorktree(r.worktree)}catch(e){let t=e instanceof Error?e.message:String(e);return r.json?console.log(JSON.stringify({success:!1,message:t})):console.error(t),{success:!1,message:t}}let{manager:o,serviceName:s,target:c}=await e.services.context(i),l=c,u=await o.getServiceResponse(s,{includeLogs:!0});if(!u){let e=l.slug===a.slug?``:` in project "${l.slug}"`;return r.json?console.log(JSON.stringify({success:!1,service:s,project:l.slug,message:`Service "${s}" not found in configuration${e}`})):console.error(`Service "${s}" not found in configuration${e}`),{success:!1,message:`Service "${s}" not found.`}}if(r.json)return console.log(JSON.stringify(u)),{success:!0,message:`Status retrieved successfully.`};let d=l.slug===a.slug?``:`${l.slug}/`,f=u.status===`running`?`Running`:u.status===`error`?`Error`:`Stopped`;console.log(`Service: ${d}${u.name}`),console.log(`Status: ${f}`),u.status===`running`&&u.pid&&console.log(`PID: ${u.pid}`),u.url&&console.log(`URL: ${u.url}`),u.localUrl&&u.localUrl!==u.url&&(u.configPort===null||u.configPort!==u.port)&&console.log(`Direct: ${u.localUrl}`),console.log(`Command: ${u.command}`),console.log(`CWD: ${u.cwd.replace((0,p.homedir)(),`~`)}`),console.log(`Logs: ${u.logPath.replace((0,p.homedir)(),`~`)}`);let m=o.getPlistPath(s);await E(m)&&console.log(`Plist: ${m.replace((0,p.homedir)(),`~`)}`);let h=(await I()).experimental?.gateway,g=o.getServiceConfig(s);if(h?.enabled&&g?.http?.domain){let e=ya(l.id,s,h.configsPath);await E(e)&&console.log(`Nginx: ${e}`)}if(u.lastExitCode!==null&&u.lastExitCode!==0&&u.status!==`running`&&console.log(`Last exit code: ${u.lastExitCode}`),u.logs&&u.logs.length>0){console.log(``),console.log(`Recent logs (last 10 lines):`);for(let e of u.logs.slice(-10))console.log(` ${e}`)}return{success:!0,message:`Status retrieved successfully.`}}})})),Xc,Zc=o((()=>{Y(),zc(),jc(),Xc=new J({name:`services:stop`,description:`Stop a service`,usage:`services stop <name> [--worktree <branch>]`,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:`worktree`,description:`Target the service in a sibling git worktree by branch name (use "main" for the primary checkout)`,required:!1,type:`string`}],completions:({project:e,sdk:t})=>Ac(e,t),handler:async({project:e,worktree:t,args:n,flags:r})=>{let i=y.z.string().parse(n.name),a=t;if(typeof r.worktree==`string`)try{a=e.selectWorktree(r.worktree)}catch(e){let t=e instanceof Error?e.message:String(e);return r.json?console.log(JSON.stringify({success:!1,message:t})):console.error(t),{success:!1,message:t}}let{manager:o,serviceName:s,target:c}=await e.services.context(i),l=c.slug===a.slug?``:`${c.slug}/`;r.json||console.log(`Stopping ${l}${s}...`);let u=await o.stopService(s);if(!u.success)return r.json?console.log(JSON.stringify({success:!1,service:s,project:c.slug,message:u.message})):console.error(`✗ Failed to stop ${l}${s}: ${u.message}`),{success:!1,message:u.message};let d=await o.getServiceResponse(s);return await Rc({json:!!r.json}),r.json?console.log(JSON.stringify(d)):console.log(`✓ ${l}${s} stopped successfully`),{success:!0,message:`Service stopped successfully.`}}})})),Qc,$c=o((()=>{q(),Y(),zc(),Qc=new J({name:`services:teardown`,description:`Stop all services and remove them from launchctl`,usage:`services teardown [--global] [--remove-logs] [--worktree <branch>]`,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},{name:`worktree`,description:`Teardown services for a sibling git worktree by branch name (use "main" for the primary checkout)`,required:!1,type:`string`}],handler:async({project:e,worktree:t,flags:n})=>{let r=n[`remove-logs`],i=n.global,a=typeof n.worktree==`string`?n.worktree:null;if(i&&a!==null){let e=`Cannot use --global and --worktree together.`;return n.json?console.log(JSON.stringify({success:!1,message:e})):console.error(e),{success:!1,message:e}}let o=t;if(a!==null)try{o=e.selectWorktree(a)}catch(e){let t=e instanceof Error?e.message:String(e);return n.json?console.log(JSON.stringify({success:!1,message:t})):console.error(t),{success:!1,message:t}}if(i){n.json||console.log(`Tearing down all denvig services globally...`);let e=await ao({removeLogs:r});if(n.json)console.log(JSON.stringify(e));else if(e.services.length===0)console.log(`No services found to teardown.`);else{for(let t of e.services)t.success?console.log(`✓ ${t.name} removed`):console.log(`✗ ${t.name}: ${t.message}`);console.log(``),console.log(`Teardown complete. ${e.services.filter(e=>e.success).length}/${e.services.length} services removed.`),r&&console.log(`Log files have been removed.`)}return await Rc({json:!!n.json}),{success:!0,message:`Global teardown complete`}}n.json||console.log(`Tearing down all services for ${o.slug}...`);let s=await e.teardown({removeLogs:r});if(n.json)console.log(JSON.stringify(s));else if(s.services.length===0)console.log(`No services found to teardown.`);else{for(let e of s.services)e.success?console.log(`✓ ${e.name} removed`):console.log(`✗ ${e.name}: ${e.message}`);console.log(``),console.log(`Teardown complete. ${s.services.filter(e=>e.success).length}/${s.services.length} services removed.`),r&&console.log(`Log files have been removed.`)}return await Rc({json:!!n.json}),{success:!0,message:`Teardown complete`}}})})),el=s({servicesCommand:()=>tl}),tl,nl=o((()=>{Y(),kc(),Nc(),Gc(),qc(),Yc(),Zc(),$c(),tl=new J({name:`services`,description:`Manage services across projects`,usage:`services <subcommand>`,example:`denvig services list`,args:[],flags:[],subcommands:{list:Oc,start:Kc,stop:Xc,restart:Wc,status:Jc,logs:Mc,teardown:Qc},defaultSubcommand:`list`,handler:()=>({success:!0})})})),rl=s({internalsResourceHashCommand:()=>il,internalsResourceIdCommand:()=>al}),il,al,ol=o((()=>{Y(),il=new J({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:e,args:t,flags:n})=>{let r=t.resource,i=n.workspace,a=r;if(r.startsWith(`@`)){let e=r.match(/^@([^#]+)#([^|]+)\|(.+)$/);if(!e)return n.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`};i=e[2],a=e[3]}else if(r.includes(`|`)){let e=r.split(`|`);i=e[0],a=e[1]}if(!a.startsWith(`action/`)&&!a.startsWith(`service/`))return n.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 o=e.resourceHash({workspace:i,resource:a});return n.json?console.log(JSON.stringify(o)):console.log(`${o.id}\n${o.hash}`),{success:!0,message:`Hash generated successfully`}}}),al=new J({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:e,args:t,flags:n})=>{let r=t.resource,i=n.workspace,a=r;if(r.includes(`|`)){let e=r.split(`|`);i=e[0],a=e[1]}if(!a.startsWith(`action/`)&&!a.startsWith(`service/`))return n.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 o=e.resourceId({workspace:i,resource:a});return n.json?console.log(JSON.stringify({id:o})):console.log(o),{success:!0,message:`ID generated successfully`}}})})),sl,cl=o((()=>{Y(),Q(),sl=new J({name:`deps:dedupe`,description:`Deduplicate lockfile dependencies by combining compatible versions`,usage:`deps dedupe [--apply]`,example:`denvig deps dedupe`,args:[],flags:[{name:`apply`,description:`Apply deduplication changes to the lockfile and run install`,required:!1,type:`boolean`,defaultValue:!1}],handler:async({worktree:e,flags:t})=>{let n=t.apply,r=await e.deduplicateDependencies({dryRun:!n});if(r.length===0)return console.error(`Dependency deduplication is not supported for this project.`),{success:!1,message:`No supported package manager found.`};let i=!1;for(let e of r){if(Object.keys(e.removals).length===0)continue;i=!0;let r=Object.values(e.removals).flat().length;if(t.json)console.log(JSON.stringify({ecosystem:e.ecosystem,optimised:!1,totalDependencies:e.totalDependencies,optimisedDependencies:e.optimisedDependencies,changes:e.details,applied:e.applied}));else{console.log(`Can be optimised from ${e.totalDependencies} to ${e.optimisedDependencies} resolved versions (${e.ecosystem})`),console.log(``);for(let t of e.details){let e=t.versions.map(e=>t.optimisedVersions.includes(e)?`${Z.green}${e}${Z.reset}`:`${Z.red}${e}${Z.reset}`);console.log(`${t.name}: ${e.join(`, `)}`)}console.log(``),console.log(n?`Removed ${r} duplicate version(s).`:`${r} duplicate version(s) can be removed. Run with --apply to apply.`)}}return i||(t.json?console.log(JSON.stringify({optimised:!0,changes:[]})):console.log(`No deduplication possible. Lockfiles are already optimised.`)),{success:!0,message:`Deduplication complete.`}}})})),ll,ul=o((()=>{Y(),Q(),ll=new J({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:e,flags:t})=>{let n=t.ecosystem,r=t.depth??0,i=await e.dependencies.list();if(i.length===0)return t.json?console.log(JSON.stringify([])):console.log(`No dependencies detected in this project.`),{success:!0,message:`No dependencies detected.`};let a=await e.dependencies.tree({depth:r,ecosystem:n});if(a.length===0){if(t.json)console.log(JSON.stringify([]));else{let e=n?`No dependencies found for ecosystem "${n}".`:`No direct dependencies detected in this project.`;console.log(e)}return{success:!0,message:n?`No dependencies found for ecosystem "${n}".`:`No direct dependencies detected in this project.`}}if(t.json)return console.log(JSON.stringify(i)),{success:!0,message:`Dependencies listed successfully.`};let o=Ec({columns:[{header:`Package`,accessor:e=>e.name},{header:``,accessor:e=>e.depth===0&&e.isDevDependency?`${Z.grey}(dev)${Z.reset}`:` `},{header:`Current`,accessor:e=>e.version},{header:`Ecosystem`,accessor:e=>e.ecosystem,visible:new Set(a.map(e=>e.ecosystem)).size>1&&!n}],data:a,tree:{getDepth:e=>e.depth,getIsLast:e=>e.isLast,getHasChildren:e=>e.hasChildren,getParentPath:e=>e.parentPath}});for(let e of o)console.log(e);let s=a.filter(e=>e.depth===0),c=s.filter(e=>!e.isDevDependency).length,l=s.filter(e=>e.isDevDependency).length,u=i.length-s.length;return console.log(``),console.log(`${i.length} total (${c} dependencies, ${l} devDependencies, ${u} subdependencies)`),{success:!0,message:`Dependencies listed successfully.`}}})})),dl,fl=o((()=>{dl=(e,t=new Date)=>{let n=new Date(e),r=Math.abs(t.getTime()-n.getTime())/1e3,i=r/60,a=i/60,o=a/24,s=o/7,c=o/30.44,l=o/365.25;return l>=1?`${Math.round(l)}y`:c>=1?`${Math.round(c)}mo`:s>=1?`${Math.round(s)}w`:o>=1?`${Math.round(o)}d`:a>=1?`${Math.round(a)}h`:i>=1?`${Math.round(i)}m`:`${Math.round(r)}s`}})),pl,ml,hl,gl,_l,vl=o((()=>{ss(),q(),ac(),Y(),fl(),Q(),pl=10080*60*1e3,ml=()=>{let e=Rr(pl);if(e===0)return;let t=e===1?`certificate is`:`certificates are`;console.log(``),console.log(`${Z.yellow}${e} ${t} due to expire. Run denvig certs for details.${Z.reset}`)},hl=(e,t)=>{if(e===t)return Z.white;let n=co(e,t);return n?n===`major`?Z.red:n===`minor`?Z.yellow:n===`patch`?Z.green:Z.white:Z.white},gl=(e,t,n)=>{let r=process.env.DENVIG_OPEN_VIA||`npm`;return r===`none`?null:n===`npm`?r===`npmx`?`https://npmx.dev/package/${e}/v/${t}`:`https://www.npmjs.com/package/${e}/v/${t}`:null},_l=new J({name:`deps:outdated`,description:`Show outdated dependencies`,usage:`deps outdated [--no-cache] [--semver patch|minor|major] [--ecosystem <name>] [--release-latency <duration>]`,example:`denvig deps outdated --release-latency 7d`,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, "major" for major updates only`,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:`release-latency`,description:`Only show updates released longer ago than this duration (e.g., "3h", "7d", "2w"). Use "auto" to read from pnpm minimumReleaseAge with a 24h fallback, or "0" to disable.`,required:!1,type:`string`,defaultValue:`auto`}],handler:async({project:e,flags:t})=>{let n=t.semver,r=t.ecosystem,i=t[`release-latency`],a=e=>e.versions[0]?.resolved||``,o;try{o=await e.dependencies.outdated({noCache:t[`no-cache`],semver:n,ecosystem:r,releaseLatency:i})}catch(e){if(e instanceof b)return console.error(e.message),{success:!1,message:e.message};throw e}let s=o;if(s.length===0){if(t.json)console.log(JSON.stringify([]));else{let e=`All dependencies are up to date!`;r&&n?e=`No ${n}-level updates available for ecosystem "${r}".`:r?e=`No outdated dependencies found for ecosystem "${r}".`:n&&(e=`No ${n}-level updates available.`),console.log(e),ml()}let e=`All dependencies are up to date!`;return r&&n?e=`No ${n}-level updates available for ecosystem "${r}".`:r?e=`No outdated dependencies found for ecosystem "${r}".`:n&&(e=`No ${n}-level updates available.`),{success:!0,message:e}}if(t.json)return console.log(JSON.stringify(o)),{success:!0,message:`Outdated dependencies listed.`};let c=Ec({columns:[{header:`Package`,accessor:e=>e.name},{header:``,accessor:e=>e.isDevDependency?`${Z.grey}(dev)${Z.reset}`:` `},{header:`Current`,accessor:e=>e.currentDate?`${a(e)} (${dl(e.currentDate)})`:a(e),format:(e,t)=>{let n=a(t),r=gl(t.name,n,t.ecosystem);if(t.currentDate){let t=e.indexOf(` (`),n=e.slice(0,t),i=e.slice(t);return`${r?wc(n,r):n}${Z.grey}${i}${Z.reset}`}return r?wc(e.trimEnd(),r)+e.slice(e.trimEnd().length):e}},{header:`Wanted`,accessor:e=>e.wanted===a(e)?`-`:e.wantedDate?`${e.wanted} (${dl(e.wantedDate)})`:e.wanted,format:(e,t)=>{if(e.trimEnd()===`-`)return e;let n=hl(a(t),t.wanted),r=gl(t.name,t.wanted,t.ecosystem);if(t.wantedDate){let t=e.indexOf(` (`),i=e.slice(0,t),a=e.slice(t);return`${r?wc(`${n}${i}${Z.reset}`,r):`${n}${i}${Z.reset}`}${Z.grey}${a}${Z.reset}`}let i=r?wc(`${n}${e.trimEnd()}${Z.reset}`,r):`${n}${e}${Z.reset}`;return r?i+e.slice(e.trimEnd().length):i}},{header:`Latest`,accessor:e=>e.latestDate?`${e.latest} (${dl(e.latestDate)})`:e.latest,format:(e,t)=>{let n=hl(a(t),t.latest),r=gl(t.name,t.latest,t.ecosystem);if(t.latestDate){let t=e.indexOf(` (`),i=e.slice(0,t),a=e.slice(t);return`${r?wc(`${n}${i}${Z.reset}`,r):`${n}${i}${Z.reset}`}${Z.grey}${a}${Z.reset}`}let i=r?wc(`${n}${e.trimEnd()}${Z.reset}`,r):`${n}${e}${Z.reset}`;return r?i+e.slice(e.trimEnd().length):i}},{header:`Ecosystem`,accessor:e=>e.ecosystem,visible:new Set(s.map(e=>e.ecosystem)).size>1&&!r}],data:o});for(let e of c)console.log(e);return ml(),{success:!0,message:`Outdated dependencies listed.`}}})})),yl,bl,xl,Sl=o((()=>{Q(),yl=e=>{let t=e.color?`${e.color}${e.name} ${e.version}${Z.reset}`:`${e.name} ${Z.grey}${e.version}${Z.reset}`;return e.suffix?`${t} ${e.suffix}`:t},bl=(e,t=``,n=!0,r=!0)=>{let i=[],a=e.children.length>0;if(r)i.push(yl(e));else{let r=a?n?`└─┬ `:`├─┬ `:n?`└── `:`├── `;i.push(`${t}${r}${yl(e)}`)}let o=r?``:t+(n?` `:`│ `);for(let t=0;t<e.children.length;t++){let n=e.children[t],r=t===e.children.length-1;i.push(...bl(n,o,r,!1))}return i},xl=(e,t)=>{let n=e.find(e=>e.name===t.name&&e.version===t.version);if(n)for(let e of t.children)xl(n.children,e);else e.push(t)}})),Cl,wl,Tl,El,Dl=o((()=>{q(),ac(),Y(),Q(),Sl(),Cl=e=>e===`major`?Z.red:e===`minor`?Z.yellow:Z.green,wl=(e,t)=>{try{return g.default.gt(t,e)}catch{return!1}},Tl=e=>{if(e.length===0)return``;let t=e.map(({version:e,color:t})=>`${t}${e}${Z.reset}`).join(`${Z.grey}, ${Z.reset}`);return`${Z.grey}(${Z.reset}${t}${Z.grey})${Z.reset}`},El=new J({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:[{name:`check-all-versions`,description:`Fetch latest versions from the registry for every entry in the tree. Off by default since registry lookups can be slow; without this flag only the queried package is checked.`,required:!1,type:`boolean`,defaultValue:!1}],completions:async({project:e})=>(await e.activeWorktree.dependencies()).map(e=>e.name),handler:async({project:e,worktree:t,args:n,flags:r})=>{let i=n.dependency,a=await t.dependencies(),o=a.find(e=>e.name===i);if(!o)return r.json?console.log(JSON.stringify({dependency:i,found:!1,dependencies:[],devDependencies:[]})):console.log(`Dependency "${i}" not found in this project.`),{success:!1,message:`Dependency not found.`};let s=new Map;for(let e of a)s.set(e.name,e);let c=[],l=[];for(let e of o.versions){let t=we(o.name,e.resolved,e.source,s);if(!t)continue;let n=s.get(t.name)?.versions.find(e=>e.resolved===t.version);n&&Se(n.source)?xl(l,t):xl(c,t)}let u=e=>{e.children.sort((e,t)=>e.name.localeCompare(t.name));for(let t of e.children)u(t)};for(let e of c)u(e);for(let e of l)u(e);let d=[...c.map(e=>({tree:e,isDev:!1})),...l.map(e=>({tree:e,isDev:!0}))].sort((e,t)=>e.tree.name.localeCompare(t.tree.name)),f=r[`check-all-versions`],p=new Map;if(f){let e=(t,n=0)=>t.children.length===0?n:Math.max(...t.children.map(t=>e(t,n+1))),n=d.reduce((t,{tree:n})=>Math.max(t,e(n)),0),r=await t.outdatedDependencies({cache:!0,depth:n}).catch(()=>[]);for(let e of r)p.set(e.name,{latest:e.latest,wanted:e.wanted})}else{let t=await e.dependencies.info(`${o.ecosystem}:${o.name}`).catch(()=>null);t?.latest&&p.set(o.name,{latest:t.latest,wanted:t.latest})}let m=(e,t)=>{let n=p.get(e);if(!n)return[];let r=[n.wanted,n.latest].filter(e=>typeof e==`string`&&e.length>0),i=[],a=new Set([t]);for(let e of r){if(a.has(e)||!wl(t,e))continue;let n=co(t,e);n&&(a.add(e),i.push({version:e,color:Cl(n)}))}return i},h=(e,t,n)=>{let r=[];t&&n&&r.push(`${Z.grey}(dev)${Z.reset}`);let i=Tl(m(e.name,e.version));return i&&r.push(i),r.length>0?r.join(` `):void 0},g=(e,t,n)=>({...e,color:e.name===i?Z.white:Z.grey,suffix:h(e,t,n),children:e.children.map(e=>g(e,!1,!1))});if(r.json)return console.log(JSON.stringify({dependency:i,found:!0,project:{name:t.name,path:t.path},dependencies:c,devDependencies:l})),{success:!0,message:`Dependency chain shown.`};if(d.length===0)return console.log(`Could not determine dependency chain for "${i}".`),{success:!0,message:`Dependency chain shown.`};for(let{tree:e,isDev:t}of d){let n=bl(g(e,!0,t),``,!0,!0);for(let e of n)console.log(e)}return{success:!0,message:`Dependency chain shown.`}}})})),Ol=s({depsCommand:()=>kl}),kl,Al=o((()=>{Y(),cl(),ul(),vl(),Dl(),kl=new J({name:`deps`,description:`Manage project dependencies`,usage:`deps <subcommand>`,example:`denvig deps list`,args:[],flags:[],subcommands:{list:ll,outdated:_l,why:El,dedupe:sl},defaultSubcommand:`list`,handler:()=>({success:!0})})})),jl,Ml,Nl,Pl=o((()=>{q(),ac(),Y(),jl=e=>{switch(e){case`running`:return`🟢`;case`stopped`:return`◯`;default:return``}},Ml=async(e,t,n)=>(e.selectWorktree(t),(await e.info({launchctlList:n})).serviceStatus),Nl=new J({name:`projects:list`,description:`List all projects on the system`,usage:`projects list [--with-config]`,example:`projects list --json`,args:[],flags:[{name:`with-config`,description:`Only show projects with a .denvig.yml configuration file`,required:!1,type:`boolean`,defaultValue:!1}],handler:async({sdk:e,flags:t})=>{let n=t[`with-config`],r=await e.projects.list({withConfig:n});if(r.length===0)return t.json?console.log(JSON.stringify([])):console.log(`No projects found.`),{success:!0,message:`No projects found.`};if(t.json){let e=[];for(let t of r){let{serviceStatus:n,...r}=await t.info({includeServiceStatus:!1});e.push(r)}return console.log(JSON.stringify(e)),{success:!0,message:`Projects listed successfully.`}}let i=await j.list(`denvig.`),a=[];for(let e of r){let t=e.worktrees.list().filter(e=>!e.isPrimary),n=e.primaryWorktree;a.push({status:await Ml(e,n.branch,i),label:n.config.name||n.slug,path:n.path,depth:0});for(let n of t)a.push({status:await Ml(e,n.branch,i),label:n.branch,path:n.path,depth:1})}let o=e=>e.depth>0?`└ ${e.label}`:e.label,s=Math.max(...a.map(e=>o(e).length));for(let e of a){let t=jl(e.status)||` `,n=o(e).padEnd(s);console.log(`${t} ${n} ${G(e.path)}`)}return console.log(``),console.log(`${r.length} project${r.length===1?``:`s`} found`),{success:!0,message:`Projects listed successfully.`}}})})),Fl=s({projectsCommand:()=>Il}),Il,Ll=o((()=>{Y(),Pl(),Il=new J({name:`projects`,description:`Manage projects on the system`,usage:`projects <subcommand>`,example:`denvig projects list`,args:[],flags:[],subcommands:{list:Nl},defaultSubcommand:`list`,handler:()=>({success:!0})})})),Rl,zl=o((()=>{Y(),Rl=new J({name:`certs:ca:info`,description:`Display information about the local Certificate Authority`,usage:`certs ca info`,example:`denvig certs ca info`,args:[],flags:[],handler:async({sdk:e,flags:t})=>{let n=await e.certs.ca.status();if(!n.initialized){let e="CA has not been initialized. Run `denvig certs ca install` first.";return t.json?console.log(JSON.stringify({success:!1,error:e})):console.error(e),{success:!1,message:e}}let r={subject:n.subject,issuer:n.issuer,validFrom:n.validFrom,validTo:n.validTo,serialNumber:n.serialNumber,fingerprint256:n.fingerprint256,path:n.path};return t.json?(console.log(JSON.stringify(r)),{success:!0,message:`CA info displayed.`}):(console.log(`Subject: `,r.subject),console.log(`Issuer: `,r.issuer),console.log(`Valid from: `,r.validFrom),console.log(`Valid to: `,r.validTo),console.log(`Serial: `,r.serialNumber),console.log(`Fingerprint: `,r.fingerprint256),console.log(`Path: `,r.path),{success:!0,message:`CA info displayed.`})}})})),Bl,Vl=o((()=>{Y(),Bl=new J({name:`certs:ca:install`,description:`Initialize a local Certificate Authority and install it to the system keychain`,usage:`certs ca install`,example:`denvig certs ca install`,args:[],flags:[],handler:async({sdk:e})=>{if((await e.certs.ca.status()).initialized){let{path:t}=await e.certs.ca.configure();return console.log(`CA already exists at`,t),console.log(`Reinstalling CA to system keychain...`),console.log(`CA reinstalled to system keychain.`),{success:!0,message:`CA already exists, reinstalled to keychain.`}}console.log(`Generating new Certificate Authority...`);let{path:t}=await e.certs.ca.configure();return console.log(`CA certificate written to`,t),console.log(`Installing CA to system keychain...`),console.log(`CA installed to system keychain.`),{success:!0,message:`CA initialized and installed.`}}})})),Hl,Ul=o((()=>{Y(),Hl=new J({name:`certs:ca:uninstall`,description:`Remove the local Certificate Authority from the system keychain`,usage:`certs ca uninstall`,example:`denvig certs ca uninstall`,args:[],flags:[],handler:async({sdk:e,flags:t})=>{if(!(await e.certs.ca.status()).initialized){let e="CA has not been initialized. Run `denvig certs ca install` first.";return t.json?console.log(JSON.stringify({success:!1,error:e})):console.error(e),{success:!1,message:e}}if(t.json){let{path:t}=await e.certs.ca.remove();console.log(JSON.stringify({success:!0,path:t}))}else console.log(`Removing CA from system keychain...`),await e.certs.ca.remove(),console.log(`CA removed from system keychain.`);return{success:!0,message:`CA uninstalled from keychain.`}}})})),Wl,Gl=o((()=>{Y(),zl(),Vl(),Ul(),Wl=new J({name:`certs:ca`,description:`Manage the local Certificate Authority`,usage:`certs ca <subcommand>`,example:`denvig certs ca info`,args:[],flags:[],subcommands:{install:Bl,uninstall:Hl,info:Rl},defaultSubcommand:`info`,handler:Rl.handler})})),Kl,ql=o((()=>{Y(),Fc(),Kl=new J({name:`certs:generate`,description:`Generate a TLS certificate for a domain signed by the local CA`,usage:`certs generate <domain>`,example:`denvig certs generate "*.denvig.localhost"`,args:[{name:`domain`,description:`Domain name to generate a certificate for (e.g., *.denvig.localhost)`,required:!0,type:`string`}],flags:[],handler:async({sdk:e,args:t,flags:n})=>{let r=t.domain;if(!(await e.certs.ca.status()).initialized)return console.error("CA not initialized. Run `denvig certs init` first."),{success:!1,message:`CA not initialized.`};if(!n.json&&await e.certs.retrieve({domain:r})&&!await $(`Certificate already exists for ${r}. Overwrite?`))return console.log(`Cancelled.`),{success:!0,message:`Cancelled.`};let i=await e.certs.create({domain:r,force:!0});return n.json?console.log(JSON.stringify({domain:i.domain,privkey:i.privkey,fullchain:i.fullchain})):(console.log(`Certificate generated for ${r}`),console.log(` privkey: ${i.privkey}`),console.log(` fullchain: ${i.fullchain}`)),{success:!0,message:`Certificate generated for ${r}.`}}})})),Jl,Yl,Xl=o((()=>{ss(),Y(),Jl=y.z.string().regex(/^(\*\.)?([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\.)*[a-zA-Z]{2,}$/,`Must be a valid domain (e.g., example.com or *.example.com)`),Yl=new J({name:`certs:import`,description:`Import an existing TLS certificate and private key`,usage:`certs import --key <path> --cert <path>`,example:`denvig certs import --key ./privkey.pem --cert ./fullchain.pem`,args:[],completions:(e,t)=>{let n=t[t.length-2];return n===`--key`||n===`--cert`||n===`--name`?[]:[`--key`,`--cert`,`--name`]},flags:[{name:`key`,description:`Path to the private key PEM file`,required:!0,type:`string`},{name:`cert`,description:`Path to the certificate PEM file`,required:!0,type:`string`},{name:`name`,description:`Override the directory name for the imported certificate (defaults to auto-detected domain)`,required:!1,type:`string`}],handler:async({sdk:e,flags:t})=>{let n;if(t.name){let e=Jl.safeParse(t.name);if(!e.success){let t=e.error.issues[0]?.message??`Invalid domain name`;return console.error(`Invalid --name value: ${t}`),{success:!1,message:t}}n=e.data}let r;try{r=await e.certs.import({keyPath:t.key,certPath:t.cert,name:n})}catch(e){if(e instanceof b)return console.error(e.message),{success:!1,message:e.message};throw e}return t.json?console.log(JSON.stringify({domain:r.domain,privkey:r.privkey,fullchain:r.fullchain})):(console.log(`Certificate imported for ${r.domain}`),console.log(` privkey: ${r.privkey}`),console.log(` fullchain: ${r.fullchain}`)),{success:!0,message:`Certificate imported for ${r.domain}.`}}})})),Zl,Ql=o((()=>{Vl(),Zl=Bl})),$l,eu,tu,nu,ru,iu=o((()=>{Y(),fl(),Q(),$l=1440*60*1e3,eu=7*$l,tu=(e,t=new Date)=>{let n=e.getTime()-t.getTime();return n<$l?Z.red:n<eu?Z.yellow:Z.green},nu=e=>e.status===`expired`?`expired`:e.signedByLocalCa?e.caTrusted?`valid (local-ca)`:`untrusted`:`valid (${e.issuer?e.issuer.toLowerCase():`unknown`})`,ru=new J({name:`certs:list`,description:`List all managed TLS certificates`,usage:`certs list`,example:`denvig certs list`,args:[],flags:[],handler:async({sdk:e,flags:t})=>{let n=await e.certs.list();if(n.length===0)return t.json?console.log(JSON.stringify([])):console.log(`No certificates found.`),{success:!0,message:`No certificates found.`};let r=n.map(e=>({dir:e.name,domains:e.domains,expires:new Date(e.expires),status:nu(e)}));if(t.json)return console.log(JSON.stringify(r.map(e=>({domains:e.domains,expires:e.expires.toISOString(),status:e.status})))),{success:!0,message:`Certificates listed.`};let i=[];for(let[e,t]of r.entries()){let n=e===r.length-1;i.push({name:t.dir,expires:t.expires,status:t.status,depth:0,isLast:n,hasChildren:t.domains.length>0,parentPath:[]});for(let[e,r]of t.domains.entries()){let a=e===t.domains.length-1;i.push({name:r,expires:t.expires,status:t.status,depth:1,isLast:a,hasChildren:!1,parentPath:[n]})}}let a=Ec({columns:[{header:`Certificate`,accessor:e=>e.name},{header:`Expires`,accessor:e=>e.depth===0?`${e.expires.toISOString().slice(0,10)} (${dl(e.expires.toISOString())})`:``,format:(e,t)=>{if(t.depth!==0)return e;let n=e.trimEnd();if(!n)return e;let r=tu(t.expires),i=` `.repeat(e.length-n.length);return`${r}${n}${Z.reset}${i}`}},{header:`Status`,accessor:e=>e.depth===0?e.status:``,format:(e,t)=>{let n=e.trim();return n?t.status===`expired`?`${Z.red}${n}${Z.reset}`:t.status===`untrusted`?`${Z.yellow}${n}${Z.reset}`:t.status.startsWith(`valid`)?`${Z.green}${n}${Z.reset}`:n:e}}],data:i,tree:{getDepth:e=>e.depth,getIsLast:e=>e.isLast,getHasChildren:e=>e.hasChildren,getParentPath:e=>e.parentPath}});for(let e of a)console.log(e);return console.log(``),console.log(`${r.length} certificate${r.length===1?``:`s`}`),{success:!0,message:`Certificates listed.`}}})})),au,ou=o((()=>{Y(),Fc(),au=new J({name:`certs:rm`,description:`Remove a certificate by its directory name`,usage:`certs rm <name>`,example:`denvig certs rm _wildcard.upvio.dev`,args:[{name:`name`,description:`Certificate directory name (e.g., _wildcard.upvio.dev)`,required:!0,type:`string`}],flags:[],handler:async({sdk:e,args:t,flags:n})=>{let r=t.name,i=await e.certs.retrieve({name:r});if(!i){let e=`Certificate "${r}" not found.`;return n.json?console.log(JSON.stringify({success:!1,name:r,message:e})):console.error(e),{success:!1,message:e}}if(!n.json){console.log(`Certificate: ${r}`);for(let e of i.files)console.log(` ${e}`);if(!await $(`Remove this certificate?`))return console.log(`Cancelled.`),{success:!0,message:`Cancelled.`}}return await e.certs.remove({name:r}),n.json?console.log(JSON.stringify({success:!0,name:r})):console.log(`Removed ${r}`),{success:!0,message:`Removed ${r}.`}}})})),su=s({certsCommand:()=>cu}),cu,lu=o((()=>{Y(),Gl(),ql(),Xl(),Ql(),iu(),ou(),cu=new J({name:`certs`,description:`Manage local TLS certificates`,usage:`certs <subcommand>`,example:`denvig certs list`,args:[],flags:[],subcommands:{list:ru,ca:Wl,init:Zl,generate:Kl,import:Yl,rm:au},defaultSubcommand:`list`,handler:()=>({success:!0})})})),uu,du=o((()=>{uu=async()=>{let{runCommand:e}=await Promise.resolve().then(()=>(ic(),nc)),{configCommand:t}=await Promise.resolve().then(()=>(fc(),lc)),{pluginsCommand:n}=await Promise.resolve().then(()=>(hc(),pc)),{versionCommand:r}=await Promise.resolve().then(()=>(vc(),gc)),{infoCommand:i}=await Promise.resolve().then(()=>(Sc(),yc)),{servicesCommand:a}=await Promise.resolve().then(()=>(nl(),el)),{depsCommand:o}=await Promise.resolve().then(()=>(Al(),Ol)),{projectsCommand:s}=await Promise.resolve().then(()=>(Ll(),Fl)),{certsCommand:c}=await Promise.resolve().then(()=>(lu(),su)),{shellCommand:l}=await Promise.resolve().then(()=>(Ou(),Eu));return{run:e,config:t,plugins:n,version:r,info:i,services:a,deps:o,projects:s,shell:l,certs:c}}})),fu,pu,mu=o((()=>{ss(),fu=async(e=``,t=new as({client:`cli`}))=>{if(e.startsWith(`/`)||e.startsWith(`~`))return[];let n=await t.projects.list();return e.startsWith(`id:`)?n.map(e=>`id:${e.id.slice(0,8)}`).filter(t=>t.startsWith(e)):n.map(e=>e.slug.replace(/^(github|local):/,``)).filter(t=>t.startsWith(e))},pu=e=>{let t=e[e.length-1]||``;return t.startsWith(`--project=`)?t.slice(10):e.length>=2&&e[e.length-2]===`--project`?t:null}})),hu,gu,_u,vu=o((()=>{mu(),hu=e=>Object.keys(e.subcommands).filter(e=>!e.startsWith(`__`)),gu=(e,t)=>{if(e.length===0)return{command:void 0,remaining:[]};let n=t[e[0]];if(!n)return{command:void 0,remaining:e};let r=1;for(;r<e.length&&n.hasSubcommands;){let t=e[r];if(n.subcommands[t])n=n.subcommands[t],r++;else break}return{command:n,remaining:e.slice(r)}},_u=async(e,t)=>{let n=pu(e);if(n!==null)return fu(n,t?.sdk);let r=t?.commands??{},i=Object.keys(r).filter(e=>!e.includes(`:`));if(e.length===1)return i;let a=e[1],o=r[a];if(e.length===2){if(o?.hasSubcommands)return hu(o);if(i.includes(a)&&t?.commands&&t?.project){let e=t.commands[a];return e?.completions?await e.completions({project:t.project,sdk:t.sdk},[]):[]}return i.filter(e=>e.startsWith(a))}if(!o)return[];let{command:s,remaining:c}=gu(e.slice(1),r);if(!s)return[];if(s.hasSubcommands&&c.length<=1){let e=c[0]||``,n=hu(s);if(e&&!s.subcommands[e])return n.filter(t=>t.startsWith(e));if(e&&s.subcommands[e]){let n=s.subcommands[e];return n.hasSubcommands?hu(n):n.completions&&t?.project?await n.completions({project:t.project,sdk:t.sdk},[]):[]}return n}if(s.completions&&t?.project){let e=await s.completions({project:t.project,sdk:t.sdk},c),n=c[c.length-1]||``;return n?e.filter(e=>e.startsWith(n)):e}return[]}})),yu,bu=o((()=>{Y(),du(),vu(),yu=new J({name:`shell:__complete__`,description:`Handle shell completion requests (internal)`,usage:`shell __complete__ -- <words...>`,example:`denvig shell __complete__ -- denvig services`,args:[],flags:[],acceptsExtraArgs:!0,handler:async({sdk:e,project:t,extraArgs:n=[]})=>{let r=await _u(n,{sdk:e,project:t,commands:await uu()});for(let e of r)console.log(e.replace(/:/g,`\\:`));return{success:!0}}})})),xu,Su,Cu,wu,Tu=o((()=>{oc(),Y(),xu=[`zsh`],Su=`#compdef denvig
213
+
214
+ _denvig() {
215
+ local -a completions
216
+ local line
217
+
218
+ # Get completions from denvig itself
219
+ completions=("\${(@f)$(denvig shell __complete__ -- "\${words[@]}" 2>/dev/null)}")
220
+
221
+ if [[ \${#completions[@]} -gt 0 && -n "\${completions[1]}" ]]; then
222
+ _describe 'denvig' completions
223
+ else
224
+ _files
225
+ fi
226
+ }
227
+
228
+ _denvig "$@"
229
+ `,Cu=async()=>{let e=m.join(p.homedir(),`.zsh`,`completions`),t=m.join(e,`_denvig`);return await E(e)||await(0,f.mkdir)(e,{recursive:!0}),await(0,f.writeFile)(t,Su),t},wu=new J({name:`shell:completions`,description:`Output a shell completion script`,usage:`shell completions <shell> [--install]`,example:`denvig shell completions zsh --install`,args:[{name:`shell`,description:`Shell to generate completions for (${xu.join(`, `)})`,required:!0,type:`string`}],flags:[{name:`install`,description:`Install completions to the shell completions directory`,required:!1,type:`boolean`,defaultValue:!1}],handler:async({args:e,flags:t})=>{let n=String(e.shell);if(!xu.includes(n)){let e=`Unsupported shell for completions: ${n}. Supported shells: ${xu.join(`, `)}`;return console.error(e),{success:!1,message:e}}if(t.install){let e=await Cu();return console.log(`Installed completions to ${e}`),{success:!0}}return console.log(Su),{success:!0}}})})),Eu=s({shellCommand:()=>Du}),Du,Ou=o((()=>{Y(),bu(),Tu(),Du=new J({name:`shell`,description:`Shell integration helpers`,usage:`shell <subcommand>`,example:`denvig shell completions zsh --install`,args:[],flags:[],subcommands:{completions:wu,__complete__:yu},handler:()=>(console.log(`Usage: denvig shell <subcommand>`),console.log(``),console.log(`Subcommands:`),console.log(` completions Output a shell completion script`),{success:!0})})})),ku,Au=o((()=>{Y(),ku=new J({name:`gateway:configure`,description:`Reconcile launchctl with ~/.denvig/state.json and rebuild all nginx configs`,usage:`gateway configure`,example:`gateway configure`,args:[],flags:[],handler:async({sdk:e,flags:t})=>{let{reconcile:n,gateway:r}=await e.gateway.configure();if(!r)return console.error(`Gateway is not enabled. Add experimental.gateway.enabled: true to ~/.denvig/config.yml`),{success:!1,message:`Gateway is not enabled`};if(t.json)console.log(JSON.stringify({reconcile:n,gateway:r},null,2));else{if(n.actions.length>0){for(let e of n.actions){let t=e.type===`started`?`▶`:e.type===`stopped`?`■`:e.type===`restarted`?`↻`:`·`;console.log(`${t} ${e.type} ${e.project}/${e.service} — ${e.reason}`)}console.log(``)}for(let e of n.errors)console.error(`reconcile: ${e.project}/${e.service}: ${e.message}`);if(console.log(``),r.removed.length>0&&(console.log(`Removed ${r.removed.length} existing config${r.removed.length===1?``:`s`}`),console.log(``)),r.services.length===0)console.log(`No services with http.domain and http.port configured.`);else{console.log(`Gateway Configuration:`),console.log(``);for(let e of r.services){let t=e.certStatus===`valid`?`✓`:`✗`,n=e.configStatus===`written`?`✓`:`✗`,r=e.cnames.length>0?` + ${e.cnames.length} cname${e.cnames.length>1?`s`:``}`:``;console.log(` ${e.projectSlug}/${e.serviceName}:`),console.log(` Domain: ${e.domain}${r} -> localhost:${e.port}`);let i=e.certDir?` (${e.certDir.split(`/`).pop()})`:e.certMessage?` (${e.certMessage})`:``;console.log(` Certs: ${t} ${e.certStatus}${i}`),console.log(` Nginx: ${n} ${e.configStatus}${e.configMessage?` (${e.configMessage})`:``}`),console.log(``)}}r.nginxReload?console.log(`Nginx reloaded successfully`):console.log(`Nginx reload failed: ${r.nginxReloadMessage}`),console.log(``)}return{success:r.success,message:r.message}}})})),ju,Mu=o((()=>{Y(),ju=new J({name:`gateway:status`,description:`Show gateway configuration status`,usage:`gateway [status]`,example:`gateway status`,args:[],flags:[],handler:async({sdk:e,flags:t})=>{let n=await e.gateway.status();if(t.json)return console.log(JSON.stringify({enabled:n.enabled,handler:n.handler,nginx:n.nginx,nginxConf:n.nginxConf,configsPath:n.configsPath,services:n.services})),{success:!0,message:`Gateway status retrieved`};if(console.log(``),console.log(`Gateway Status`),console.log(`==============`),console.log(``),!n.enabled)return console.log(`Status: Disabled`),console.log(``),console.log(`To enable gateway, add to ~/.denvig/config.yml:`),console.log(``),console.log(` experimental:`),console.log(` gateway:`),console.log(` enabled: true`),console.log(``),{success:!0,message:`Gateway is disabled`};let r=n.nginx.running?`Started (pid ${n.nginx.pid})`:`Stopped`;if(console.log(`Status: ${r}`),console.log(`Handler: ${n.handler}`),console.log(`Config: ${n.nginxConf}`),console.log(`Configs: ${n.configsPath}`),console.log(``),n.services.length===0)return console.log(`No services configured with http.domain`),console.log(``),console.log(`To configure a service for gateway, add http.domain:`),console.log(``),console.log(` services:`),console.log(` my-service:`),console.log(` command: node server.js`),console.log(` http:`),console.log(` port: 3000`),console.log(` domain: my-service.denvig.localhost`),console.log(``),{success:!0,message:`No gateway services configured`};console.log(`Services:`),console.log(``);for(let e of n.services){let t=[e.domain,...e.cnames],n=e.secure?e.certFound?`✓`:`✗`:`-`,r=e.secure?e.certFound?`found`:`missing`:`not enabled`,i=e.nginxConfigExists?`✓`:`✗`;console.log(` ${e.name}:`),console.log(` Domains: ${t.join(`, `)}`),console.log(` Port: ${e.port||`(not set)`}`),console.log(` Certs: ${n} ${r}`),console.log(` Nginx: ${i} ${e.nginxConfigExists?`configured`:`not generated`}`),console.log(``)}return{success:!0,message:`Gateway status retrieved`}}})})),Nu=s({gatewayCommand:()=>Pu}),Pu,Fu=o((()=>{Y(),Au(),Mu(),Pu=new J({name:`gateway`,description:`Manage nginx gateway proxy for local domains`,usage:`gateway <subcommand>`,example:`denvig gateway status`,args:[],flags:[],subcommands:{status:ju,configure:ku},defaultSubcommand:`status`,handler:()=>({success:!0})})})),Iu,Lu,Ru,zu,Bu,Vu,Hu,Uu,Wu,Gu,Ku=o((()=>{q(),Fc(),Iu=`✓`,Lu=`✗`,Ru=(e,t)=>{console.log(`${t?Iu:Lu} ${e}: ${t?`configured`:`not configured`}`)},zu=async e=>{let t=await e.check();return Ru(e.name,t),t?!1:await $(` ${e.enableLabel}`)?(await e.enable()||console.error(` Failed to configure ${e.name}`),!0):(console.log(` skipped`),!0)},Bu=async()=>{let e=await Pc(` GitHub username`);if(!e){console.log(` skipped (no username provided)`);return}let t=await vs(_s(e));t.success||console.error(` ${t.message}`)},Vu=async()=>{let e=await Pc(` Git user.name`),t=await Pc(` Git user.email`);if(!e||!t){console.log(` skipped (name and email required)`);return}await Ds(e,t)||console.error(` Failed to configure git`)},Hu=async()=>{let e=await gs();return Ru(`Dotfiles`,e),e?!1:await $(` Install dotfiles from github.com/<username>/dotfiles?`)?(await Bu(),!0):(console.log(` skipped`),!0)},Uu=async()=>{let e=await Es();return e?(console.log(`${Iu} Git config: ${e.name} <${e.email}>`),!1):(Ru(`Git config`,!1),await $(` Configure git user.name + user.email?`)?(await Vu(),!0):(console.log(` skipped`),!0))},Wu=[{name:`sudo Touch ID`,check:Vs,enable:Hs,enableLabel:`Enable sudo Touch ID?`},{name:`FileVault`,check:xs,enable:Ss,enableLabel:`Enable FileVault full disk encryption?`},{name:`Xcode Command Line Tools`,check:Gs,enable:Ks,enableLabel:`Install Xcode Command Line Tools?`},{name:`Homebrew`,check:js,enable:Ms,enableLabel:`Install Homebrew?`}],Gu=async()=>{let e=[...Wu.map(e=>()=>zu(e)),Hu,Uu];for(let[t,n]of e.entries())await n()&&t<e.length-1&&console.log(``)}})),qu,Ju=o((()=>{Y(),Ku(),qu=new J({name:`system:configure`,description:`Walk through system setup checks and enable each feature interactively`,usage:`system configure`,example:`denvig system configure`,args:[],flags:[],handler:async()=>(await Gu(),{success:!0,message:`System configuration complete`})})})),Yu,Xu=o((()=>{q(),Y(),Yu=new J({name:`system:setup`,description:`Clone a dotfiles repository to ~/.dotfiles and run setup`,usage:`system setup <url>`,example:`denvig system setup https://github.com/marcqualie/dotfiles`,args:[{name:`url`,description:`Git URL of the dotfiles repository`,required:!0,type:`string`}],flags:[],handler:async({args:e})=>{let t=await vs(String(e.url));return t.success||console.error(`Error: ${t.message}`),t}})})),Zu,Qu=o((()=>{oc(),q(),ac(),Y(),Q(),Fc(),Zu=new J({name:`system:update`,description:`Update the local system: dotfiles, brew packages, and skills`,usage:`system update`,example:`denvig system update`,args:[],flags:[],handler:async()=>{let e=m.default.join((0,p.homedir)(),`.dotfiles`);if(!await rt(e))return console.error(`Error: ${G(e)} does not exist. Run 'denvig system bootstrap <url>' first.`),{success:!1,message:`Dotfiles directory missing`};let t=[],n=async(e,n)=>{console.log(``),console.log(`${Z.bold}==> ${e}${Z.reset}`);try{let r=await n();return t.push({name:e,...r}),r.success}catch(n){let r=n instanceof Error?n.message:String(n);return console.error(`Error: ${r}`),t.push({name:e,success:!1,message:r}),!1}};await n(`Pull dotfiles (${G(e)})`,async()=>(await fi(e)&&console.warn(`Warning: ${G(e)} has uncommitted changes`),await di(e)?{success:!0}:{success:!1,message:`git pull failed`})),await n(`Run dotfiles update action`,async()=>await ps(e,[`run`,`update`])?{success:!0}:{success:!1,message:`denvig run update failed`}),await n(`Update Homebrew`,async()=>await ls()?{success:!0}:{success:!1,message:`brew update failed`});let r=await ds(),i=r?.formulae??[],a=r?.casks??[],o=i.length+a.length;if(console.log(``),o===0)console.log(`All Homebrew packages are up to date`);else{console.log(`Outdated Homebrew packages (${o}):`);for(let e of i){let t=e.installed_versions?.join(`, `)??`?`,n=e.current_version??`?`;console.log(` ${e.name}: ${t} → ${n}`)}for(let e of a){let t=e.installed_versions??`?`,n=e.current_version??`?`;console.log(` ${e.name} (cask): ${t} → ${n}`)}await $("Run `brew upgrade`?")&&await n(`Upgrade Homebrew packages`,async()=>await us()?{success:!0}:{success:!1,message:`brew upgrade failed`})}await Fs()&&await n(`Update skills`,async()=>await Is()?{success:!0}:{success:!1,message:`skills update failed`});let s=t.filter(e=>!e.success);console.log(``),console.log(`${Z.bold}Summary${Z.reset}`);for(let e of t){let t=e.success?`${Z.green}✓${Z.reset}`:`${Z.red}✗${Z.reset}`;console.log(`${t} ${e.name}`)}return s.length>0?{success:!1,message:`${s.length} of ${t.length} steps failed`}:{success:!0,message:`System update complete`}}})})),$u=s({systemCommand:()=>ed}),ed,td=o((()=>{Y(),Ju(),Xu(),Qu(),ed=new J({name:`system`,description:`Manage the local system: dotfiles, packages, and tooling`,usage:`system <subcommand>`,example:`denvig system update`,args:[],flags:[],subcommands:{setup:Yu,update:Zu,configure:qu},handler:()=>({success:!0})})}));ss(),q();async function nd(){let e=process.argv[2],t=process.argv.slice(2),n=(0,u.parseArgs)({args:t,options:{version:{type:`boolean`,short:`v`},help:{type:`boolean`,short:`h`},project:{type:`string`}},strict:!1,allowPositionals:!0}).values,r=new as({client:`cli`,cwd:process.cwd()});n.version&&(console.log(`v${r.version()}`),process.exit(0));let i=await I(),a=typeof n.project==`string`?n.project:void 0,{project:o,slug:s}=await r.projects.detect(a),c=ce({version:r.version(),command:`denvig ${process.argv.slice(2).join(` `)}`,slug:s??void 0,path:process.cwd(),via:process.env.DENVIG_CLI_VIA});e===`outdated`&&(e=`deps`,t=[`deps`,`outdated`,...process.argv.slice(3)]),[...i.quickActions??[],...o?.activeWorktree.config?.quickActions??[]].sort().includes(e)&&(t=[`run`,...process.argv.slice(2)],e=`run`,console.log(`> Proxying to denvig run`,...process.argv.slice(2)));let{runCommand:l}=await Promise.resolve().then(()=>(ic(),nc)),{configCommand:d}=await Promise.resolve().then(()=>(fc(),lc)),{pluginsCommand:f}=await Promise.resolve().then(()=>(hc(),pc)),{versionCommand:p}=await Promise.resolve().then(()=>(vc(),gc)),{infoCommand:m}=await Promise.resolve().then(()=>(Sc(),yc)),{servicesCommand:h}=await Promise.resolve().then(()=>(nl(),el)),{internalsResourceHashCommand:g,internalsResourceIdCommand:_}=await Promise.resolve().then(()=>(ol(),rl)),{depsCommand:v}=await Promise.resolve().then(()=>(Al(),Ol)),{projectsCommand:y}=await Promise.resolve().then(()=>(Ll(),Fl)),{shellCommand:ee}=await Promise.resolve().then(()=>(Ou(),Eu)),{gatewayCommand:te}=await Promise.resolve().then(()=>(Fu(),Nu)),{certsCommand:ne}=await Promise.resolve().then(()=>(lu(),su)),{systemCommand:b}=await Promise.resolve().then(()=>(td(),$u)),x={run:l,config:d,plugins:f,version:p,info:m,services:h,deps:v,"internals:resource-hash":g,"internals:resource-id":_,projects:y,shell:ee,gateway:te,certs:ne,system:b};e||(Zs(x,r.version()),await c.finish(1,`No command provided`),process.exit(1)),n.help&&!x[e]&&(Zs(x,r.version()),await c.finish(0,`Showed help`),process.exit(0));let S=e=>{console.error(``);for(let t of e)console.error(t)};if(!x[e]){let t=`Command "${e}" not found`;console.error(`${t}.`),S(Xs(x,r.version())),await c.finish(1,t),process.exit(1)}let re=!!n.help,C=x[e],ie=1;for(;C.hasSubcommands;){let e=t[ie];if(e&&C.subcommands[e])C=C.subcommands[e],ie++;else if(e&&!e.startsWith(`-`)&&!C.acceptsExtraArgs){let t=Object.keys(C.subcommands).filter(e=>!e.startsWith(`__`)).join(`, `),n=`Unknown subcommand "${e}" for "${C.name}". Available subcommands: ${t}`;console.error(n),S(ec(C)),await c.finish(1,n),process.exit(1)}else if(C.defaultSubcommand&&!re)C=C.subcommands[C.defaultSubcommand];else break}t=[t[0],...t.slice(ie)],re&&(C.hasSubcommands?tc(C):$s(C),await c.finish(0,`Showed command help`),process.exit(0));let ae=[...Js,...C?.flags||[]],oe={help:{type:`boolean`,short:`h`},version:{type:`boolean`,short:`v`}};for(let e of ae){let t=`short`in e?e.short:void 0;oe[e.name]={type:e.type===`boolean`?`boolean`:`string`,...t?{short:t}:{}}}let se=(0,u.parseArgs)({args:t,options:oe,strict:!1,allowPositionals:!0,tokens:!0}),le={},ue=null;for(let[e,t]of(C?.args||[]).entries()){let n=se.positionals[e+1];if(n!==void 0)le[t.name]=t.type===`number`?Number(n):n;else if(t.required){ue=t.name;break}}if(ue){let e=`Missing required argument: ${ue}`;console.error(e),S(Qs(C)),await c.finish(1,e),process.exit(1)}let de=new Set(ae.map(e=>e.name)),fe={},w=null;for(let e of ae){let t=se.values[e.name];if(t!==void 0)fe[e.name]=e.type===`number`&&typeof t==`string`?Number(t):t;else if(e.defaultValue!==void 0)fe[e.name]=e.defaultValue;else if(e.required){w=e.name;break}}if(w){let e=`Missing required flag: ${w}`;console.error(e),S(Qs(C)),await c.finish(1,e),process.exit(1)}let pe=C?.args.length||0,T=[],me=0;for(let e of se.tokens??[])if(e.kind===`positional`){if(me>pe){if(!C.acceptsExtraArgs){let t=`Unexpected argument: "${e.value}"`;console.error(t),S(Qs(C)),await c.finish(1,t),process.exit(1)}T.push(e.value)}me++}else if(e.kind===`option`){if(de.has(e.name)||e.name===`help`||e.name===`version`)continue;let t=e.rawName??`--${e.name}`;if(!C.acceptsExtraArgs){let e=`Unknown flag: ${t}`;console.error(e),S(Qs(C)),await c.finish(1,e),process.exit(1)}e.value===void 0?T.push(t):e.inlineValue?T.push(`${t}=${e.value}`):T.push(t,e.value)}try{if(!o){let e=`No project provided or detected`;console.error(`${e}.`),await c.finish(1,e),process.exit(1)}let{success:e,message:t}=await C.run(r,o,le,fe,T);if(!e){let e=(t||`Command failed`).replace(/[\r\n]+/g,` `).trim();await c.finish(1,e),process.exit(1)}await c.finish(0)}catch(t){let n=(t instanceof Error?t.message:`Unknown error`).replace(/[\r\n]+/g,` `).trim();console.error(`Error executing command "${e}":`,t),await c.finish(1,n),process.exit(1)}}nd();
package/dist/sdk.cjs ADDED
@@ -0,0 +1 @@
1
+ var e=require("@denvig/sdk");Object.keys(e).forEach(function(t){t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:function(){return e[t]}})});
package/dist/sdk.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "@denvig/sdk";
package/dist/sdk.js ADDED
@@ -0,0 +1 @@
1
+ export*from"@denvig/sdk";export{};
package/package.json ADDED
@@ -0,0 +1,71 @@
1
+ {
2
+ "name": "@denvig/cli",
3
+ "version": "0.7.0-alpha.4",
4
+ "license": "MIT",
5
+ "description": "A CLI tool to consistently manage cross-discipline projects",
6
+ "type": "module",
7
+ "bin": {
8
+ "denvig": "./dist/cli.cjs"
9
+ },
10
+ "main": "./dist/sdk.cjs",
11
+ "module": "./dist/sdk.js",
12
+ "types": "./dist/sdk.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "denvig-source": "./src/sdk.ts",
16
+ "import": {
17
+ "types": "./dist/sdk.d.ts",
18
+ "default": "./dist/sdk.js"
19
+ },
20
+ "require": {
21
+ "types": "./dist/sdk.d.ts",
22
+ "default": "./dist/sdk.cjs"
23
+ }
24
+ },
25
+ "./cli": {
26
+ "denvig-source": "./src/cli.ts",
27
+ "default": "./dist/cli.cjs"
28
+ }
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "files": [
34
+ "dist/",
35
+ "LICENSE",
36
+ "README.md"
37
+ ],
38
+ "dependencies": {
39
+ "node-forge": "^1.4.0",
40
+ "semver": "^7.8.1",
41
+ "yaml": "^2.9.0",
42
+ "zod": "^4.4.3",
43
+ "@denvig/sdk": "0.7.0-alpha.4"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node-forge": "^1.3.14",
47
+ "@types/semver": "^7.7.1",
48
+ "@denvig/tsconfig": "0.7.0-alpha.4"
49
+ },
50
+ "engines": {
51
+ "node": ">=22"
52
+ },
53
+ "repository": {
54
+ "type": "git",
55
+ "url": "git+https://github.com/marcqualie/denvig.git",
56
+ "directory": "packages/cli"
57
+ },
58
+ "keywords": [
59
+ "cli",
60
+ "node",
61
+ "developer-tools",
62
+ "productivity",
63
+ "typescript"
64
+ ],
65
+ "scripts": {
66
+ "build": "rm -rf dist && rolldown -c && chmod +x dist/cli.cjs",
67
+ "check-types": "tsc --noEmit",
68
+ "test": "node --test --conditions=denvig-source --test-skip-pattern='node_modules' 'src/**/*.test.ts'",
69
+ "test:ci": "node --test --conditions=denvig-source --test-skip-pattern='node_modules' 'src/**/*.test.ts' --reporter=default"
70
+ }
71
+ }