@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.
- package/LICENSE +8 -0
- package/README.md +17 -0
- package/dist/chunk-CMqjfN_6.cjs +1 -0
- package/dist/fs.cjs +1 -0
- package/dist/fs.d.ts +15 -0
- package/dist/fs.js +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +273 -0
- package/dist/index.js +1 -0
- package/dist/internal.cjs +1 -0
- package/dist/internal.d.ts +202 -0
- package/dist/internal.js +1 -0
- package/dist/path-DElA4WIM.js +1 -0
- package/dist/path-pt0IDc1N.cjs +1 -0
- package/dist/project-BA4nj7bB.js +1 -0
- package/dist/project-BqMRVXi0.cjs +1 -0
- package/dist/project-DmYu4L1C.d.ts +247 -0
- package/dist/reconcile-C90QGHEJ.d.ts +50 -0
- package/dist/reconcile-CvY7dT3H.js +1 -0
- package/dist/reconcile-DU2Wb6SO.cjs +1 -0
- package/dist/safeReadFile-BlLUgHuA.cjs +1 -0
- package/dist/safeReadFile-Z2PHqO9j.js +1 -0
- package/dist/semver-CxqsdmU_.cjs +1 -0
- package/dist/semver-dZSpezIR.js +1 -0
- package/dist/teardown-BuHyVdhH.d.ts +764 -0
- package/dist/teardown-DgjT-aE7.js +208 -0
- package/dist/teardown-DypXa0Wy.cjs +208 -0
- package/dist/testing.cjs +1 -0
- package/dist/testing.d.ts +32 -0
- package/dist/testing.js +1 -0
- package/dist/utils.cjs +1 -0
- package/dist/utils.d.ts +15 -0
- package/dist/utils.js +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require("./teardown-DypXa0Wy.cjs"),t=require("./semver-CxqsdmU_.cjs");let n=require("node:child_process"),r=require("node:crypto");var i=class extends Error{constructor(e){super(e),this.name=`DenvigError`}},a=class extends i{constructor(e){super(e),this.name=`DenvigValidationError`}},o=class extends i{details;constructor(e,t){super(e),this.name=`DenvigOperationError`,this.details=t}},s=class extends Error{originalMessage;stderr;stdout;constructor(e,t,n,r){super(e),this.name=`DenvigSDKError`,this.originalMessage=t,this.stderr=n,this.stdout=r}};const c=async(e,t)=>{let{args:r=[],projectSlug:i,cwd:a}=t,o=t.onCommand??(e=>console.log(e)),s=t.interactive??!!(process.stdout.isTTY&&process.stdin.isTTY),c={success:!0};for(let t of e){let e=`${t} ${r.join(` `)}`.trim();o(`$ ${e}`);let l={...process.env,DENVIG_PROJECT:i},u,d;s?process.platform===`darwin`?(u=`script`,d=[`-q`,`/dev/null`,`sh`,`-c`,e]):(u=`script`,d=[`-q`,`-c`,e,`/dev/null`]):(u=`sh`,d=[`-c`,e]);let f=(0,n.spawn)(u,d,{cwd:a,env:l,stdio:`inherit`}),p=await new Promise(e=>{f.on(`close`,t=>{e({success:t===0})})});p.success||(c=p)}return c};var l=`0.7.0-alpha.4`;function u(){return l}const d=async(t,n,r,i)=>{let a=e.st({version:u(),command:`sdk:${n}`,path:t.cwd,slug:r??void 0,via:`sdk:${t.client}`});try{let e=await i();return await a.finish(0),e}catch(e){let t=e instanceof Error?e.message:String(e);throw await a.finish(1,t.replace(/[\r\n]+/g,` `).trim()),e}};var f=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 d(this.ctx,`actions.run`,this.worktree.slug,()=>c(this._commands,{args:e?.args,projectSlug:this.worktree.slug,cwd:this.worktree.path}))}};const p=async t=>{let n=[];if(t.config.actions)for(let[e,r]of Object.entries(t.config.actions))n.push({name:e,ecosystem:`project`,commands:[r.command]});for(let[r,i]of Object.entries(e.Z)){let e=await i.actions(t);for(let[t,a]of Object.entries(e))n.push({name:t,ecosystem:i.name??r,commands:a})}return n},m=(e,t,n)=>{let r=t,i=n,o=t.indexOf(`:`);o!==-1&&!e.some(e=>e.name===t)&&(i=t.slice(0,o),r=t.slice(o+1));let s=e.filter(e=>e.name===r);if(s.length===0)throw new a(`Action "${t}" not found.`);if(i){let e=s.find(e=>e.ecosystem===i);if(!e)throw new a(`Action "${r}" not found for ecosystem "${i}".`);return e}return{name:r,ecosystem:s[0].ecosystem,commands:s.flatMap(e=>e.commands)}},h=async(t,n)=>{let r=t.activeWorktree,i=r.config.$sources.length>0,a=n?.includeServiceStatus??!0,{$sources:o,...s}=r.config,c=`none`;if(a){let t=r.config.services||{},i=Object.keys(t);if(i.length>0){let t=n?.launchctlList??await e.X.list(`denvig.`),a=new e.r(r),o=!1;for(let e of i)if((await a.getServiceResponse(e,{launchctlList:t}))?.status===`running`){o=!0;break}c=o?`running`:`stopped`}}return{id:r.id,slug:r.slug,name:r.name,path:r.path,refs:r.refs,worktrees:t.worktrees.filter(e=>!e.isPrimary).map(e=>({path:e.path,branch:e.branch})),config:i?s:null,serviceStatus:c}},g=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}`},_=e=>{let t=g(e);return{id:t,hash:(0,r.createHash)(`sha256`).update(t).digest(`hex`)}},v=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(`/`)}},y=async(t,n)=>{let r=await e.m();switch(t.type){case`id`:for(let n of r){let r=await e.g.retrieve(n.path);if(r.id===t.value||r.id.startsWith(t.value))return n.path}return null;case`github`:{let e=r.find(e=>e.slug===`github:${t.value}`);return e?e.path:null}case`local`:{let e=n(t.value),i=r.find(t=>t.path===e);return i?i.path:e}case`path`:return n(t.value)}},b=async(e,t)=>{let n=v(e);return{path:await y(n,t),serviceName:n.serviceName}},x=(e,t)=>{if(e.startsWith(`global:`))return{projectSlug:`global`,serviceName:e.slice(7)};if(!e.includes(`/`))return{projectSlug:t,serviceName:e};let n=v(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}},S=async t=>{let n=await e.m({withConfig:!0}),r=n.find(e=>e.slug===t);if(r)return r.path;let i=n.find(e=>e.slug.replace(/^(github|local):/,``)===t);return i?i.path:null},C=async t=>{let n=await e.m({withConfig:!0});for(let r of n){let n=await e.g.retrieve(r.path);if(n.id===t||n.id.startsWith(t))return r.path}return null},w=async(t,n)=>{if(t.startsWith(`global:`)){let n=t.slice(7);return{project:await e.d(),manager:await e.f(),serviceName:n}}let r=v(t);if(r.serviceName!==void 0&&r.serviceName!==``){let t=await y(r,e.T);if(t){let n=(await e.g.retrieve(t)).activeWorktree;return{project:n,manager:new e.r(n),serviceName:r.serviceName}}}let{projectSlug:i,projectId:a,serviceName:o}=x(t,n.slug),s;if(e.p(i))return{project:await e.d(),manager:await e.f(),serviceName:o};if(a)if(n.id===a||n.id.startsWith(a))s=n.activeWorktree;else{let t=await C(a);if(t)s=(await e.g.retrieve(t)).activeWorktree;else throw Error(`Project with ID "${a}" not found`)}else if(i===n.slug)s=n.activeWorktree;else{let t=await S(i);s=t?(await e.g.retrieve(t)).activeWorktree:(await e.g.retrieve(i)).activeWorktree}let c=new e.r(s);return{project:s,manager:c,serviceName:o}},T=(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},E={npm:async(t,n)=>{let r=await e.rt(t,n);return r?{ecosystem:`npm`,name:t,...r}:null},jsr:async(t,n)=>{let r=await e.nt(t,n);return r?{ecosystem:`jsr`,name:t,...r}:null},pypi:async(t,n)=>{let r=await e.Q(t,n);return r?{ecosystem:`pypi`,name:t,...r}:null},rubygems:async(t,n)=>{let r=await e.$(t,n);return r?{ecosystem:`rubygems`,name:t,...r}:null}},D=async(e,t={})=>{let n=e.indexOf(`:`);if(n<=0)throw new a(`Invalid dependency identifier "${e}". Expected "<ecosystem>:<name>" (e.g. "npm:redis").`);let r=e.slice(0,n),i=e.slice(n+1),o=E[r];if(!o)throw new a(`Unsupported ecosystem "${r}". Supported: ${Object.keys(E).join(`, `)}.`);if(!i)throw new a(`Invalid dependency identifier "${e}". Missing package name.`);return o(i,t.noCache)},O=e=>e.dependencies(),k=e=>e.versions[0]?.resolved||``,A=async(n,r={})=>{let{semver:i,ecosystem:o}=r,s=r.cache??!0;if(i&&i!==`patch`&&i!==`minor`&&i!==`major`)throw new a(`Invalid semver value: "${i}". Must be "patch", "minor", or "major".`);let c=await n.outdatedDependencies({cache:s});o&&(c=c.filter(e=>e.ecosystem===o)),i&&(c=c.filter(e=>t.n({currentVersion:k(e),wantedVersion:e.wanted,latestVersion:e.latest},i)));let l=null,u=[],d=r.releaseLatency??`auto`;if(d===`0`)l=null;else if(d===`auto`){let t=await e.et(n.path);t?(l=t.minimumReleaseAgeMs,u=t.exclude):l=1440*60*1e3}else if(l=e.tt(d),l===null)throw new a(`Invalid releaseLatency value: "${d}". Use a duration like "3h", "7d", "2w", or "auto".`);if(l!==null){let e=l,t=Date.now();c=c.filter(n=>{if(u.includes(n.name))return!0;let r=k(n),i=n.wanted!==r,a=n.latest!==r,o=i&&n.wantedDate?t-new Date(n.wantedDate).getTime()>=e:!1,s=a&&n.latestDate?t-new Date(n.latestDate).getTime()>=e:!1;return i&&n.wantedDate||a&&n.latestDate?o||s:!0})}return c.sort((e,t)=>{let n=e.ecosystem.localeCompare(t.ecosystem);return n===0?e.name.localeCompare(t.name):n})},j=async t=>{let n={};for(let[r,i]of Object.entries(e.Z)){let e=await i.actions(t);n[r]={name:i.name,actions:e}}return n},M=new Set([`running`,`stopped`,`error`]),N=e=>{if(!e)return null;let t=(Array.isArray(e)?e:e.split(`,`)).map(e=>e.trim().toLowerCase()),n=t.filter(e=>!M.has(e));if(n.length>0)throw new a(`Invalid status value(s): ${n.join(`, `)}. Allowed: running, stopped, error.`);return t},P=async(t,n,r={})=>{let i=!!r.all,o=!!r.global,s=!!r.worktrees,c=r.worktree??null,l=N(r.status);if((i||o)&&c!==null)throw new a(`worktree cannot be combined with all or global.`);if(s&&(o||c!==null))throw new a(`worktrees cannot be combined with global or worktree.`);if(i&&o)throw new a(`Cannot combine all and global. Choose one.`);if(!i&&!o&&(!t||!n))throw new a(`No project provided or detected.`);let u=n;c!==null&&t&&(u=T(t,c));let d=await e.X.list(`denvig.`),f=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:d});i&&r.push({service:i,depth:t,label:n})}},p=async e=>{let t=new Map;for(let n of await e.listServices()){let r=await e.getServiceResponse(n.name,{launchctlList:d});r&&t.set(n.name,r)}return t},m=async(t,n)=>{let r=t.primaryWorktree,i=await p(new e.r(r));if(!s){for(let e of[...i.keys()].sort()){let t=i.get(e);t&&n.push({service:t,depth:0,label:r.slug})}return}let a=[];for(let n of t.worktrees.filter(e=>!e.isPrimary))a.push({branch:n.branch,services:await p(new e.r(n))});let o=new Set(i.keys());for(let e of a)for(let t of e.services.keys())o.add(t);for(let e of[...o].sort()){let t=i.get(e);t&&n.push({service:t,depth:0,label:r.slug});for(let t of a){let r=t.services.get(e);r&&n.push({service:r,depth:1,label:t.branch})}}},h=async t=>{let n=new Map;for(let r of t){let t=await e.g.retrieve(r),i=t.primaryWorktree.path;n.has(i)||n.set(i,t)}return[...n.values()].sort((e,t)=>e.primaryWorktree.slug.localeCompare(t.primaryWorktree.slug))},g=[];if(o){let t=await e.d();Object.keys(t.config.services||{}).length>0&&await f(new e.r(t),0,t.slug,g)}else if(i){let t=await h((await e.m()).map(e=>e.path));for(let e of t)await m(e,g);let n=await e.d();Object.keys(n.config.services||{}).length>0&&await f(new e.r(n),0,n.slug,g)}else if(s)await m(t,g);else{let t=u;await f(new e.r(t),0,t.slug,g)}return l?g.filter(e=>l.includes(e.service.status)):g},F=async(e,t,n)=>(n&&(e.activeWorktree=T(e,n)),w(t,e)),I=async(e,t,n={})=>{let{manager:r,serviceName:i}=await F(e,t,n.worktree),o=await r.getServiceResponse(i,{includeLogs:n.includeLogs??!1});if(!o)throw new a(`Service "${i}" not found in configuration.`);return o},L=()=>new Promise(e=>setTimeout(e,2e3)),R=async(e,t,n={})=>{let{manager:r,serviceName:i,project:a}=await F(e,t,n.worktree),s=await r.resolveServicePort(i,{}),c=await r.startService(i,{port:s.success?s.port:void 0,portResolved:!0});if(!c.success)throw new o(c.message,{service:i,project:a.slug});await L();let l=await r.getServiceResponse(i,{includeLogs:!0});if(l?.status===`running`&&await r.reconfigureGateway(),!l)throw new o(`Service failed to start.`,{service:i,project:a.slug});return l},z=async(e,t,n={})=>{let{manager:r,serviceName:i,project:a}=await F(e,t,n.worktree),s=await r.stopService(i);if(!s.success)throw new o(s.message,{service:i,project:a.slug});let c=await r.getServiceResponse(i);if(!c)throw new o(`Service "${i}" not found after stopping.`,{service:i,project:a.slug});return c};var B=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 d(this.ctx,`services.start`,this.project.slug,()=>R(this.project,this.serviceName,{worktree:this.worktreeName}))}async stop(){return d(this.ctx,`services.stop`,this.project.slug,()=>z(this.project,this.serviceName,{worktree:this.worktreeName}))}async status(){return d(this.ctx,`services.status`,this.project.slug,()=>I(this.project,this.serviceName,{worktree:this.worktreeName,includeLogs:!0}))}},V=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)}},H=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 V(this.internal.activeWorktree)}get primaryWorktree(){return new V(this.internal.primaryWorktree)}worktreeFor(e){return e?T(this.internal,e):this.internal.activeWorktree}selectWorktree(e){let t=T(this.internal,e);return this.internal.activeWorktree=t,new V(t)}info(e){return d(this.ctx,`projects.info`,this.internal.slug,()=>h(this.internal,e))}plugins(){return d(this.ctx,`plugins.list`,this.internal.slug,()=>j(this.internal.activeWorktree))}teardown(t){return d(this.ctx,`projects.teardown`,this.internal.slug,()=>e.n(this.internal,t))}resourceId(e){return g({project:this.internal,...e})}resourceHash(e){return _({project:this.internal,...e})}worktrees={list:()=>this.internal.worktrees.map(e=>new V(e)),retrieve:e=>new V(T(this.internal,e))};actions={retrieve:async(e,t)=>{let n=this.worktreeFor(t?.worktree),r=m(await p(n),e,t?.ecosystem);return new f(r.name,r.commands,n,this.ctx)}};services={retrieve:async(e,t)=>new B(this.internal,e,t?.worktree,this.ctx),list:e=>d(this.ctx,`services.list`,this.internal.slug,()=>P(this.internal,this.internal.activeWorktree,e)),context:async e=>{let{manager:t,serviceName:n,project:r}=await w(e,this.internal);return{manager:t,serviceName:n,target:r}}};dependencies={list:()=>d(this.ctx,`dependencies.list`,this.internal.slug,()=>O(this.internal.activeWorktree)),tree:t=>d(this.ctx,`dependencies.tree`,this.internal.slug,async()=>e.it(await O(this.internal.activeWorktree),t?.depth??0,t?.ecosystem)),info:(e,t)=>d(this.ctx,`dependencies.info`,this.internal.slug,()=>D(e,t)),retrieve:async e=>{let t=(await O(this.internal.activeWorktree)).find(t=>t.id===e);if(!t)throw new a(`Dependency "${e}" not found.`);return t},outdated:e=>{let t=this.worktreeFor(e?.worktree);return d(this.ctx,`dependencies.outdated`,this.internal.slug,()=>A(t,{ecosystem:e?.ecosystem,semver:e?.semver,releaseLatency:e?.releaseLatency,cache:e?.noCache?!1:void 0}))}};config={retrieve:()=>Promise.resolve(this.internal.activeWorktree.config)}};Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return f}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return b}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return o}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return s}});
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { D as ProjectConfigSchema, _ as ProjectInfo, a as TreeDependencyEntry, d as DeduplicateResult, f as OutdatedDependenciesOptions, g as GetProjectInfoOptions, h as ServiceResponse, i as ServiceManagerProject, l as Worktree, m as OutdatedDependency, p as Dependency, r as ServiceManager, t as ProjectTeardownResult, u as DeduplicateDependenciesOptions, w as ConfigWithSourcePaths, y as DenvigProject$1 } from "./teardown-BuHyVdhH.js";
|
|
2
|
+
|
|
3
|
+
//#region src/resources/context.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Shared context threaded through every resource so SDK calls are attributed to
|
|
6
|
+
* the calling client in the usage log (`via: sdk:<client>`).
|
|
7
|
+
*/
|
|
8
|
+
type ResourceContext = {
|
|
9
|
+
/** Identifier for the integration using the SDK (e.g. `cli`, `raycast`). */client: string; /** Working directory used to resolve projects and as the log entry path. */
|
|
10
|
+
cwd: string;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/resources/action.d.ts
|
|
14
|
+
/**
|
|
15
|
+
* A runnable action resolved for a worktree. `run()` streams the underlying
|
|
16
|
+
* command(s) to the parent process, TTY-aware, exactly as the CLI does.
|
|
17
|
+
*/
|
|
18
|
+
declare class DenvigAction {
|
|
19
|
+
private readonly _name;
|
|
20
|
+
private readonly _commands;
|
|
21
|
+
private readonly worktree;
|
|
22
|
+
private readonly ctx;
|
|
23
|
+
constructor(name: string, commands: string[], worktree: Worktree, ctx: ResourceContext);
|
|
24
|
+
get name(): string;
|
|
25
|
+
/** The resolved shell command(s) this action runs, in order. */
|
|
26
|
+
get commands(): string[];
|
|
27
|
+
/** Run the action's commands, streaming output to the parent process. */
|
|
28
|
+
run(options?: {
|
|
29
|
+
args?: string[];
|
|
30
|
+
}): Promise<{
|
|
31
|
+
success: boolean;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
//#region src/lib/resources.d.ts
|
|
36
|
+
type ResourceIdOptions = {
|
|
37
|
+
project: DenvigProject$1;
|
|
38
|
+
workspace?: string;
|
|
39
|
+
resource: `action/${string}` | `service/${string}`;
|
|
40
|
+
};
|
|
41
|
+
type DenvigResourceHash = {
|
|
42
|
+
id: string;
|
|
43
|
+
hash: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Construct a unique ID for a denvig resource.
|
|
47
|
+
* These IDs are used internally to identify resources uniquely across all projects, workspaces, and resources.
|
|
48
|
+
*/
|
|
49
|
+
/**
|
|
50
|
+
* Generate a unique hash for a denvig resource.
|
|
51
|
+
*/
|
|
52
|
+
declare const generateDenvigResourceHash: (options: ResourceIdOptions) => DenvigResourceHash;
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/operations/deps.d.ts
|
|
55
|
+
type SemverLevel = 'patch' | 'minor' | 'major';
|
|
56
|
+
/** Registry information about a single dependency, across ecosystems. */
|
|
57
|
+
type DependencyInfo = {
|
|
58
|
+
/** Ecosystem the dependency belongs to (e.g. `npm`, `rubygems`). */ecosystem: string; /** Package name within the ecosystem. */
|
|
59
|
+
name: string; /** Latest version published to the registry, or `null` if unknown. */
|
|
60
|
+
latest: string | null; /** All known versions, newest-last where the registry preserves order. */
|
|
61
|
+
versions: string[]; /** ISO publish dates keyed by version, when the registry provides them. */
|
|
62
|
+
versionDates?: Record<string, string>;
|
|
63
|
+
};
|
|
64
|
+
type DependencyInfoOptions = {
|
|
65
|
+
/** Skip the on-disk cache and fetch fresh data from the registry. */noCache?: boolean;
|
|
66
|
+
};
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/operations/plugins.d.ts
|
|
69
|
+
type PluginInfo = {
|
|
70
|
+
name: string;
|
|
71
|
+
actions: Record<string, string[]>;
|
|
72
|
+
};
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/resources/service.d.ts
|
|
75
|
+
/**
|
|
76
|
+
* A single service belonging to a project. Lifecycle calls resolve the service
|
|
77
|
+
* (including cross-project identifiers and the optional worktree override) and
|
|
78
|
+
* are logged via the owning SDK client.
|
|
79
|
+
*/
|
|
80
|
+
declare class DenvigService {
|
|
81
|
+
private readonly project;
|
|
82
|
+
private readonly serviceName;
|
|
83
|
+
private readonly worktreeName;
|
|
84
|
+
private readonly ctx;
|
|
85
|
+
constructor(project: DenvigProject$1, serviceName: string, worktreeName: string | undefined, ctx: ResourceContext);
|
|
86
|
+
get name(): string;
|
|
87
|
+
/** Start the service and return its resulting status. */
|
|
88
|
+
start(): Promise<ServiceResponse>;
|
|
89
|
+
/** Stop the service and return its resulting status. */
|
|
90
|
+
stop(): Promise<ServiceResponse>;
|
|
91
|
+
/** Get the service's current status, including recent log lines. */
|
|
92
|
+
status(): Promise<ServiceResponse>;
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/resources/worktree.d.ts
|
|
96
|
+
/**
|
|
97
|
+
* A public view of a single git checkout belonging to a project. Identity
|
|
98
|
+
* (`name`/`branch`/`path`/`slug`/`id`) plus the path-sensitive config, actions,
|
|
99
|
+
* services and dependencies for this checkout are reached from here.
|
|
100
|
+
*/
|
|
101
|
+
declare class DenvigWorktree {
|
|
102
|
+
private readonly _internal;
|
|
103
|
+
constructor(internal: Worktree);
|
|
104
|
+
/** The underlying internal worktree. Not part of the public contract. */
|
|
105
|
+
get internal(): Worktree;
|
|
106
|
+
get name(): string;
|
|
107
|
+
get branch(): string;
|
|
108
|
+
get path(): string;
|
|
109
|
+
get slug(): string;
|
|
110
|
+
get id(): string;
|
|
111
|
+
get isPrimary(): boolean;
|
|
112
|
+
/** This checkout's resolved configuration (with source paths). */
|
|
113
|
+
get config(): ConfigWithSourcePaths<ProjectConfigSchema>;
|
|
114
|
+
/** Services defined in this checkout's configuration. */
|
|
115
|
+
get services(): NonNullable<ProjectConfigSchema['services']>;
|
|
116
|
+
/** All actions runnable for this checkout, keyed by name. */
|
|
117
|
+
get actions(): Promise<Record<string, string[]>>;
|
|
118
|
+
/** Detect all dependencies for this checkout. */
|
|
119
|
+
dependencies(): Promise<Dependency[]>;
|
|
120
|
+
/** Resolve outdated dependencies for this checkout. */
|
|
121
|
+
outdatedDependencies(options?: OutdatedDependenciesOptions): Promise<OutdatedDependency[]>;
|
|
122
|
+
/** Deduplicate this checkout's lockfile dependencies. */
|
|
123
|
+
deduplicateDependencies(options?: DeduplicateDependenciesOptions): Promise<DeduplicateResult[]>;
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
//#region src/operations/services.d.ts
|
|
127
|
+
type ListServicesOptions = {
|
|
128
|
+
/** List services across all projects and global services. */all?: boolean; /** List only global services. */
|
|
129
|
+
global?: boolean; /** Nest each project's worktree services beneath it. */
|
|
130
|
+
worktrees?: boolean; /** Target a sibling git worktree by branch name (use "main" for primary). */
|
|
131
|
+
worktree?: string;
|
|
132
|
+
/**
|
|
133
|
+
* Filter by runtime status. Accepts a status, a list of statuses, or a
|
|
134
|
+
* comma-separated string; invalid values throw a validation error.
|
|
135
|
+
*/
|
|
136
|
+
status?: string | string[];
|
|
137
|
+
};
|
|
138
|
+
/** A rendered row: a service plus where it sits in the project/worktree tree. */
|
|
139
|
+
type ServiceRow = {
|
|
140
|
+
service: ServiceResponse; /** 0 for a project's own services, 1 for a worktree's. */
|
|
141
|
+
depth: 0 | 1; /** Project column text: project slug at depth 0, branch at depth 1. */
|
|
142
|
+
label: string;
|
|
143
|
+
};
|
|
144
|
+
//#endregion
|
|
145
|
+
//#region src/resources/project.d.ts
|
|
146
|
+
type ActionRetrieveOptions = {
|
|
147
|
+
/** Target a sibling git worktree by branch name (`main` = primary). */worktree?: string; /** Restrict resolution to a single ecosystem (e.g. `npm`). */
|
|
148
|
+
ecosystem?: string;
|
|
149
|
+
};
|
|
150
|
+
type ServiceRetrieveOptions = {
|
|
151
|
+
/** Target a sibling git worktree by branch name (`main` = primary). */worktree?: string;
|
|
152
|
+
};
|
|
153
|
+
type DependenciesTreeOptions = {
|
|
154
|
+
/** Include transitive dependencies up to this depth (`0` = direct only). */depth?: number; /** Restrict the tree to a single ecosystem (e.g. `npm`). */
|
|
155
|
+
ecosystem?: string;
|
|
156
|
+
};
|
|
157
|
+
type DependenciesOutdatedOptions = {
|
|
158
|
+
/** Filter to a specific ecosystem (e.g. `npm`, `rubygems`). */ecosystem?: string; /** Filter by semver level. */
|
|
159
|
+
semver?: SemverLevel; /** Resolve dependencies in a sibling worktree by branch name. */
|
|
160
|
+
worktree?: string; /** Only show updates released longer ago than this duration. */
|
|
161
|
+
releaseLatency?: string; /** Skip cache and fetch fresh data from the registry. */
|
|
162
|
+
noCache?: boolean;
|
|
163
|
+
};
|
|
164
|
+
type ResourceIdentifierOptions = {
|
|
165
|
+
/** Workspace within the project (defaults to `root`). */workspace?: string; /** Resource reference, e.g. `service/api` or `action/build`. */
|
|
166
|
+
resource: `action/${string}` | `service/${string}`;
|
|
167
|
+
};
|
|
168
|
+
/** A resolved service target: its manager plus the worktree it lives in. */
|
|
169
|
+
type DenvigServiceContext = {
|
|
170
|
+
manager: ServiceManager;
|
|
171
|
+
serviceName: string; /** The checkout (or global project) the service belongs to. */
|
|
172
|
+
target: ServiceManagerProject;
|
|
173
|
+
};
|
|
174
|
+
/**
|
|
175
|
+
* A project — the primary checkout plus its detached worktrees — and the entry
|
|
176
|
+
* point for the chained resource API. Everything path-sensitive is reached
|
|
177
|
+
* through the namespaces below, which act on the active worktree unless an
|
|
178
|
+
* explicit `worktree` is given.
|
|
179
|
+
*/
|
|
180
|
+
declare class DenvigProject {
|
|
181
|
+
private readonly internal;
|
|
182
|
+
private readonly ctx;
|
|
183
|
+
constructor(internal: DenvigProject$1, ctx: ResourceContext);
|
|
184
|
+
get id(): string;
|
|
185
|
+
get slug(): string;
|
|
186
|
+
get name(): string;
|
|
187
|
+
get path(): string;
|
|
188
|
+
get refs(): string[];
|
|
189
|
+
/** The checkout this project instance is currently acting on. */
|
|
190
|
+
get activeWorktree(): DenvigWorktree;
|
|
191
|
+
/** The primary checkout (`main`). */
|
|
192
|
+
get primaryWorktree(): DenvigWorktree;
|
|
193
|
+
private worktreeFor;
|
|
194
|
+
/**
|
|
195
|
+
* Select the active checkout by branch name (`main` = primary). Subsequent
|
|
196
|
+
* worktree-sensitive operations act on it. Throws if the branch is unknown.
|
|
197
|
+
*/
|
|
198
|
+
selectWorktree(branch: string): DenvigWorktree;
|
|
199
|
+
/** Build the project's info summary, including aggregate service status. */
|
|
200
|
+
info(options?: GetProjectInfoOptions): Promise<ProjectInfo>;
|
|
201
|
+
/** List the available plugins and the actions each resolves. */
|
|
202
|
+
plugins(): Promise<Record<string, PluginInfo>>;
|
|
203
|
+
/** Tear down all of the active checkout's services. */
|
|
204
|
+
teardown(options?: {
|
|
205
|
+
removeLogs?: boolean;
|
|
206
|
+
}): Promise<ProjectTeardownResult>;
|
|
207
|
+
/** Construct the canonical ID for a resource within this project. */
|
|
208
|
+
resourceId(options: ResourceIdentifierOptions): string;
|
|
209
|
+
/** Construct the canonical ID and hash for a resource within this project. */
|
|
210
|
+
resourceHash(options: ResourceIdentifierOptions): ReturnType<typeof generateDenvigResourceHash>;
|
|
211
|
+
worktrees: {
|
|
212
|
+
list: () => DenvigWorktree[];
|
|
213
|
+
retrieve: (branch: string) => DenvigWorktree;
|
|
214
|
+
};
|
|
215
|
+
actions: {
|
|
216
|
+
retrieve: (name: string, options?: ActionRetrieveOptions) => Promise<DenvigAction>;
|
|
217
|
+
};
|
|
218
|
+
services: {
|
|
219
|
+
retrieve: (name: string, options?: ServiceRetrieveOptions) => Promise<DenvigService>; /** Collect services for a scope into rendered rows. */
|
|
220
|
+
list: (options?: ListServicesOptions) => Promise<ServiceRow[]>;
|
|
221
|
+
/**
|
|
222
|
+
* Resolve a service identifier to its manager, name and target checkout.
|
|
223
|
+
* Honours cross-project identifiers (e.g. `slug/service`, `id:abcd/svc`).
|
|
224
|
+
*/
|
|
225
|
+
context: (name: string) => Promise<DenvigServiceContext>;
|
|
226
|
+
};
|
|
227
|
+
dependencies: {
|
|
228
|
+
list: () => Promise<Dependency[]>;
|
|
229
|
+
/**
|
|
230
|
+
* Build the dependency tree for the active worktree. Direct dependencies
|
|
231
|
+
* are the roots; pass `depth` to walk transitive dependencies.
|
|
232
|
+
*/
|
|
233
|
+
tree: (options?: DependenciesTreeOptions) => Promise<TreeDependencyEntry[]>;
|
|
234
|
+
/**
|
|
235
|
+
* Look up registry information for a dependency by `<ecosystem>:<name>`
|
|
236
|
+
* (e.g. `npm:redis`). Returns `null` when the package cannot be found.
|
|
237
|
+
*/
|
|
238
|
+
info: (identifier: string, options?: DependencyInfoOptions) => Promise<DependencyInfo | null>;
|
|
239
|
+
retrieve: (id: string) => Promise<Dependency>;
|
|
240
|
+
outdated: (options?: DependenciesOutdatedOptions) => Promise<OutdatedDependency[]>;
|
|
241
|
+
};
|
|
242
|
+
config: {
|
|
243
|
+
retrieve: () => Promise<ConfigWithSourcePaths<ProjectConfigSchema>>;
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
//#endregion
|
|
247
|
+
export { DenvigAction as a, DenvigService as i, ServiceRow as n, DenvigWorktree as r, DenvigProject as t };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
//#region src/lib/services/reconcile.d.ts
|
|
2
|
+
type ReconcileAction = {
|
|
3
|
+
type: 'started';
|
|
4
|
+
project: string;
|
|
5
|
+
service: string;
|
|
6
|
+
reason: string;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'stopped';
|
|
9
|
+
project: string;
|
|
10
|
+
service: string;
|
|
11
|
+
reason: string;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'restarted';
|
|
14
|
+
project: string;
|
|
15
|
+
service: string;
|
|
16
|
+
reason: string;
|
|
17
|
+
} | {
|
|
18
|
+
type: 'skipped';
|
|
19
|
+
project: string;
|
|
20
|
+
service: string;
|
|
21
|
+
reason: string;
|
|
22
|
+
};
|
|
23
|
+
type ReconcileResult = {
|
|
24
|
+
actions: ReconcileAction[];
|
|
25
|
+
errors: Array<{
|
|
26
|
+
project: string;
|
|
27
|
+
service: string;
|
|
28
|
+
message: string;
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Reconcile actual launchctl state with the desired state recorded in
|
|
33
|
+
* `~/.denvig/state.json`.
|
|
34
|
+
*
|
|
35
|
+
* Categories of action:
|
|
36
|
+
* 0. A service whose recorded checkout no longer resolves to a real
|
|
37
|
+
* project (a deleted worktree) is orphaned → bootout it, drop its plist
|
|
38
|
+
* and remove its state and gateway routes so the project that
|
|
39
|
+
* legitimately owns its domain can reclaim it.
|
|
40
|
+
* 1. State says running, launchctl agrees, plist matches → no-op.
|
|
41
|
+
* 2. State says running, but launchctl is missing the service or the
|
|
42
|
+
* plist on disk differs from what the snapshot would produce → call
|
|
43
|
+
* startService (idempotent: it only re-bootstraps when the plist
|
|
44
|
+
* content actually changed).
|
|
45
|
+
* 3. launchctl has a `denvig.*` service that state doesn't know about,
|
|
46
|
+
* or marks as `desiredStatus: stopped` → bootout it.
|
|
47
|
+
*/
|
|
48
|
+
declare const reconcileServices: () => Promise<ReconcileResult>;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { reconcileServices as n, ReconcileResult as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{X as e,c as t,d as n,h as r,i,l as a,r as o,u as s}from"./teardown-DgjT-aE7.js";import{unlink as c}from"node:fs/promises";const l=`denvig.`,u=e=>{if(!e.startsWith(l))return null;let t=e.slice(7),n=t.indexOf(`.`);return n===-1?null:{projectId:t.slice(0,n),serviceName:t.slice(n+1)}},d=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}}}},f=async()=>{let f=await t(),p=await e.list(l),m={actions:[],errors:[]},h=new Map;for(let e of p){let t=u(e.label);t&&h.set(e.label,t)}let g=new Set,_=e=>{if(!e.startsWith(`id:`))return null;let t=e.slice(3),n=t.indexOf(`:`);return n===-1?null:`${l}${t.slice(0,n)}.${t.slice(n+1)}`},v=await r(),y=new Set(v.keys());y.add((await n()).id);let b=!1;for(let[t,n]of Object.entries(f.services)){if(!n.project||!n.serviceName||y.has(n.project.id))continue;b=!0;let r=d(n),i;if(r){let e=new o(r);i=e.getServiceLabel(n.serviceName),await c(e.getPlistPath(n.serviceName)).catch(()=>{})}else i=_(t);i&&(await e.bootout(i),g.add(i)),await s(n.project.id,n.serviceName),await a(n.project.id,n.serviceName),delete f.services[t],m.actions.push({type:`stopped`,project:n.project.slug,service:n.serviceName,reason:`checkout no longer exists; removed orphaned service`})}for(let[,e]of Object.entries(f.gatewayRoutes))y.has(e.project)||(b=!0,await a(e.project,e.service));for(let[e,t]of Object.entries(f.services)){if(t.desiredStatus!==`running`)continue;let n=d(t);if(!n||!t.serviceName){let t=_(e);t&&g.add(t);continue}let r=new o(n),i=r.getServiceLabel(t.serviceName);g.add(i);try{let e=await r.startService(t.serviceName,{port:t.port,portResolved:!0,reviveIfNotRunning:!1});if(!e.success){m.errors.push({project:n.slug,service:t.serviceName,message:e.message});continue}e.message===`Service already running with current config`?m.actions.push({type:`skipped`,project:n.slug,service:t.serviceName,reason:`already running with current config`}):h.has(i)?m.actions.push({type:`restarted`,project:n.slug,service:t.serviceName,reason:`config changed since last bootstrap`}):m.actions.push({type:`started`,project:n.slug,service:t.serviceName,reason:`desiredStatus is running but service was not bootstrapped`})}catch(e){m.errors.push({project:n.slug,service:t.serviceName,message:e instanceof Error?e.message:String(e)})}}for(let t of p){if(g.has(t.label))continue;let n=await e.bootout(t.label),r=u(t.label),i=r?.projectId.slice(0,8)??`unknown`,a=r?.serviceName??t.label;n.success?m.actions.push({type:`stopped`,project:i,service:a,reason:`no matching entry in state.json`}):m.errors.push({project:i,service:a,message:`Failed to bootout: ${n.output}`})}return b&&await i(),m};export{f as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require("./teardown-DypXa0Wy.cjs");let t=require("node:fs/promises");const n=`denvig.`,r=e=>{if(!e.startsWith(n))return null;let t=e.slice(7),r=t.indexOf(`.`);return r===-1?null:{projectId:t.slice(0,r),serviceName:t.slice(r+1)}},i=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}}}},a=async()=>{let a=await e.c(),o=await e.X.list(n),s={actions:[],errors:[]},c=new Map;for(let e of o){let t=r(e.label);t&&c.set(e.label,t)}let l=new Set,u=e=>{if(!e.startsWith(`id:`))return null;let t=e.slice(3),r=t.indexOf(`:`);return r===-1?null:`${n}${t.slice(0,r)}.${t.slice(r+1)}`},d=await e.h(),f=new Set(d.keys());f.add((await e.d()).id);let p=!1;for(let[n,r]of Object.entries(a.services)){if(!r.project||!r.serviceName||f.has(r.project.id))continue;p=!0;let o=i(r),c;if(o){let n=new e.r(o);c=n.getServiceLabel(r.serviceName),await(0,t.unlink)(n.getPlistPath(r.serviceName)).catch(()=>{})}else c=u(n);c&&(await e.X.bootout(c),l.add(c)),await e.u(r.project.id,r.serviceName),await e.l(r.project.id,r.serviceName),delete a.services[n],s.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(a.gatewayRoutes))f.has(t.project)||(p=!0,await e.l(t.project,t.service));for(let[t,n]of Object.entries(a.services)){if(n.desiredStatus!==`running`)continue;let r=i(n);if(!r||!n.serviceName){let e=u(t);e&&l.add(e);continue}let a=new e.r(r),o=a.getServiceLabel(n.serviceName);l.add(o);try{let e=await a.startService(n.serviceName,{port:n.port,portResolved:!0,reviveIfNotRunning:!1});if(!e.success){s.errors.push({project:r.slug,service:n.serviceName,message:e.message});continue}e.message===`Service already running with current config`?s.actions.push({type:`skipped`,project:r.slug,service:n.serviceName,reason:`already running with current config`}):c.has(o)?s.actions.push({type:`restarted`,project:r.slug,service:n.serviceName,reason:`config changed since last bootstrap`}):s.actions.push({type:`started`,project:r.slug,service:n.serviceName,reason:`desiredStatus is running but service was not bootstrapped`})}catch(e){s.errors.push({project:r.slug,service:n.serviceName,message:e instanceof Error?e.message:String(e)})}}for(let t of o){if(l.has(t.label))continue;let n=await e.X.bootout(t.label),i=r(t.label),a=i?.projectId.slice(0,8)??`unknown`,o=i?.serviceName??t.label;n.success?s.actions.push({type:`stopped`,project:a,service:o,reason:`no matching entry in state.json`}):s.errors.push({project:a,service:o,message:`Failed to bootout: ${n.output}`})}return p&&await e.i(),s};Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return a}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
let e=require("node:fs/promises");const t=async t=>{try{return(await(0,e.readFile)(t,`utf8`)).trim()||null}catch(e){if(e&&typeof e==`object`&&`code`in e&&e.code===`ENOENT`)return null;throw e}},n=async t=>{try{return await(0,e.access)(t),!0}catch{return!1}},r=async t=>{try{return(await(0,e.stat)(t)).isDirectory()}catch{return!1}};Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return r}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{access as e,readFile as t,stat as n}from"node:fs/promises";const r=async e=>{try{return(await t(e,`utf8`)).trim()||null}catch(e){if(e&&typeof e==`object`&&`code`in e&&e.code===`ENOENT`)return null;throw e}},i=async t=>{try{return await e(t),!0}catch{return!1}},a=async e=>{try{return(await n(e)).isDirectory()}catch{return!1}};export{i as n,r,a as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=require("./chunk-CMqjfN_6.cjs");let t=require("semver");t=e.t(t,1);const n=(e,n)=>{if(e===n)return null;try{let r=t.default.diff(e,n);return r?r===`major`||r===`premajor`?`major`:r===`minor`||r===`preminor`?`minor`:r===`patch`||r===`prepatch`||r===`prerelease`?`patch`:null:null}catch{return null}},r=(e,t)=>e===null?!1:t===`patch`?e===`patch`:t===`minor`?e===`patch`||e===`minor`:t===`major`?e===`major`:!1,i=(e,t)=>r(n(e.currentVersion,e.wantedVersion),t)?!0:r(n(e.currentVersion,e.latestVersion),t);Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return n}});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"semver";const t=(t,n)=>{if(t===n)return null;try{let r=e.diff(t,n);return r?r===`major`||r===`premajor`?`major`:r===`minor`||r===`preminor`?`minor`:r===`patch`||r===`prepatch`||r===`prerelease`?`patch`:null:null}catch{return null}},n=(e,t)=>e===null?!1:t===`patch`?e===`patch`:t===`minor`?e===`patch`||e===`minor`:t===`major`?e===`major`:!1,r=(e,r)=>n(t(e.currentVersion,e.wantedVersion),r)?!0:n(t(e.currentVersion,e.latestVersion),r);export{r as n,t};
|