@denvig/sdk 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.
@@ -0,0 +1,208 @@
1
+ import{n as e,r as t,t as n}from"./safeReadFile-Z2PHqO9j.js";import{exec as r,execFile as i,execSync as a,spawn as o,spawnSync as s}from"node:child_process";import{access as c,appendFile as l,chmod as u,mkdir as d,readFile as f,readdir as p,rename as m,rm as h,stat as g,symlink as _,unlink as v,writeFile as y}from"node:fs/promises";import{homedir as b,hostname as ee}from"node:os";import te,{basename as ne,dirname as x,resolve as S}from"node:path";import{parse as C}from"yaml";import{satisfies as re}from"semver";import{promisify as ie}from"node:util";import{X509Certificate as w,createHash as ae}from"node:crypto";import{readFileSync as T,readdirSync as oe,realpathSync as se,statSync as E}from"node:fs";import{z as D}from"zod";import{createServer as ce}from"node:net";const le=()=>process.env.DENVIG_CLI_LOGS_ENABLED!==`0`,ue=()=>process.env.DENVIG_CLI_LOGS_PATH?S(process.env.DENVIG_CLI_LOGS_PATH):S(b(),`.denvig`,`logs`,`cli.jsonl`),de=async()=>{await d(S(ue(),`..`),{recursive:!0})},fe=async e=>{if(le())try{await de(),await l(ue(),`${JSON.stringify(e)}\n`,`utf-8`)}catch{}},pe=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 fe(i)}}},me=(e,t)=>{for(let[n,r]of Object.entries(t))e[n]||(e[n]=[]),e[n].push(...r);return e},he=[`pnpm-lock.yaml:`,`yarn.lock:`,`Gemfile.lock:`,`uv.lock:`,`deno.lock:`],O=e=>{for(let t of he)if(e.startsWith(t)){let n=e.slice(t.length).match(/^((?:@[^@/]+\/)?[^@]+)@([^(@]+)/);if(n)return{name:n[1],version:n[2]}}return null},ge=e=>he.some(t=>e.startsWith(t)),_e=(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=O(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=O(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))},ve=e=>e.endsWith(`#dependencies`),ye=e=>e.endsWith(`#devDependencies`),be=(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(!ge(e.source)){let n=ye(e.source);if(ve(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=O(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=O(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},xe=(e,t,n,r)=>{if(!ge(n))return{name:e,version:t,children:[]};let i=[{name:e,version:t}],a=n,o=0;for(;o<50;){let e=O(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||!ge(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},Se=async()=>{let e=`${b()}/.cache/denvig/dependencies/npm`;return await d(e,{recursive:!0}),e},Ce=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},we=async e=>{let t=Ce(e);return`${await Se()}/${t}.json`},Te=async e=>{try{let t=await g(e);return Date.now()-t.mtimeMs<36e5}catch{return!1}},Ee=async e=>{let t=await we(e);if(!await Te(t))return null;try{let e=await f(t,`utf-8`),n=JSON.parse(e);return n.versionDates?n:null}catch{return null}},De=async(e,t)=>{try{await y(await we(e),JSON.stringify(t),`utf-8`)}catch{}},Oe=async(e,t=!1)=>{if(!t){let t=await Ee(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 De(e,o),o}catch{return null}},k=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},A=(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},ke=(e,t)=>{let n=k(e);if(!n||n.prerelease)return!1;if(t.startsWith(`^`)){let r=k(t.slice(1));return r?r.major===0?n.major===0&&n.minor===r.minor&&n.patch>=r.patch:n.major===r.major&&A(e,t.slice(1))>=0:!1}if(t.startsWith(`~`)){let e=k(t.slice(1));return e?n.major===e.major&&n.minor===e.minor&&n.patch>=e.patch:!1}if(t.startsWith(`>=`))return A(e,t.slice(2))>=0;if(t.startsWith(`>`)&&!t.startsWith(`>=`))return A(e,t.slice(1))>0;let r=k(t);return r?n.major===r.major&&n.minor===r.minor&&n.patch===r.patch:!1},Ae=(e,t)=>{let n=e.filter(e=>ke(e,t)).sort(A);return n.length>0?n[n.length-1]:null},je=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}},Me=async(e,t={})=>{let n=t.cache??!0,r=t.depth??0,i=[],a=_e(e,r).map(async e=>{let t=je(e);if(!t)return;let r=await Oe(e.name,!n);if(!r)return;let a=Ae(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},Ne=async()=>{let e=`${b()}/.cache/denvig/dependencies/jsr`;return await d(e,{recursive:!0}),e},Pe=async e=>{let t=Ce(e);return`${await Ne()}/${t}.json`},Fe=async e=>{try{let t=await g(e);return Date.now()-t.mtimeMs<36e5}catch{return!1}},Ie=async e=>{let t=await Pe(e);if(!await Fe(t))return null;try{let e=await f(t,`utf-8`);return JSON.parse(e)}catch{return null}},Le=async(e,t)=>{try{await y(await Pe(e),JSON.stringify(t),`utf-8`)}catch{}},Re=async(e,t=!1)=>{if(!t){let t=await Ie(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 Le(e,o),o}catch{return null}},ze=async(e,t={})=>{let n=t.cache??!0,r=t.depth??0,i=[],a=_e(e,r).map(async e=>{let t=je(e);if(!t)return;let r=await Re(e.name,!n);if(!r)return;let a=t.specifier===`*`?r.latest:Ae(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},j=async e=>{let t=`${e.path}/package.json`;try{let e=await f(t,`utf-8`);return JSON.parse(e)}catch{return null}},M=e=>e,Be=new Map,Ve=e=>{let t=e.match(/^(npm|jsr):(.+)@([^@]+)$/);return t?{ecosystem:t[1],name:t[2],versionRange:t[3]}:null},He=(e,t)=>{for(let[n,r]of Object.entries(t))if(n===e||n.startsWith(`${e}@`))return{specKey:n,resolved:r};return null},Ue=(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},We=async e=>{try{let t=await f(e,`utf-8`);return JSON.parse(t)}catch{return{}}},Ge=M({name:`deno`,actions:async t=>{let n=t.rootFiles;if(!(n.includes(`deno.json`)||n.includes(`deno.jsonc`)))return{};let r=(await j(t))?.scripts||{},i={...Object.entries(r).map(([e,t])=>[e,`deno ${t}`]).reduce((e,[t,n])=>(e[t]=[n],e),{}),install:[`deno install`],outdated:[`deno outdated`]},a=await e(`${t.path}/deno.json`)?`${t.path}/deno.json`:await e(`${t.path}/deno.jsonc`)?`${t.path}/deno.jsonc`:null,o=(a?await We(a):{}).tasks||{};return i=me(i,{test:[o?.test?`deno task test`:`deno test`],lint:[o?.lint?`deno task lint`:`deno lint`],"check-types":[o?.checkTypes?`deno task check-types`:`deno check`],...Object.entries(o).reduce((e,[t,n])=>(e[t]=[n.startsWith(`deno`)?n:`deno task ${t}`],e),{}),install:[`deno install`],outdated:[`deno outdated`]}),i},dependencies:async t=>{if(!await e(`${t.path}/deno.lock`))return[];let n=Be.get(t.path);if(n)return n;let r=new Map,i=new Set,a=(e,t,n,i,a,o)=>{let s=r.get(e);s?s.versions.push({resolved:i,specifier:o,source:a}):r.set(e,{id:e,name:t,ecosystem:n,versions:[{resolved:i,specifier:o,source:a}]})},o=await f(`${t.path}/deno.lock`,`utf-8`),s=JSON.parse(o),c=s.workspace?.dependencies||[];for(let e of c){let t=s.specifiers[e];if(!t)continue;let n=Ve(e);if(!n)continue;let r=`${n.ecosystem}:${n.name}`;i.add(r),a(r,n.name,n.ecosystem,t,`.#dependencies`,n.versionRange)}if(s.jsr){for(let[e,t]of Object.entries(s.jsr))if(t.dependencies)for(let n of t.dependencies){let t=He(n,s.specifiers);if(!t)continue;let r=Ve(t.specKey);if(!r)continue;let o=`${r.ecosystem}:${r.name}`;i.has(o)||a(o,r.name,r.ecosystem,t.resolved,`deno.lock:${e}`,t.resolved)}}if(s.npm)for(let[e,t]of Object.entries(s.npm)){let n=[...t.dependencies||[],...t.optionalDependencies||[]];if(n.length!==0)for(let t of n){let n=`npm:${t}`;if(i.has(n))continue;let r=Ue(t,s.npm);r&&a(n,t,`npm`,r,`deno.lock:${e}`,r)}}let l=Array.from(r.values()).sort((e,t)=>e.name.localeCompare(t.name));return Be.set(t.path,l),l},outdatedDependencies:async(t,n)=>{if(!await e(`${t.path}/deno.lock`))return[];let r=await Ge.dependencies?.(t);if(!r)return[];let i=r.filter(e=>e.ecosystem===`npm`),a=r.filter(e=>e.ecosystem===`jsr`),[o,s]=await Promise.all([Me(i,n),ze(a,n)]);return[...o,...s]}}),Ke=M({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 j(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`]}}}),qe=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}},Je=async(e,t,n)=>{await y(e,t,`utf-8`),await new Promise((t,r)=>{o(n,[`install`],{cwd:x(e),stdio:`inherit`,shell:!0}).on(`close`,e=>{e===0?t():r(Error(`${n} install failed with code ${e}`))})})},Ye=(e,t)=>{let n=`0.0.0`;for(let r of t)re(r,e)&&(n=r);return n===`0.0.0`?t[t.length-1]:n},Xe=e=>{let t=Object.keys(e),n=Object.values(e).flat(),r={};for(let e of n){let n=Ye(e,t);r[n]||(r[n]=[]),r[n].push(e)}return r},Ze=e=>{let t=e.match(/^([^(]+)/);return t?t[1]:e},Qe=e=>{let t={},n=C(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=Ze(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=Xe(n.versions);return{dependencies:t}},$e=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),et=e=>{let t=e.match(/^([^(]+)/);return t?t[1]:e},tt=(e,t)=>{for(let[n,r]of Object.entries(t))if(r.includes(e))return n;return null},nt=(e,t)=>{let n=$e(t),r=RegExp(`^ '?${n}'?:.*\\n(?: .*\\n)*\\n?`,`gm`);return e.replace(r,``)},rt=(e,t,n)=>{let r=C(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=et(e);if(t[r]?.includes(s)){let t=n[r];if(t){let n=tt(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: )${$e(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=nt(i,n),i=nt(i,n)}return i},it=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=async e=>{try{return C(await f(`${e}/pnpm-workspace.yaml`,`utf-8`))}catch{return null}},ot=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??{}}},st=(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},ct=e=>e==="default"?`pnpm-workspace.yaml$catalog`:`pnpm-workspace.yaml$catalogs.${e}`,lt=async e=>{try{let t=C(await f(`${e}/pnpm-workspace.yaml`,`utf-8`));if(t?.minimumReleaseAge==null)return null;let n=it(String(t.minimumReleaseAge));return n===null?null:{minimumReleaseAgeMs:n,exclude:t.minimumReleaseAgeExclude??[]}}catch{return null}},ut=new Map,dt=e=>{let t=e.indexOf(`(`);return t===-1?e:e.slice(0,t)},ft=e=>{if(/^\d/.test(e))return null;let t=e.match(/^((?:@[^@/]+\/)?[^@]+)@(.+)$/);return t?{name:t[1],version:t[2]}:null},pt=M({name:`pnpm`,actions:async e=>{if(!e.rootFiles.includes(`pnpm-lock.yaml`))return{};let t=(await j(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 t=>{if(!await e(`${t.path}/pnpm-lock.yaml`))return[];let n=ut.get(t.path);if(n)return n;let r=new Map,i=(e,t,n,i,a,o)=>{let s=r.get(e);s?s.versions.push({resolved:i,specifier:o,source:a}):r.set(e,{id:e,name:t,ecosystem:n,versions:[{resolved:i,specifier:o,source:a}]})};r.set(`npm:pnpm`,{id:`npm:pnpm`,name:`pnpm`,ecosystem:`system`,versions:[]});let a=C(await f(`${t.path}/pnpm-lock.yaml`,`utf-8`)),o=await ot(t.path),s=new Set,c=(e,t,n)=>{let r=`npm:${e}`,a=dt(t.version),c=st(o,e,t.specifier);if(i(r,e,`npm`,a,n,t.specifier),c){let t=ct(c.catalogName),n=`${r}@${t}`;s.has(n)||(s.add(n),i(r,e,`npm`,a,t,c.specifier))}};if(a?.importers)for(let[e,t]of Object.entries(a.importers)){let n=e===`.`?`.`:e;if(t.dependencies)for(let[e,r]of Object.entries(t.dependencies))r?.specifier&&r?.version&&c(e,r,`${n}#dependencies`);if(t.devDependencies)for(let[e,r]of Object.entries(t.devDependencies))r?.specifier&&r?.version&&c(e,r,`${n}#devDependencies`)}if(a?.snapshots)for(let[e,t]of Object.entries(a.snapshots)){let n={...t.dependencies};for(let[t,r]of Object.entries(n)){let n=ft(r),a=n?n.name:t,o=dt(n?n.version:r),s=`pnpm-lock.yaml:${e}`;i(`npm:${a}`,a,`npm`,o,s,o)}}let l=Array.from(r.values()).sort((e,t)=>e.name.localeCompare(t.name));return ut.set(t.path,l),l},outdatedDependencies:async(t,n)=>{if(!await e(`${t.path}/pnpm-lock.yaml`))return[];let r=await pt.dependencies?.(t);return r?Me(r,n):[]},deduplicateDependencies:async(t,n)=>{let r=`${t.path}/pnpm-lock.yaml`;if(!await e(r))return null;let i=await f(r,`utf-8`),a=Qe(i),o=qe(a),s=n?.dryRun??!1,c=!1;if(!s&&Object.keys(o.removals).length>0){let e={};for(let[t,n]of Object.entries(a.dependencies))o.removals[t]&&n.optimisedVersions&&(e[t]=n.optimisedVersions);await Je(r,rt(i,o.removals,e),`pnpm`),c=!0}return{ecosystem:`pnpm-lock.yaml`,...o,applied:c}}}),mt=async()=>{let e=`${b()}/.cache/denvig/dependencies/rubygems`;return await d(e,{recursive:!0}),e},ht=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},gt=async e=>{let t=ht(e);return`${await mt()}/${t}.json`},_t=async e=>{try{let t=await g(e);return Date.now()-t.mtimeMs<36e5}catch{return!1}},vt=async e=>{let t=await gt(e);if(!await _t(t))return null;try{let e=await f(t,`utf-8`),n=JSON.parse(e);return n.versionDates?n:null}catch{return null}},yt=async(e,t)=>{try{await y(await gt(e),JSON.stringify(t),`utf-8`)}catch{}},bt=async(e,t=!1)=>{if(!t){let t=await vt(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 yt(e,o),o}catch{return null}},N=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},P=(e,t)=>{let n=N(e),r=N(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},xt=(e,t)=>{let n=N(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=N(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&&P(e,`${i.major}.${i.minor}.0`)>=0:!1}if(r.startsWith(`>=`))return P(e,r.slice(2).trim())>=0;if(r.startsWith(`>`)&&!r.startsWith(`>=`))return P(e,r.slice(1).trim())>0;if(r.startsWith(`<=`))return P(e,r.slice(2).trim())<=0;if(r.startsWith(`<`)&&!r.startsWith(`<=`))return P(e,r.slice(1).trim())<0;if(r.startsWith(`=`)){let e=N(r.slice(1).trim());return e?n.major===e.major&&n.minor===e.minor&&n.patch===e.patch:!1}let i=N(r);return i?n.major===i.major&&n.minor===i.minor&&n.patch===i.patch:!1},St=(e,t)=>{let n=e.filter(e=>xt(e,t)).sort(P);return n.length>0?n[n.length-1]:null},Ct=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}},wt=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=Ct(e);if(!t)return;let i=await bt(e.name,!n);if(!i)return;let a=St(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},Tt=e=>{let t=[],n=e.split(`
2
+ `),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},Et=e=>{let t={},n={},r=e.split(`
3
+ `),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}},Dt=async e=>{let t=`${e.path}/Gemfile`,n=`${e.path}/Gemfile.lock`,r;try{r=await f(t,`utf-8`)}catch{return[]}let i=new Map,a=new Set,o=Tt(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 f(n,`utf-8`)}catch{}if(c){let e=Et(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))},Ot=new Map,kt=M({name:`ruby`,actions:async t=>{let n=t.rootFiles,r=n.includes(`Gemfile`),i=n.includes(`Rakefile`),a=n.includes(`config.ru`),o=await e(`${t.path}/config/application.rb`);if(!(r||i))return{};let s={install:[`bundle install`],update:[`bundle update`],outdated:[`bundle outdated`]};return o&&(s.dev=[`bundle exec rails server`],s.repl=[`bundle exec rails console`]),a&&!o&&(s.dev=[`bundle exec rackup`]),s},dependencies:async e=>{if(!e.rootFiles.includes(`Gemfile`))return[];let t=Ot.get(e.path);if(t)return t;let n=await Dt(e);return Ot.set(e.path,n),n},outdatedDependencies:async(e,t)=>{if(!e.rootFiles.includes(`Gemfile`))return[];let n=await kt.dependencies?.(e);return n?wt(n,t):[]}}),At=async()=>{let e=`${b()}/.cache/denvig/dependencies/pypi`;return await d(e,{recursive:!0}),e},jt=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},Mt=async e=>{let t=jt(e);return`${await At()}/${t}.json`},Nt=async e=>{try{let t=await g(e);return Date.now()-t.mtimeMs<36e5}catch{return!1}},Pt=async e=>{let t=await Mt(e);if(!await Nt(t))return null;try{let e=await f(t,`utf-8`),n=JSON.parse(e);return n.versionDates?n:null}catch{return null}},Ft=async(e,t)=>{try{await y(await Mt(e),JSON.stringify(t),`utf-8`)}catch{}},It=async(e,t=!1)=>{let n=e.toLowerCase().replace(/_/g,`-`);if(!t){let e=await Pt(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 Ft(n,o),o}catch{return null}},F=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},I=(e,t)=>{let n=F(e),r=F(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},Lt=e=>/[a-zA-Z]/.test(e),Rt=(e,t)=>{let n=F(e);if(!n||Lt(e))return!1;if(t===`*`)return!0;if(t.startsWith(`~=`)){let e=t.slice(2).trim(),r=F(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 I(e,t.slice(2).trim())>=0;if(t.startsWith(`>`)&&!t.startsWith(`>=`))return I(e,t.slice(1).trim())>0;if(t.startsWith(`<=`))return I(e,t.slice(2).trim())<=0;if(t.startsWith(`<`)&&!t.startsWith(`<=`))return I(e,t.slice(1).trim())<0;if(t.startsWith(`!=`))return I(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=F(r);return i?n.major===i.major&&n.minor===i.minor&&n.patch===i.patch:!1}let r=F(t);return r?n.major===r.major&&n.minor===r.minor&&n.patch===r.patch:!1},zt=(e,t)=>{let n=e.filter(e=>Rt(e,t)).sort(I);return n.length>0?n[n.length-1]:null},Bt=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}},Vt=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=Bt(e);if(!t)return;let i=await It(e.name,!n);if(!i)return;let a=zt(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},Ht=e=>{let t=e.trim();return t.startsWith(`"`)&&t.endsWith(`"`)||t.startsWith(`'`)&&t.endsWith(`'`)?t.slice(1,-1):t},Ut=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):Ht(t)},Wt=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]=Wt(i):i.startsWith(`[`)?t[r]=L(i):t[r]=Ut(i)}return t},L=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(Wt(n)):n.startsWith(`[`)?t.push(L(n)):t.push(Ut(n))}return t},Gt=(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},R=(e,t)=>{let n=e;for(let e of t)(!(e in n)||typeof n[e]!=`object`)&&(n[e]={}),n=n[e];return n},Kt=e=>{let t={},n=e.split(`
4
+ `),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=L(o.slice(0,n+1));a?a[s]=e:Gt(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=R(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=R(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(`.`),R(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(`{`)?Wt(f):f.startsWith(`[`)?L(f):Ut(f),a?a[d]=p:Gt(t,[...r,d],p)}if(a&&i){let e=R(t,i.slice(0,-1)),n=i[i.length-1];Array.isArray(e[n])||(e[n]=[]),e[n].push(a)}return t},z=e=>e.toLowerCase().replace(/_/g,`-`),qt=e=>{let t=e.match(/^([a-zA-Z0-9_-]+(?:\[[^\]]+\])?)(.*)$/);return t?{name:t[1].replace(/\[.*\]$/,``),specifier:t[2].trim()||`*`}:{name:e,specifier:`*`}},Jt=e=>{let t=[];try{let n=Kt(e);if(n.project?.dependencies)for(let e of n.project.dependencies){let{name:n,specifier:r}=qt(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}=qt(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}=qt(n);t.push({name:e,specifier:r,group:`devDependencies`})}}catch{}return t},Yt=e=>{let t={},n=null;try{let r=Kt(e);if(r.package)for(let e of r.package){let r=z(e.name);e.source?.virtual&&(n=r);let i=e.dependencies?.map(e=>z(e.name))||[];t[r]={name:e.name,version:e.version,dependencies:i}}}catch{}return{packages:t,projectName:n}},Xt=async e=>{let t=`${e.path}/pyproject.toml`,n=`${e.path}/uv.lock`,r;try{r=await f(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=Jt(r);for(let e of s)a.add(z(e.name));let c=null;try{c=await f(n,`utf-8`)}catch{}if(c){let e=Yt(c);for(let t of s){let n=z(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:${z(e.name)}`,e.name,`pypi`,e.specifier,`.#${e.group}`,e.specifier);return Array.from(i.values()).sort((e,t)=>e.name.localeCompare(t.name))},Zt=new Map,Qt=M({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=Zt.get(e.path);if(r)return r;let i=await Xt(e);return Zt.set(e.path,i),i},outdatedDependencies:async(e,t)=>{if(!e.rootFiles.includes(`pyproject.toml`))return[];let n=await Qt.dependencies?.(e);return n?Vt(n,t):[]}}),$t=e=>{let t=e.split(`
5
+
6
+ `),n={};for(let e of t){let t=e.split(`
7
+ `);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}},en=e=>{let t={},n=$t(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=Xe(n.versions);return{dependencies:t}},tn=(e,t)=>{let n=[],r=e.split(`
8
+
9
+ `);for(let e of r){let r=e.split(`
10
+ `);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(`
11
+
12
+ `)},nn=e=>{let t=e.split(`
13
+
14
+ `),n={};for(let e of t){let t=e.split(`
15
+ `);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}},rn=e=>{let t={},n=nn(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}},an=new Map;function on(e){return e.includes(`__metadata:`)}function sn(e){let t=e.match(/^(.+)@npm:/);if(t)return t[1];let n=e.lastIndexOf(`@`);return n>0?e.slice(0,n):e}const cn=M({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 j(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 t=>{let n=`${t.path}/yarn.lock`,r=`${t.path}/package.json`;if(!await e(n)||!await e(r))return[];let i=an.get(t.path);if(i)return i;let a=new Map,o=new Set,s=(e,t,n,r,i,o)=>{let s=a.get(e);s?s.versions.push({resolved:r,specifier:o,source:i}):a.set(e,{id:e,name:t,ecosystem:n,versions:[{resolved:r,specifier:o,source:i}]})};a.set(`npm:yarn`,{id:`npm:yarn`,name:`yarn`,ecosystem:`system`,versions:[]});let c=await f(n,`utf-8`),l=on(c),u=new Map,d=new Map,p=null;if(l){let e=C(c);for(let[t,n]of Object.entries(e)){if(t===`__metadata`||!n?.version||typeof n.version!=`string`)continue;let e=sn(t),r=n;u.has(e)||u.set(e,new Map);let i=t.match(/@npm:(.+)$/);i&&u.get(e)?.set(i[1],n.version),r.dependencies&&d.set(`${e}@${r.version}`,r.dependencies)}}else{p=rn(c);for(let[e,t]of Object.entries(p.dependencies)){u.has(e)||u.set(e,new Map);for(let[n,r]of Object.entries(t.versions)){let t=r[`yarn.lock`];t&&u.get(e)?.set(t,n)}}}let m=[r],h=await t.findFilesByName(`package.json`);m.push(...h);for(let e of m)try{let n=await f(e,`utf-8`),i=JSON.parse(n),a=`.`;e!==r&&(a=e.replace(`${t.path}/`,``).replace(`/package.json`,``));let c=(e,t)=>{if(e)for(let[n,r]of Object.entries(e)){o.add(n);let e=u.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)}}s(`npm:${n}`,n,`npm`,i,`${a}#${t}`,r)}};c(i.dependencies,`dependencies`),c(i.devDependencies,`devDependencies`)}catch{}if(l){for(let[e,t]of d.entries())for(let[n,r]of Object.entries(t))if(!o.has(n)){let t=u.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}`;s(`npm:${n}`,n,`npm`,i,a,r)}}else if(p){for(let[e,t]of Object.entries(p.dependencies))if(!o.has(e))for(let[n,r]of Object.entries(t.versions))for(let[t,i]of Object.entries(r))t.startsWith(`yarn.lock:`)&&s(`npm:${e}`,e,`npm`,n,t,i)}let g=Array.from(a.values()).sort((e,t)=>e.name.localeCompare(t.name));return an.set(t.path,g),g},outdatedDependencies:async(t,n)=>{if(!await e(`${t.path}/yarn.lock`))return[];let r=await cn.dependencies?.(t);return r?Me(r,n):[]},deduplicateDependencies:async(t,n)=>{let r=`${t.path}/yarn.lock`;if(!await e(r))return null;let i=await f(r,`utf-8`),a=qe(en(i)),o=n?.dryRun??!1,s=!1;return!o&&Object.keys(a.removals).length>0&&(await Je(r,tn(i,a.removals),`yarn`),s=!0),{ecosystem:`yarn.lock`,...a,applied:s}}});var B={deno:Ge,npm:Ke,pnpm:pt,ruby:kt,uv:Qt,yarn:cn};const V=ie(r);function H(){return`gui/${process.getuid?.()??501}`}async function ln(e){try{let{stdout:t,stderr:n}=await V(`launchctl bootstrap ${H()} "${e}"`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function un(e){try{let{stdout:t,stderr:n}=await V(`launchctl bootout ${H()}/${e}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function dn(e){try{let{stdout:t,stderr:n}=await V(`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 fn(e){try{let{stdout:t,stderr:n}=await V(`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 pn(e){try{let{stdout:t,stderr:n}=await V(`launchctl enable ${H()}/${e}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function mn(e){try{let{stdout:t,stderr:n}=await V(`launchctl disable ${H()}/${e}`);return{success:!0,output:t||n}}catch(e){let t=e;return{success:!1,output:t.stderr||t.message||`Unknown error`}}}async function hn(e){try{let{stdout:t}=await V(`launchctl print ${H()}/${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 gn(e){try{let{stdout:t}=await V(`launchctl list`),n=t.trim().split(`
16
+ `).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 U={bootstrap:ln,bootout:un,enable:pn,disable:mn,start:dn,stop:fn,print:hn,list:gn,getUserDomain:H};let _n;const W=async()=>(_n||=(await import(`node-forge`)).default,_n),vn=process.env.HOME||``,yn=()=>S(`${vn}/.denvig/ca`),G=()=>S(`${vn}/.denvig/certs`),bn=()=>S(yn(),`rootCA-key.pem`),K=()=>S(yn(),`rootCA.pem`),xn=e=>{let t=e.replace(/^\*/,`_wildcard`);return S(G(),t)},Sn=async()=>{let e=await W(),[t,n]=await Promise.all([f(K(),`utf-8`),f(bn(),`utf-8`)]);return{cert:e.pki.certificateFromPem(t),key:e.pki.privateKeyFromPem(n)}},Cn=async()=>{let e=await W(),t=e.pki.rsa.generateKeyPair(2048),n=e.pki.createCertificate();n.publicKey=t.publicKey,n.serialNumber=await In();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)}},wn=async(e,t,n)=>{let r=await W(),i=r.pki.rsa.generateKeyPair(2048),a=r.pki.createCertificate();a.publicKey=i.publicKey,a.serialNumber=await In();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}},Tn=e=>{a(`sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${e}`,{stdio:`inherit`})},En=e=>{a(`sudo security remove-trusted-cert -d ${e}`,{stdio:`inherit`})},q=e=>{let t=e.match(/-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/);return t?t[0]:e},Dn=e=>{let t=new w(q(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},On=e=>{let t=new w(q(e));return new Date(t.validTo)},kn=async(e,t)=>{await d(yn(),{recursive:!0}),await Promise.all([y(bn(),t,{mode:384}),y(K(),e)])},An=async(e,t,n)=>{let r=xn(e);return await d(r,{recursive:!0}),await Promise.all([y(S(r,`privkey.pem`),t,{mode:384}),y(S(r,`fullchain.pem`),n)]),r},jn=async()=>{let[t,n]=await Promise.all([e(K()),e(bn())]);return t&&n},Mn=async()=>{let t=K();return await e(t)?s(`security`,[`verify-cert`,`-c`,t],{stdio:`pipe`}).status===0:!1},Nn=(e,t)=>{try{let n=new w(q(e)),r=new w(q(t));return n.checkIssued(r)&&n.verify(r.publicKey)}catch{return!1}},Pn=e=>{try{let t=new w(q(e));return t.issuer.includes(`CN=Denvig Local CA`)&&t.issuer.includes(`O=denvig.com`)}catch{return!1}},Fn=e=>{try{let t=new w(q(e)).issuer.match(/CN=([^,\n]+)/);return t?t[1]:null}catch{return null}},In=async()=>{let e=await W();return e.util.bytesToHex(e.random.getBytesSync(16))},Ln=e=>{let t=S(e,`fullchain.pem`),n=S(e,`cert.pem`);try{return E(t),t}catch{}try{return E(n),n}catch{}return null},Rn=(e,t=new Date)=>{let n=G(),r;try{r=oe(n).filter(e=>{try{return E(S(n,e)).isDirectory()}catch{return!1}})}catch{return 0}let i=t.getTime()+e,a=0;for(let e of r){let t=Ln(S(n,e));if(t)try{On(T(t,`utf-8`)).getTime()<=i&&a++}catch{}}return a};function zn(e,t){return!!(e===t||t.startsWith(`*.`)&&e.endsWith(t.slice(1))&&!e.slice(0,-t.length+1).includes(`.`))}async function Bn(t){let n=G();if(!await e(n))return null;let r;try{r=(await p(n,{withFileTypes:!0})).filter(e=>e.isDirectory()).map(e=>e.name)}catch{return null}for(let i of r){let r=S(n,i,`fullchain.pem`);if(await e(r))try{if(Dn(await f(r,`utf-8`)).some(e=>zn(t,e)))return S(n,i)}catch{}}return null}function Vn(e){let t=e.split(`.`);return t.length<=2?e:t.slice(1).join(`.`)}function Hn(e){let t=new Map;for(let n of e){let e=Vn(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 Un(e){let t=new Map,n=[];for(let r of e){let e=await Bn(r);e?t.set(r,e):n.push(r)}if(n.length===0||!await jn())return t;let{cert:r,key:i}=await Sn(),a=Hn(n);for(let[e,n]of a){let{privkey:a,fullchain:o}=await wn(e,r,i),s=await An(e,a,o);for(let e of n)t.set(e,s)}return t}async function Wn(t){let n=S(t,`fullchain.pem`),r=S(t,`privkey.pem`),[i,a]=await Promise.all([e(n),e(r)]);return i&&a?{sslCertPath:n,sslKeyPath:r}:null}const Gn=[`build`,`check-types`,`dev`,`install`,`lint`,`outdated`,`test`],Kn=D.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`),qn=D.object({cwd:D.string().optional().describe(`Working directory for the service (relative to project root)`),command:D.string().describe(`Shell command to execute`),http:D.object({port:D.number().optional().describe(`Port number the service listens on`),domain:D.string().optional().describe(`Domain to use for the service URL`),cnames:D.array(D.string()).optional().describe(`Additional hosts that can be used via gateway`),secure:D.boolean().optional().describe(`Use HTTPS instead of HTTP`)}).optional().describe(`HTTP configuration for the service URL`),envFiles:D.array(D.string()).optional().describe(`Paths to .env files (relative to service cwd)`),env:D.record(D.string(),D.string()).optional().describe(`Environment variables`),keepAlive:D.boolean().optional().describe(`Restart service if it exits`),startOnBoot:D.boolean().optional().describe(`Start service automatically when system boots`)}),Jn=D.record(Kn,qn).optional().describe(`Services that can be managed`),Yn=D.object({projectPaths:D.array(D.string()).optional().default([`~/src/*/*`,`~/.dotfiles`]).describe(`Paths or patterns where projects are located`),quickActions:D.array(D.string()).default(Gn).optional().describe(`Quick actions that are available for all projects`),services:Jn.describe(`Global services that can be managed from any directory`),experimental:D.object({gateway:D.object({enabled:D.boolean(),handler:D.enum([`nginx`]).default(`nginx`),configsPath:D.string().default(`/opt/homebrew/etc/nginx/servers`)}).optional()}).optional()}),Xn=D.object({name:D.string().optional().describe(`Display name for the project`),actions:D.record(D.string().describe(`Name of the action`),D.object({command:D.string().describe(`Shell command to run for the action`)})).optional().describe(`Actions that can be run against the project`),quickActions:D.array(D.string()).optional().describe(`Actions that are available on the CLI root for quick access`),services:Jn}),Zn=S(`${process.env.HOME}/.denvig/config.yml`),Qn={projectPaths:[`~/src/*/*`,`~/.dotfiles`],quickActions:void 0},$n=e=>e.startsWith(`~/`)?`${process.env.HOME}${e.slice(1)}`:e,er=()=>{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},tr=(e,t)=>{let n=[],r={};if(e)try{let i=C(e)||{};r={...r,...i},n.push(t)}catch(e){console.error(`Error parsing global config at ${t}:`,e),process.exit(1)}let i=er();return r={...r,...i},{...Yn.parse({...Qn,...r}),$sources:n}},nr=()=>{let e=process.env.DENVIG_GLOBAL_CONFIG_PATH;return e?S(e):Zn},J=async()=>{let e=nr();return tr(await t(e),e)},rr=async e=>{let n=`${e}/.denvig.yml`,r=await t(n);if(r)try{return{...Xn.parse(C(r)),$sources:[n]}}catch{}return{$sources:[]}},ir=(e,t,n={})=>new Promise(r=>{let i=o(e,t,{cwd:n.cwd,stdio:n.stdio??`inherit`});i.on(`close`,e=>r(e===0)),i.on(`error`,()=>r(!1))}),ar=ie(i),or=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},sr=async e=>{let t=te.join(e,`.git`,`config`);try{let e=await f(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=or(n[1]);if(e)return e}}return null}catch{return null}},cr=(e,t)=>ir(`git`,[`clone`,e,t]),lr=e=>ir(`git`,[`pull`],{cwd:e}),ur=async e=>{try{let{stdout:t}=await ar(`git`,[`status`,`--porcelain`],{cwd:e});return t.trim().length>0}catch{return!1}},dr=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},fr=e=>{let t=e?.match(/^github\.com\/(.+\/.+)$/);return t?t[1]:null},pr=e=>{let t=S(e);for(;;){let e=S(t,`.git`);try{return E(e).isFile()?t:null}catch{}let n=S(t,`..`);if(n===t)return null;t=n}},mr=e=>{let t=hr(S(e));if(!t)return[];let n=`${t.primaryGitDir}/worktrees`,r;try{r=oe(n,{withFileTypes:!0})}catch{return[]}let i=[];for(let e of r){if(!e.isDirectory())continue;let t=`${n}/${e.name}`,r=gr(t);if(!r)continue;let a;try{a=T(`${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))},hr=e=>{let t=S(e,`.git`),n;try{n=E(t)}catch{return null}let r,i;if(n.isFile()){let e;try{e=T(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=gr(o);if(!s)return null;i={primaryPath:a,branch:s}}else if(n.isDirectory()){let n;try{n=se(e)}catch{n=e}r=t,i={primaryPath:n,branch:`main`}}else return null;return{primaryGitDir:r,remotes:_r(`${r}/config`),worktree:i}},gr=e=>{try{let t=T(`${e}/HEAD`,`utf-8`).trim().match(/^ref:\s*refs\/heads\/(.+)$/);return t?t[1]:null}catch{return null}},_r=e=>{let t={},n;try{n=T(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},vr=e=>{let t=[],n=S(e),r=hr(n),i=r?.remotes.origin??null,a=i?dr(i):null,o=r?.remotes.github??null,s=fr(a)??fr(o?dr(o):null);s&&t.push(`github:${s}`),a&&r?.worktree&&t.push(`git:${a}+${r.worktree.branch}`),t.push(`local:${n}`);let c=ae(`sha1`).update(t.join(`
17
+ `)).digest(`hex`);return t.push(`id:${c}`),t},yr=e=>{let t=vr(e);return t.find(e=>e.startsWith(`github:`))||t.find(e=>e.startsWith(`local:`))},br=e=>vr(e).find(e=>e.startsWith(`id:`)).slice(3),xr=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(B)){let n=await r.actions(e);t=me(t,n)}return t},Sr=D.object({resolved:D.string().describe(`The resolved version of the dependency`),specifier:D.string().describe(`The version constraint/specifier used`),source:D.string().describe(`The source file/path of the dependency`),wanted:D.string().describe(`The wanted version based on semver rules`).optional(),latest:D.string().describe(`The latest available version of the dependency`).optional()});D.object({id:D.string().describe(`Unique identifier for the ecosystem / dependency`),name:D.string().describe(`Name of the dependency`),versions:D.array(Sr).describe(`Map of resolved versions to sources. Each source maps a package path to its version specifier.`),ecosystem:D.string().describe(`Ecosystem of the dependency (e.g., npm, rubygems, pip)`)}).extend({wanted:D.string().describe(`Latest version compatible with the specifier (semver)`),latest:D.string().describe(`Absolute latest version available`),specifier:D.string().describe(`The version specifier from package manifest`),isDevDependency:D.boolean().describe(`Whether this is a dev dependency`),currentDate:D.string().optional().describe(`ISO date when the current version was published`),wantedDate:D.string().optional().describe(`ISO date when the wanted version was published`),latestDate:D.string().optional().describe(`ISO date when the latest version was published`)});const Cr=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())},wr=async e=>Cr((await Promise.all(Object.values(B).map(t=>t.dependencies?t.dependencies(e):Promise.resolve([])))).flat());var Tr=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=vr(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([rr(t),p(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 wr(this)}async outdatedDependencies(e){return(await Promise.all(Object.values(B).map(t=>t.outdatedDependencies?t.outdatedDependencies(this,e):Promise.resolve([])))).flat()}async deduplicateDependencies(e){return(await Promise.all(Object.values(B).map(t=>t.deduplicateDependencies?t.deduplicateDependencies(this,e):Promise.resolve(null)))).filter(e=>e!==null)}get actions(){return xr(this)}get services(){return this.config.services||{}}async findFilesByName(e){let t=[],n=async r=>{let i=await p(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}},Er=class e{primaryWorktree;worktrees;activeWorktree;constructor(e,t){this.primaryWorktree=e,this.worktrees=t,this.activeWorktree=e}static async retrieve(t){let n=hr(t);if(!n){let n=await Tr.retrieve(t,`main`,!0);return new e(n,[n])}let r=n.worktree.primaryPath,i=mr(t),[a,...o]=await Promise.all([Tr.retrieve(r,`main`,!0),...i.map(e=>Tr.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}};const Dr=async t=>{let r=$n(t).split(`/`),i=[``];for(let t of r){if(t===``){i=i.map(e=>`${e}/`);continue}if(t===`*`){let t=[];for(let n of i){let r=n||`/`;if(await e(r))try{let e=await p(r,{withFileTypes:!0});for(let r of e)r.isDirectory()&&(r.name.startsWith(`.`)||t.push(`${n}${r.name}`))}catch{}}i=t}else i=i.map(e=>`${e}${t}`);i=i.map(e=>`${e}/`)}let a=[];for(let e of i){let t=e.replace(/\/$/,``);await n(t)&&a.push(t)}return a},Or=async t=>{let n=(await J()).projectPaths,r=t?.withConfig??!1,i=await Promise.all(n.map(Dr)),a=new Set,o=[];for(let e of i.flat())a.has(e)||(a.add(e),o.push(e));return(await Promise.all(o.map(async t=>r&&!await e(`${t}/.denvig.yml`)?null:{slug:yr(t),path:t}))).filter(e=>e!==null).sort((e,t)=>e.slug.localeCompare(t.slug))},kr=async()=>{let e=await Or({withConfig:!0}),t=new Map;return await Promise.all(e.map(async e=>{let n=await Er.retrieve(e.path);for(let e of n.worktrees)t.set(e.id,{slug:e.slug,path:e.path})})),t},Ar=`global`,jr=ae(`sha1`).update(`denvig-global`).digest(`hex`);async function Mr(){let e=await J(),t=S(b(),`.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:S(t,`services`,`${jr}.${r}`,`cwd`)};n=e}return{id:jr,slug:Ar,name:`Global`,path:b(),config:{services:n}}}async function Nr(){return new wi(await Mr())}function Pr(e){return e===Ar}const Fr=D.object({id:D.string(),slug:D.string(),name:D.string(),path:D.string()}),Ir=D.object({command:D.string(),env:D.record(D.string(),D.string()).optional(),envFiles:D.array(D.string()).optional(),http:D.object({port:D.number().optional(),domain:D.string().optional(),cnames:D.array(D.string()).optional(),secure:D.boolean().optional()}).optional(),keepAlive:D.boolean().optional(),startOnBoot:D.boolean().optional()}),Lr=D.object({cwd:D.string(),port:D.number().int().positive().optional(),domains:D.array(D.string()).default([]),desiredStatus:D.enum([`running`,`stopped`]).default(`running`),project:Fr.optional(),serviceName:D.string().optional(),config:Ir.optional()}),Rr=D.object({project:D.string(),service:D.string(),port:D.number().int().positive(),defaultService:D.boolean().default(!0),secure:D.boolean().default(!1),desiredStatus:D.enum([`running`,`stopped`]).default(`running`),cert:D.string().optional()}),zr=D.object({dir:D.string(),certPath:D.string(),keyPath:D.string(),domains:D.array(D.string()).default([])}),Br=D.object({services:D.record(D.string(),Lr).default({}),gatewayRoutes:D.record(D.string(),Rr).default({}),certs:D.record(D.string(),zr).default({})}),Vr=()=>S(b(),`.denvig`,`state.json`),Hr=()=>({services:{},gatewayRoutes:{},certs:{}}),Y=(e,t)=>`id:${e}:${t}`,X=async()=>{try{let e=await f(Vr(),`utf-8`),t=Br.safeParse(JSON.parse(e));return t.success?t.data:Hr()}catch{return Hr()}},Z=async e=>{let t=Vr();await d(x(t),{recursive:!0});let n=`${t}.${process.pid}.tmp`;await y(n,`${JSON.stringify(e,null,2)}\n`,`utf-8`),await m(n,t)},Ur=async(e,t)=>(await X()).services[Y(e,t)]??null,Wr=async(e,t,n)=>{let r=await X(),i=Y(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 Z(r)},Gr=async(e,t)=>{let n=await X(),r=Y(e,t),i=n.services[r];i&&(n.services[r]={...i,desiredStatus:`stopped`},await Z(n))},Kr=async(e,t)=>{let n=await X(),r=Y(e,t);r in n.services&&(delete n.services[r],await Z(n))},qr=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},Q=async e=>(await X()).gatewayRoutes[e]??null,Jr=async(e,t)=>{let n=await X();n.gatewayRoutes[e]=t,await Z(n)},Yr=async(e,t)=>{let n=await X(),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 Z(n)},Xr=async(e,t)=>{let n=await X(),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 Z(n)},Zr=async(e,t)=>{let n=await X();n.certs[e]=t,await Z(n)};function Qr(){return S(b(),`.denvig`,`gateway`,`html`)}async function $r(){let e=Qr(),t=S(e,`errors`);await d(t,{recursive:!0}),await y(S(e,`index.html`),ei,`utf-8`),await y(S(t,`404.html`),ti,`utf-8`),await y(S(t,`504.html`),ni,`utf-8`)}const ei=`<!DOCTYPE html>
18
+ <html lang="en">
19
+ <head>
20
+ <meta charset="utf-8">
21
+ <meta name="viewport" content="width=device-width, initial-scale=1">
22
+ <title>Denvig Gateway</title>
23
+ <style>
24
+ * { margin: 0; padding: 0; box-sizing: border-box; }
25
+ 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; }
26
+ .container { text-align: center; max-width: 480px; padding: 2rem; }
27
+ h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.75rem; color: #fff; }
28
+ p { font-size: 0.95rem; line-height: 1.6; color: #888; margin-bottom: 1.5rem; }
29
+ a { color: #6ea4f7; text-decoration: none; }
30
+ a:hover { text-decoration: underline; }
31
+ code { background: #1a1a1a; padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.85rem; color: #ccc; }
32
+ </style>
33
+ </head>
34
+ <body>
35
+ <div class="container">
36
+ <h1>Denvig Gateway</h1>
37
+ <p>This nginx server is managed by <a href="https://denvig.com">Denvig</a>.</p>
38
+ <p>Configure services with <code>http.domain</code> in your <code>.denvig.yml</code> to route traffic here.</p>
39
+ </div>
40
+ </body>
41
+ </html>
42
+ `,ti=`<!DOCTYPE html>
43
+ <html lang="en">
44
+ <head>
45
+ <meta charset="utf-8">
46
+ <meta name="viewport" content="width=device-width, initial-scale=1">
47
+ <title>404 - Not Found</title>
48
+ <style>
49
+ * { margin: 0; padding: 0; box-sizing: border-box; }
50
+ 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; }
51
+ .container { text-align: center; max-width: 480px; padding: 2rem; }
52
+ .code { font-size: 3rem; font-weight: 700; color: #555; margin-bottom: 0.5rem; }
53
+ h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.75rem; color: #fff; }
54
+ p { font-size: 0.95rem; line-height: 1.6; color: #888; margin-bottom: 1rem; }
55
+ a { color: #6ea4f7; text-decoration: none; }
56
+ a:hover { text-decoration: underline; }
57
+ code { background: #1a1a1a; padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.85rem; color: #ccc; }
58
+ </style>
59
+ </head>
60
+ <body>
61
+ <div class="container">
62
+ <div class="code">404</div>
63
+ <h1>Service Not Found</h1>
64
+ <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>
65
+ <p>Check your configuration with <code>denvig gateway status</code></p>
66
+ <p><a href="https://denvig.com">denvig.com</a></p>
67
+ </div>
68
+ </body>
69
+ </html>
70
+ `,ni=`<!DOCTYPE html>
71
+ <html lang="en">
72
+ <head>
73
+ <meta charset="utf-8">
74
+ <meta name="viewport" content="width=device-width, initial-scale=1">
75
+ <title>504 - Service Unavailable</title>
76
+ <style>
77
+ * { margin: 0; padding: 0; box-sizing: border-box; }
78
+ 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; }
79
+ .container { text-align: center; max-width: 480px; padding: 2rem; }
80
+ .code { font-size: 3rem; font-weight: 700; color: #555; margin-bottom: 0.5rem; }
81
+ h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.75rem; color: #fff; }
82
+ p { font-size: 0.95rem; line-height: 1.6; color: #888; margin-bottom: 1rem; }
83
+ a { color: #6ea4f7; text-decoration: none; }
84
+ a:hover { text-decoration: underline; }
85
+ code { background: #1a1a1a; padding: 0.15rem 0.4rem; border-radius: 4px; font-size: 0.85rem; color: #ccc; }
86
+ </style>
87
+ </head>
88
+ <body>
89
+ <div class="container">
90
+ <div class="code">504</div>
91
+ <h1>Service Unavailable</h1>
92
+ <p>This service is configured but does not appear to be running. Start it with <code>denvig services start</code>.</p>
93
+ <p>Check service status with <code>denvig services</code></p>
94
+ <p><a href="https://denvig.com">denvig.com</a></p>
95
+ </div>
96
+ </body>
97
+ </html>
98
+ `,ri=ie(r);function ii(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?`
99
+ ssl_certificate ${c};
100
+ ssl_certificate_key ${l};
101
+ ssl_protocols TLSv1.2 TLSv1.3;
102
+ ssl_ciphers HIGH:!aNULL:!MD5;`:``;return`# denvig:
103
+ # slug: ${r}
104
+ # path: ${n}
105
+ # service: ${i}
106
+ upstream ${u} { server 127.0.0.1:${a} max_fails=0 fail_timeout=30; }
107
+ server {
108
+ ${f?` listen 80;
109
+ listen 443 ssl;
110
+ http2 on;`:` listen 80;`}
111
+ server_name ${d};
112
+ root ${n}/public;
113
+ index index.html;
114
+ client_max_body_size 100M;
115
+ ${p}
116
+
117
+ error_page 502 503 504 /denvig-errors/504.html;
118
+ location /denvig-errors/ {
119
+ alias ${Qr()}/errors/;
120
+ internal;
121
+ }
122
+
123
+ location / {
124
+ proxy_pass http://${u};
125
+ proxy_set_header Host $host;
126
+ proxy_set_header X-Forwarded-Host $host;
127
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
128
+ proxy_redirect off;
129
+ proxy_buffering off;
130
+
131
+ proxy_http_version 1.1;
132
+ proxy_set_header Upgrade $http_upgrade;
133
+ proxy_set_header Connection "upgrade";
134
+ }
135
+ }
136
+ `}function ai(e){return S(e,`..`,`nginx.conf`)}function oi(e){let t=Qr();return`# Managed by denvig — do not edit manually
137
+ # https://denvig.com
138
+
139
+ worker_processes 4;
140
+
141
+ events {
142
+ worker_connections 1024;
143
+ }
144
+
145
+ http {
146
+ include ${S(e,`..`)}/mime.types;
147
+ default_type application/octet-stream;
148
+
149
+ sendfile on;
150
+ keepalive_timeout 65;
151
+
152
+ server {
153
+ listen 80 default_server;
154
+ server_name _;
155
+
156
+ root ${t};
157
+ index index.html;
158
+
159
+ error_page 404 /errors/404.html;
160
+ }
161
+
162
+ include ${e}/*;
163
+ }
164
+ `}async function si(e){try{return await y(ai(e),oi(e),`utf-8`),{success:!0}}catch(e){return{success:!1,message:`Failed to write nginx.conf: ${e instanceof Error?e.message:`Unknown error`}`}}}function ci(e,t,n){return S(n,`denvig.${e}.${t}.conf`)}async function li(e,t){try{let n=ci(e.projectId,e.serviceName,t);return await d(x(n),{recursive:!0}),await y(n,ii(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 ui(){try{return await ri(`/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 di(e){try{let t=(await p(e)).filter(e=>e.startsWith(`denvig.`)&&e.endsWith(`.conf`));return await Promise.all(t.map(t=>h(S(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`}`}}}async function fi(){let e=(await J()).experimental?.gateway;if(!e?.enabled)return null;let t=e.configsPath;await $r();let n=await si(t);if(!n.success)return{success:!1,removed:[],services:[],nginxReload:!1,message:n.message||`Failed to write nginx.conf`};let r=await di(t);if(!r.success)return{success:!1,removed:[],services:[],nginxReload:!1,message:r.message||`Failed to remove existing configs`};let i=await kr(),a=await Mr();i.set(a.id,{slug:a.slug,path:a.path});let o=await X(),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 li({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 ui(),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`}}const pi=[`.env.development`,`.env.local`];function mi(e){let t={},n=e.split(`
165
+ `);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 hi(e){try{return mi(await f(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 gi(e,t){let n={},r=t?.skipMissing??!1;for(let t of e){if(r)try{await c(t)}catch{continue}let e=await hi(t);Object.assign(n,e)}return n}function $(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&apos;`)}function _i(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 vi(e){return e.replace(/'/g,`'\\''`)}function yi(e){let t=_i(e.command);return`#!/bin/bash
166
+ #
167
+ # Denvig service wrapper
168
+ # Service: ${e.serviceName}
169
+ # Project: ${e.projectSlug}
170
+ # Path: ${e.projectPath}
171
+ # Command: ${e.command}
172
+ # Workdir: ${e.workingDirectory}
173
+ #
174
+ exec /bin/zsh -l -c '${vi(t)}'
175
+ `}function bi(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>${$(e)}</key>
176
+ <string>${$(t)}</string>`).join(`
177
+ `);return`<?xml version="1.0" encoding="UTF-8"?>
178
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
179
+ <plist version="1.0">
180
+ <dict>
181
+ <key>Label</key>
182
+ <string>${$(t)}</string>
183
+
184
+ <key>ProgramArguments</key>
185
+ <array>
186
+ <string>${$(n)}</string>
187
+ </array>
188
+
189
+ <key>WorkingDirectory</key>
190
+ <string>${$(r)}</string>
191
+
192
+ <key>EnvironmentVariables</key>
193
+ <dict>
194
+ ${c}
195
+ </dict>
196
+
197
+ <key>StandardOutPath</key>
198
+ <string>${$(a)}</string>
199
+
200
+ <key>KeepAlive</key>
201
+ <${o?`true`:`false`}/>
202
+
203
+ <key>RunAtLoad</key>
204
+ <${s?`true`:`false`}/>
205
+ </dict>
206
+ </plist>
207
+ `}const xi={min:8e3,max:9999},Si=e=>new Promise(t=>{let n=ce();n.unref(),n.once(`error`,e=>{t(e.code===`EADDRINUSE`)}),n.once(`listening`,()=>{n.close(()=>t(!1))}),n.listen(e)}),Ci=async e=>{let t=e?.range??xi,n=await X(),r=new Set([...qr(n),...e?.excludePorts??[]]),i=async e=>r.has(e)?!1:!await Si(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};var wi=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??pi;if(a.length>0)try{let e=await gi(a.map(e=>S(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 Ur(this.project.id,e);if(t?.forceRandom){let e=await Ci({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 Si(r))return{success:!0,port:r,source:`config`,conflict:!1,configPort:r};let e=await Ci();return{success:!0,port:e??void 0,source:e===null?`none`:`allocated`,conflict:!0,configPort:r}}let a=await Ci();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 U.print(a),s=o!==null,c=o!==null&&o.pid!==void 0&&o.state===`running`,p=n.http?.domain?[n.http.domain,...n.http.cnames??[]]:[];if(await Wr(this.project.id,e,{cwd:this.resolveServiceCwd(n),port:r,domains:p,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&&p.length>0){let i=n.http?.secure??!1,a;if(i){let e=await Bn(p[0]);if(e){let t=await Wn(e);t&&(a=ne(e),await Zr(a,{dir:e,certPath:t.sslCertPath,keyPath:t.sslKeyPath,domains:p}))}}for(let n of p){let o=await Q(n),s=o?.project===this.project.id&&o?.service===e,c=o!==null&&!s&&o.desiredStatus===`stopped`;!o||s||c?await Jr(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 Jr(n,{project:this.project.id,service:e,port:r,secure:i,defaultService:!1,desiredStatus:`running`,cert:a})}}await this.ensureDenvigDirectories();let m=await this.createLogFile(e),h=this.getPlistPath(e),g=this.resolveServiceCwd(n);await d(g,{recursive:!0});let _=this.getServiceScriptPath(e),v=yi({command:n.command,serviceName:e,projectPath:this.project.path,projectSlug:this.project.slug,workingDirectory:g}),b=null;try{b=await f(_,`utf-8`)}catch{}b!==v&&(await y(_,v,`utf-8`),await u(_,493));let ee=bi({label:a,programPath:_,workingDirectory:g,environmentVariables:i.env,standardOutPath:this.getStableLogPath(e),keepAlive:n.keepAlive??!0,runAtLoad:n.startOnBoot??!1}),te=null;try{te=await f(h,`utf-8`)}catch{}let x=te!==ee;if(x&&await y(h,ee,`utf-8`),await U.enable(a),!s){let t=await U.bootstrap(h);if(!t.success)return{name:e,success:!1,message:`Failed to bootstrap service: ${t.output}`}}else if(x||t?.reviveIfNotRunning!==!1&&!c){let t=await U.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 U.bootstrap(h);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 l(m,`[${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 U.stop(n);if(!t.success)return{name:e,success:!1,message:`Failed to stop service: ${t.output}`}}else{let t=await U.bootout(n);if(!t.success)return{name:e,success:!1,message:`Failed to stop service: ${t.output}`};await U.disable(n),r=!0}try{let t=new Date().toISOString();await l(this.getLogPath(e),`[${t}] Service Stopped\n`,`utf-8`)}catch{}return await Gr(this.project.id,e),await Yr(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 U.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 U.list(n);for(let e of i){let i=await U.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=S(b(),`Library`,`LaunchAgents`);if(await Promise.all(r.map(async e=>{try{await v(S(a,`${e}.plist`))}catch{}})),e?.removeLogs&&r.length>0){let e=this.getDenvigHomeDir(),t=S(e,`logs`),n=r.map(e=>e.replace(`denvig.`,``));await Promise.all(n.flatMap(n=>[h(S(e,`services`,n),{recursive:!0,force:!0}).catch(()=>{}),v(S(t,`${n}.log`)).catch(()=>{}),v(S(t,`${n}.error.log`)).catch(()=>{})]))}return await Promise.all(r.flatMap(e=>{let t=e.replace(n,``);return[Kr(this.project.id,t),Xr(this.project.id,t)]})),await this.reconfigureGateway(),t}async isServiceBootstrapped(e){let t=this.getServiceLabel(e);return await U.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 S(b(),`.denvig`)}getPlistPath(e){let t=this.getServiceLabel(e);return S(b(),`Library`,`LaunchAgents`,`${t}.plist`)}getServiceDir(e){let t=this.normalizeForLabel(e),n=`${this.project.id}.${t}`;return S(this.getDenvigHomeDir(),`services`,n)}getServiceLogDir(e){return S(this.getServiceDir(e),`logs`)}getServiceScriptPath(e){let t=this.normalizeForLabel(e),n=this.project.slug,r=n.startsWith(`github:`)?`${n.replace(`github:`,``).replace(`/`,`-`)}-`:``;return S(this.getServiceDir(e),`denvig-${r}${t}`)}getStableLogPath(e){return S(this.getServiceLogDir(e),`latest.log`)}getLogPath(e,t){let n=ee();return S(this.getServiceLogDir(e),`latest.${n}.log`)}async createLogFile(e){let t=this.getServiceLogDir(e);await d(t,{recursive:!0});let n=`${Math.floor(Date.now()/1e3)}.log`,r=S(t,n);await y(r,``,`utf-8`);let i=this.getStableLogPath(e),a=this.getLogPath(e);return await Promise.all([i,a].map(async e=>{try{await v(e)}catch{}await _(n,e)})),r}async ensureDenvigDirectories(){await d(S(this.getDenvigHomeDir(),`logs`),{recursive:!0})}async getRecentLogs(e,t){try{return(await f(this.getLogPath(e),`utf-8`)).trim().split(`
208
+ `).slice(-t)}catch{return[]}}resolveServiceCwd(e){return S(this.project.path,e.cwd||`.`)}getServiceConfig(e){return this.project.config.services?.[e]}async reconfigureGateway(){let e=await fi();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 Q(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 Ur(this.project.id,e);return t?.port===void 0?this.getServiceConfig(e)?.http?.port:t.port}async plistExists(e){try{return await c(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 U.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??pi).map(e=>S(this.resolveServiceCwd(n),e)),lastExitCode:o};return t?.includeLogs&&(c.logs=await this.getRecentLogs(e,t.logLines??20)),c}};async function Ti(e){let t=[],n=[],r=await U.list(`denvig.`);for(let e of r){let r=await U.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=S(b(),`Library`,`LaunchAgents`);try{let e=(await p(i)).filter(e=>e.startsWith(`denvig.`)&&e.endsWith(`.plist`));await Promise.all(e.map(async e=>{try{await v(S(i,e))}catch{}}))}catch{}if(e?.removeLogs){let e=S(b(),`.denvig`),t=S(e,`logs`);try{let e=await p(t);await Promise.all(e.map(async e=>{try{await v(S(t,e))}catch{}}))}catch{}let n=S(e,`services`);try{let e=await p(n);await Promise.all(e.filter(e=>e.startsWith(`denvig.`)||e.includes(`.`)).map(async e=>{try{await h(S(n,e,`logs`),{recursive:!0,force:!0})}catch{}}))}catch{}}try{await y(S(b(),`.denvig`,`state.json`),`${JSON.stringify({services:{},gatewayRoutes:{}},null,2)}\n`,`utf-8`)}catch{}return{success:!0,services:t,logsRemoved:e?.removeLogs??!1}}async function Ei(e,t){let n=e.activeWorktree,r=await new wi(n).teardownAll({removeLogs:t?.removeLogs});return{success:!0,project:n.slug,services:r,logsRemoved:t?.removeLogs??!1}}export{bt as $,Wn as A,Tn as B,or as C,Xn as D,J as E,K as F,Sn as G,Mn as H,xn as I,kn as J,Dn as K,On as L,Ln as M,Cn as N,Bn as O,wn as P,It as Q,Fn as R,ur as S,$n as T,Nn as U,jn as V,Pn as W,U as X,An as Y,B as Z,br as _,ai as a,xe as at,cr as b,X as c,Mr as d,lt as et,Nr as f,Er as g,kr as h,fi as i,be as it,Rn as j,Un as k,Xr as l,Or as m,Ei as n,Re as nt,ci as o,ye as ot,Pr as p,En as q,wi as r,Oe as rt,Q as s,pe as st,Ti as t,it as tt,Kr as u,pr as v,ir as w,lr as x,sr as y,G as z};