localdeck 1.7.0 → 1.7.1

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.
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>LocalDeck</title>
7
7
  <link rel="icon" type="image/png" href="/localdeck-icon.png" />
8
- <script type="module" crossorigin src="/assets/index-CbmaAEDy.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-2gSOxBaK.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/assets/index-DDw1Wq-H.css">
10
10
  </head>
11
11
  <body>
@@ -1,4 +1,4 @@
1
- import{$ as SO,J as IO,K as Z,L as hv,_ as aX,aa as VO,ba as PO,ra as EO}from"./index-2da1tyad.js";var Db=Z((S3)=>{Object.defineProperty(S3,"__esModule",{value:!0});S3.regexpCode=S3.getEsmExportName=S3.getProperty=S3.safeStringify=S3.stringify=S3.strConcat=S3.addCodeArg=S3.str=S3._=S3.nil=S3._Code=S3.Name=S3.IDENTIFIER=S3._CodeOrName=void 0;class HX{}S3._CodeOrName=HX;S3.IDENTIFIER=/^[a-z$_][a-z$_0-9]*$/i;class Y1 extends HX{constructor($){super();if(!S3.IDENTIFIER.test($))throw Error("CodeGen: name must be a valid identifier");this.str=$}toString(){return this.str}emptyStr(){return!1}get names(){return{[this.str]:1}}}S3.Name=Y1;class Sv extends HX{constructor($){super();this._items=typeof $==="string"?[$]:$}toString(){return this.str}emptyStr(){if(this._items.length>1)return!1;let $=this._items[0];return $===""||$==='""'}get str(){var $;return($=this._str)!==null&&$!==void 0?$:this._str=this._items.reduce((v,b)=>`${v}${b}`,"")}get names(){var $;return($=this._names)!==null&&$!==void 0?$:this._names=this._items.reduce((v,b)=>{if(b instanceof Y1)v[b.str]=(v[b.str]||0)+1;return v},{})}}S3._Code=Sv;S3.nil=new Sv("");function A3($,...v){let b=[$[0]],D=0;while(D<v.length)qY(b,v[D]),b.push($[++D]);return new Sv(b)}S3._=A3;var LY=new Sv("+");function M3($,...v){let b=[bb($[0])],D=0;while(D<v.length)b.push(LY),qY(b,v[D]),b.push(LY,bb($[++D]));return UM(b),new Sv(b)}S3.str=M3;function qY($,v){if(v instanceof Sv)$.push(...v._items);else if(v instanceof Y1)$.push(v);else $.push(JM(v))}S3.addCodeArg=qY;function UM($){let v=1;while(v<$.length-1){if($[v]===LY){let b=bM($[v-1],$[v+1]);if(b!==void 0){$.splice(v-1,3,b);continue}$[v++]="+"}v++}}function bM($,v){if(v==='""')return $;if($==='""')return v;if(typeof $=="string"){if(v instanceof Y1||$[$.length-1]!=='"')return;if(typeof v!="string")return`${$.slice(0,-1)}${v}"`;if(v[0]==='"')return $.slice(0,-1)+v.slice(1);return}if(typeof v=="string"&&v[0]==='"'&&!($ instanceof Y1))return`"${$}${v.slice(1)}`;return}function DM($,v){return v.emptyStr()?$:$.emptyStr()?v:M3`${$}${v}`}S3.strConcat=DM;function JM($){return typeof $=="number"||typeof $=="boolean"||$===null?$:bb(Array.isArray($)?$.join(","):$)}function XM($){return new Sv(bb($))}S3.stringify=XM;function bb($){return JSON.stringify($).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}S3.safeStringify=bb;function WM($){return typeof $=="string"&&S3.IDENTIFIER.test($)?new Sv(`.${$}`):A3`[${$}]`}S3.getProperty=WM;function QM($){if(typeof $=="string"&&S3.IDENTIFIER.test($))return new Sv(`${$}`);throw Error(`CodeGen: invalid export name: ${$}, use explicit $id name mapping`)}S3.getEsmExportName=QM;function GM($){return new Sv($.toString())}S3.regexpCode=GM});var AY=Z((R3)=>{Object.defineProperty(R3,"__esModule",{value:!0});R3.ValueScope=R3.ValueScopeName=R3.Scope=R3.varKinds=R3.UsedValueState=void 0;var vv=Db();class P3 extends Error{constructor($){super(`CodeGen: "code" for ${$} not defined`);this.value=$.value}}var NX;(function($){$[$.Started=0]="Started",$[$.Completed=1]="Completed"})(NX||(R3.UsedValueState=NX={}));R3.varKinds={const:new vv.Name("const"),let:new vv.Name("let"),var:new vv.Name("var")};class jY{constructor({prefixes:$,parent:v}={}){this._names={},this._prefixes=$,this._parent=v}toName($){return $ instanceof vv.Name?$:this.name($)}name($){return new vv.Name(this._newName($))}_newName($){let v=this._names[$]||this._nameGroup($);return`${$}${v.index++}`}_nameGroup($){var v,b;if(((b=(v=this._parent)===null||v===void 0?void 0:v._prefixes)===null||b===void 0?void 0:b.has($))||this._prefixes&&!this._prefixes.has($))throw Error(`CodeGen: prefix "${$}" is not allowed in this scope`);return this._names[$]={prefix:$,index:0}}}R3.Scope=jY;class FY extends vv.Name{constructor($,v){super(v);this.prefix=$}setValue($,{property:v,itemIndex:b}){this.value=$,this.scopePath=vv._`.${new vv.Name(v)}[${b}]`}}R3.ValueScopeName=FY;var FM=vv._`\n`;class E3 extends jY{constructor($){super($);this._values={},this._scope=$.scope,this.opts={...$,_n:$.lines?FM:vv.nil}}get(){return this._scope}name($){return new FY($,this._newName($))}value($,v){var b;if(v.ref===void 0)throw Error("CodeGen: ref must be passed in value");let D=this.toName($),{prefix:U}=D,J=(b=v.key)!==null&&b!==void 0?b:v.ref,X=this._values[U];if(X){let G=X.get(J);if(G)return G}else X=this._values[U]=new Map;X.set(J,D);let W=this._scope[U]||(this._scope[U]=[]),Q=W.length;return W[Q]=v.ref,D.setValue(v,{property:U,itemIndex:Q}),D}getValue($,v){let b=this._values[$];if(!b)return;return b.get(v)}scopeRefs($,v=this._values){return this._reduceValues(v,(b)=>{if(b.scopePath===void 0)throw Error(`CodeGen: name "${b}" has no value`);return vv._`${$}${b.scopePath}`})}scopeCode($=this._values,v,b){return this._reduceValues($,(D)=>{if(D.value===void 0)throw Error(`CodeGen: name "${D}" has no value`);return D.value.code},v,b)}_reduceValues($,v,b={},D){let U=vv.nil;for(let J in $){let X=$[J];if(!X)continue;let W=b[J]=b[J]||new Map;X.forEach((Q)=>{if(W.has(Q))return;W.set(Q,NX.Started);let G=v(Q);if(G){let Y=this.opts.es5?R3.varKinds.var:R3.varKinds.const;U=vv._`${U}${Y} ${Q} = ${G};${this.opts._n}`}else if(G=D===null||D===void 0?void 0:D(Q))U=vv._`${U}${G}${this.opts._n}`;else throw new P3(Q);W.set(Q,NX.Completed)})}return U}}R3.ValueScope=E3});var a=Z((Uv)=>{Object.defineProperty(Uv,"__esModule",{value:!0});Uv.or=Uv.and=Uv.not=Uv.CodeGen=Uv.operators=Uv.varKinds=Uv.ValueScopeName=Uv.ValueScope=Uv.Scope=Uv.Name=Uv.regexpCode=Uv.stringify=Uv.getProperty=Uv.nil=Uv.strConcat=Uv.str=Uv._=void 0;var D$=Db(),Vv=AY(),A6=Db();Object.defineProperty(Uv,"_",{enumerable:!0,get:function(){return A6._}});Object.defineProperty(Uv,"str",{enumerable:!0,get:function(){return A6.str}});Object.defineProperty(Uv,"strConcat",{enumerable:!0,get:function(){return A6.strConcat}});Object.defineProperty(Uv,"nil",{enumerable:!0,get:function(){return A6.nil}});Object.defineProperty(Uv,"getProperty",{enumerable:!0,get:function(){return A6.getProperty}});Object.defineProperty(Uv,"stringify",{enumerable:!0,get:function(){return A6.stringify}});Object.defineProperty(Uv,"regexpCode",{enumerable:!0,get:function(){return A6.regexpCode}});Object.defineProperty(Uv,"Name",{enumerable:!0,get:function(){return A6.Name}});var jX=AY();Object.defineProperty(Uv,"Scope",{enumerable:!0,get:function(){return jX.Scope}});Object.defineProperty(Uv,"ValueScope",{enumerable:!0,get:function(){return jX.ValueScope}});Object.defineProperty(Uv,"ValueScopeName",{enumerable:!0,get:function(){return jX.ValueScopeName}});Object.defineProperty(Uv,"varKinds",{enumerable:!0,get:function(){return jX.varKinds}});Uv.operators={GT:new D$._Code(">"),GTE:new D$._Code(">="),LT:new D$._Code("<"),LTE:new D$._Code("<="),EQ:new D$._Code("==="),NEQ:new D$._Code("!=="),NOT:new D$._Code("!"),OR:new D$._Code("||"),AND:new D$._Code("&&"),ADD:new D$._Code("+")};class M6{optimizeNodes(){return this}optimizeNames($,v){return this}}class _3 extends M6{constructor($,v,b){super();this.varKind=$,this.name=v,this.rhs=b}render({es5:$,_n:v}){let b=$?Vv.varKinds.var:this.varKind,D=this.rhs===void 0?"":` = ${this.rhs}`;return`${b} ${this.name}${D};`+v}optimizeNames($,v){if(!$[this.name.str])return;if(this.rhs)this.rhs=I1(this.rhs,$,v);return this}get names(){return this.rhs instanceof D$._CodeOrName?this.rhs.names:{}}}class VY extends M6{constructor($,v,b){super();this.lhs=$,this.rhs=v,this.sideEffects=b}render({_n:$}){return`${this.lhs} = ${this.rhs};`+$}optimizeNames($,v){if(this.lhs instanceof D$.Name&&!$[this.lhs.str]&&!this.sideEffects)return;return this.rhs=I1(this.rhs,$,v),this}get names(){let $=this.lhs instanceof D$.Name?{}:{...this.lhs.names};return KX($,this.rhs)}}class g3 extends VY{constructor($,v,b,D){super($,b,D);this.op=v}render({_n:$}){return`${this.lhs} ${this.op}= ${this.rhs};`+$}}class T3 extends M6{constructor($){super();this.label=$,this.names={}}render({_n:$}){return`${this.label}:`+$}}class Z3 extends M6{constructor($){super();this.label=$,this.names={}}render({_n:$}){return`break${this.label?` ${this.label}`:""};`+$}}class C3 extends M6{constructor($){super();this.error=$}render({_n:$}){return`throw ${this.error};`+$}get names(){return this.error.names}}class f3 extends M6{constructor($){super();this.code=$}render({_n:$}){return`${this.code};`+$}optimizeNodes(){return`${this.code}`?this:void 0}optimizeNames($,v){return this.code=I1(this.code,$,v),this}get names(){return this.code instanceof D$._CodeOrName?this.code.names:{}}}class FX extends M6{constructor($=[]){super();this.nodes=$}render($){return this.nodes.reduce((v,b)=>v+b.render($),"")}optimizeNodes(){let{nodes:$}=this,v=$.length;while(v--){let b=$[v].optimizeNodes();if(Array.isArray(b))$.splice(v,1,...b);else if(b)$[v]=b;else $.splice(v,1)}return $.length>0?this:void 0}optimizeNames($,v){let{nodes:b}=this,D=b.length;while(D--){let U=b[D];if(U.optimizeNames($,v))continue;VM($,U.names),b.splice(D,1)}return b.length>0?this:void 0}get names(){return this.nodes.reduce(($,v)=>$4($,v.names),{})}}class S6 extends FX{render($){return"{"+$._n+super.render($)+"}"+$._n}}class x3 extends FX{}class Jb extends S6{}Jb.kind="else";class av extends S6{constructor($,v){super(v);this.condition=$}render($){let v=`if(${this.condition})`+super.render($);if(this.else)v+="else "+this.else.render($);return v}optimizeNodes(){super.optimizeNodes();let $=this.condition;if($===!0)return this.nodes;let v=this.else;if(v){let b=v.optimizeNodes();v=this.else=Array.isArray(b)?new Jb(b):b}if(v){if($===!1)return v instanceof av?v:v.nodes;if(this.nodes.length)return this;return new av(i3($),v instanceof av?[v]:v.nodes)}if($===!1||!this.nodes.length)return;return this}optimizeNames($,v){var b;if(this.else=(b=this.else)===null||b===void 0?void 0:b.optimizeNames($,v),!(super.optimizeNames($,v)||this.else))return;return this.condition=I1(this.condition,$,v),this}get names(){let $=super.names;if(KX($,this.condition),this.else)$4($,this.else.names);return $}}av.kind="if";class z1 extends S6{}z1.kind="for";class y3 extends z1{constructor($){super();this.iteration=$}render($){return`for(${this.iteration})`+super.render($)}optimizeNames($,v){if(!super.optimizeNames($,v))return;return this.iteration=I1(this.iteration,$,v),this}get names(){return $4(super.names,this.iteration.names)}}class l3 extends z1{constructor($,v,b,D){super();this.varKind=$,this.name=v,this.from=b,this.to=D}render($){let v=$.es5?Vv.varKinds.var:this.varKind,{name:b,from:D,to:U}=this;return`for(${v} ${b}=${D}; ${b}<${U}; ${b}++)`+super.render($)}get names(){let $=KX(super.names,this.from);return KX($,this.to)}}class MY extends z1{constructor($,v,b,D){super();this.loop=$,this.varKind=v,this.name=b,this.iterable=D}render($){return`for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})`+super.render($)}optimizeNames($,v){if(!super.optimizeNames($,v))return;return this.iterable=I1(this.iterable,$,v),this}get names(){return $4(super.names,this.iterable.names)}}class wX extends S6{constructor($,v,b){super();this.name=$,this.args=v,this.async=b}render($){return`${this.async?"async ":""}function ${this.name}(${this.args})`+super.render($)}}wX.kind="func";class OX extends FX{render($){return"return "+super.render($)}}OX.kind="return";class u3 extends S6{render($){let v="try"+super.render($);if(this.catch)v+=this.catch.render($);if(this.finally)v+=this.finally.render($);return v}optimizeNodes(){var $,v;return super.optimizeNodes(),($=this.catch)===null||$===void 0||$.optimizeNodes(),(v=this.finally)===null||v===void 0||v.optimizeNodes(),this}optimizeNames($,v){var b,D;return super.optimizeNames($,v),(b=this.catch)===null||b===void 0||b.optimizeNames($,v),(D=this.finally)===null||D===void 0||D.optimizeNames($,v),this}get names(){let $=super.names;if(this.catch)$4($,this.catch.names);if(this.finally)$4($,this.finally.names);return $}}class LX extends S6{constructor($){super();this.error=$}render($){return`catch(${this.error})`+super.render($)}}LX.kind="catch";class qX extends S6{render($){return"finally"+super.render($)}}qX.kind="finally";class n3{constructor($,v={}){this._values={},this._blockStarts=[],this._constants={},this.opts={...v,_n:v.lines?`
1
+ import{$ as SO,J as IO,K as Z,L as hv,_ as aX,aa as VO,ba as PO,ra as EO}from"./index-scnd2pq4.js";var Db=Z((S3)=>{Object.defineProperty(S3,"__esModule",{value:!0});S3.regexpCode=S3.getEsmExportName=S3.getProperty=S3.safeStringify=S3.stringify=S3.strConcat=S3.addCodeArg=S3.str=S3._=S3.nil=S3._Code=S3.Name=S3.IDENTIFIER=S3._CodeOrName=void 0;class HX{}S3._CodeOrName=HX;S3.IDENTIFIER=/^[a-z$_][a-z$_0-9]*$/i;class Y1 extends HX{constructor($){super();if(!S3.IDENTIFIER.test($))throw Error("CodeGen: name must be a valid identifier");this.str=$}toString(){return this.str}emptyStr(){return!1}get names(){return{[this.str]:1}}}S3.Name=Y1;class Sv extends HX{constructor($){super();this._items=typeof $==="string"?[$]:$}toString(){return this.str}emptyStr(){if(this._items.length>1)return!1;let $=this._items[0];return $===""||$==='""'}get str(){var $;return($=this._str)!==null&&$!==void 0?$:this._str=this._items.reduce((v,b)=>`${v}${b}`,"")}get names(){var $;return($=this._names)!==null&&$!==void 0?$:this._names=this._items.reduce((v,b)=>{if(b instanceof Y1)v[b.str]=(v[b.str]||0)+1;return v},{})}}S3._Code=Sv;S3.nil=new Sv("");function A3($,...v){let b=[$[0]],D=0;while(D<v.length)qY(b,v[D]),b.push($[++D]);return new Sv(b)}S3._=A3;var LY=new Sv("+");function M3($,...v){let b=[bb($[0])],D=0;while(D<v.length)b.push(LY),qY(b,v[D]),b.push(LY,bb($[++D]));return UM(b),new Sv(b)}S3.str=M3;function qY($,v){if(v instanceof Sv)$.push(...v._items);else if(v instanceof Y1)$.push(v);else $.push(JM(v))}S3.addCodeArg=qY;function UM($){let v=1;while(v<$.length-1){if($[v]===LY){let b=bM($[v-1],$[v+1]);if(b!==void 0){$.splice(v-1,3,b);continue}$[v++]="+"}v++}}function bM($,v){if(v==='""')return $;if($==='""')return v;if(typeof $=="string"){if(v instanceof Y1||$[$.length-1]!=='"')return;if(typeof v!="string")return`${$.slice(0,-1)}${v}"`;if(v[0]==='"')return $.slice(0,-1)+v.slice(1);return}if(typeof v=="string"&&v[0]==='"'&&!($ instanceof Y1))return`"${$}${v.slice(1)}`;return}function DM($,v){return v.emptyStr()?$:$.emptyStr()?v:M3`${$}${v}`}S3.strConcat=DM;function JM($){return typeof $=="number"||typeof $=="boolean"||$===null?$:bb(Array.isArray($)?$.join(","):$)}function XM($){return new Sv(bb($))}S3.stringify=XM;function bb($){return JSON.stringify($).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")}S3.safeStringify=bb;function WM($){return typeof $=="string"&&S3.IDENTIFIER.test($)?new Sv(`.${$}`):A3`[${$}]`}S3.getProperty=WM;function QM($){if(typeof $=="string"&&S3.IDENTIFIER.test($))return new Sv(`${$}`);throw Error(`CodeGen: invalid export name: ${$}, use explicit $id name mapping`)}S3.getEsmExportName=QM;function GM($){return new Sv($.toString())}S3.regexpCode=GM});var AY=Z((R3)=>{Object.defineProperty(R3,"__esModule",{value:!0});R3.ValueScope=R3.ValueScopeName=R3.Scope=R3.varKinds=R3.UsedValueState=void 0;var vv=Db();class P3 extends Error{constructor($){super(`CodeGen: "code" for ${$} not defined`);this.value=$.value}}var NX;(function($){$[$.Started=0]="Started",$[$.Completed=1]="Completed"})(NX||(R3.UsedValueState=NX={}));R3.varKinds={const:new vv.Name("const"),let:new vv.Name("let"),var:new vv.Name("var")};class jY{constructor({prefixes:$,parent:v}={}){this._names={},this._prefixes=$,this._parent=v}toName($){return $ instanceof vv.Name?$:this.name($)}name($){return new vv.Name(this._newName($))}_newName($){let v=this._names[$]||this._nameGroup($);return`${$}${v.index++}`}_nameGroup($){var v,b;if(((b=(v=this._parent)===null||v===void 0?void 0:v._prefixes)===null||b===void 0?void 0:b.has($))||this._prefixes&&!this._prefixes.has($))throw Error(`CodeGen: prefix "${$}" is not allowed in this scope`);return this._names[$]={prefix:$,index:0}}}R3.Scope=jY;class FY extends vv.Name{constructor($,v){super(v);this.prefix=$}setValue($,{property:v,itemIndex:b}){this.value=$,this.scopePath=vv._`.${new vv.Name(v)}[${b}]`}}R3.ValueScopeName=FY;var FM=vv._`\n`;class E3 extends jY{constructor($){super($);this._values={},this._scope=$.scope,this.opts={...$,_n:$.lines?FM:vv.nil}}get(){return this._scope}name($){return new FY($,this._newName($))}value($,v){var b;if(v.ref===void 0)throw Error("CodeGen: ref must be passed in value");let D=this.toName($),{prefix:U}=D,J=(b=v.key)!==null&&b!==void 0?b:v.ref,X=this._values[U];if(X){let G=X.get(J);if(G)return G}else X=this._values[U]=new Map;X.set(J,D);let W=this._scope[U]||(this._scope[U]=[]),Q=W.length;return W[Q]=v.ref,D.setValue(v,{property:U,itemIndex:Q}),D}getValue($,v){let b=this._values[$];if(!b)return;return b.get(v)}scopeRefs($,v=this._values){return this._reduceValues(v,(b)=>{if(b.scopePath===void 0)throw Error(`CodeGen: name "${b}" has no value`);return vv._`${$}${b.scopePath}`})}scopeCode($=this._values,v,b){return this._reduceValues($,(D)=>{if(D.value===void 0)throw Error(`CodeGen: name "${D}" has no value`);return D.value.code},v,b)}_reduceValues($,v,b={},D){let U=vv.nil;for(let J in $){let X=$[J];if(!X)continue;let W=b[J]=b[J]||new Map;X.forEach((Q)=>{if(W.has(Q))return;W.set(Q,NX.Started);let G=v(Q);if(G){let Y=this.opts.es5?R3.varKinds.var:R3.varKinds.const;U=vv._`${U}${Y} ${Q} = ${G};${this.opts._n}`}else if(G=D===null||D===void 0?void 0:D(Q))U=vv._`${U}${G}${this.opts._n}`;else throw new P3(Q);W.set(Q,NX.Completed)})}return U}}R3.ValueScope=E3});var a=Z((Uv)=>{Object.defineProperty(Uv,"__esModule",{value:!0});Uv.or=Uv.and=Uv.not=Uv.CodeGen=Uv.operators=Uv.varKinds=Uv.ValueScopeName=Uv.ValueScope=Uv.Scope=Uv.Name=Uv.regexpCode=Uv.stringify=Uv.getProperty=Uv.nil=Uv.strConcat=Uv.str=Uv._=void 0;var D$=Db(),Vv=AY(),A6=Db();Object.defineProperty(Uv,"_",{enumerable:!0,get:function(){return A6._}});Object.defineProperty(Uv,"str",{enumerable:!0,get:function(){return A6.str}});Object.defineProperty(Uv,"strConcat",{enumerable:!0,get:function(){return A6.strConcat}});Object.defineProperty(Uv,"nil",{enumerable:!0,get:function(){return A6.nil}});Object.defineProperty(Uv,"getProperty",{enumerable:!0,get:function(){return A6.getProperty}});Object.defineProperty(Uv,"stringify",{enumerable:!0,get:function(){return A6.stringify}});Object.defineProperty(Uv,"regexpCode",{enumerable:!0,get:function(){return A6.regexpCode}});Object.defineProperty(Uv,"Name",{enumerable:!0,get:function(){return A6.Name}});var jX=AY();Object.defineProperty(Uv,"Scope",{enumerable:!0,get:function(){return jX.Scope}});Object.defineProperty(Uv,"ValueScope",{enumerable:!0,get:function(){return jX.ValueScope}});Object.defineProperty(Uv,"ValueScopeName",{enumerable:!0,get:function(){return jX.ValueScopeName}});Object.defineProperty(Uv,"varKinds",{enumerable:!0,get:function(){return jX.varKinds}});Uv.operators={GT:new D$._Code(">"),GTE:new D$._Code(">="),LT:new D$._Code("<"),LTE:new D$._Code("<="),EQ:new D$._Code("==="),NEQ:new D$._Code("!=="),NOT:new D$._Code("!"),OR:new D$._Code("||"),AND:new D$._Code("&&"),ADD:new D$._Code("+")};class M6{optimizeNodes(){return this}optimizeNames($,v){return this}}class _3 extends M6{constructor($,v,b){super();this.varKind=$,this.name=v,this.rhs=b}render({es5:$,_n:v}){let b=$?Vv.varKinds.var:this.varKind,D=this.rhs===void 0?"":` = ${this.rhs}`;return`${b} ${this.name}${D};`+v}optimizeNames($,v){if(!$[this.name.str])return;if(this.rhs)this.rhs=I1(this.rhs,$,v);return this}get names(){return this.rhs instanceof D$._CodeOrName?this.rhs.names:{}}}class VY extends M6{constructor($,v,b){super();this.lhs=$,this.rhs=v,this.sideEffects=b}render({_n:$}){return`${this.lhs} = ${this.rhs};`+$}optimizeNames($,v){if(this.lhs instanceof D$.Name&&!$[this.lhs.str]&&!this.sideEffects)return;return this.rhs=I1(this.rhs,$,v),this}get names(){let $=this.lhs instanceof D$.Name?{}:{...this.lhs.names};return KX($,this.rhs)}}class g3 extends VY{constructor($,v,b,D){super($,b,D);this.op=v}render({_n:$}){return`${this.lhs} ${this.op}= ${this.rhs};`+$}}class T3 extends M6{constructor($){super();this.label=$,this.names={}}render({_n:$}){return`${this.label}:`+$}}class Z3 extends M6{constructor($){super();this.label=$,this.names={}}render({_n:$}){return`break${this.label?` ${this.label}`:""};`+$}}class C3 extends M6{constructor($){super();this.error=$}render({_n:$}){return`throw ${this.error};`+$}get names(){return this.error.names}}class f3 extends M6{constructor($){super();this.code=$}render({_n:$}){return`${this.code};`+$}optimizeNodes(){return`${this.code}`?this:void 0}optimizeNames($,v){return this.code=I1(this.code,$,v),this}get names(){return this.code instanceof D$._CodeOrName?this.code.names:{}}}class FX extends M6{constructor($=[]){super();this.nodes=$}render($){return this.nodes.reduce((v,b)=>v+b.render($),"")}optimizeNodes(){let{nodes:$}=this,v=$.length;while(v--){let b=$[v].optimizeNodes();if(Array.isArray(b))$.splice(v,1,...b);else if(b)$[v]=b;else $.splice(v,1)}return $.length>0?this:void 0}optimizeNames($,v){let{nodes:b}=this,D=b.length;while(D--){let U=b[D];if(U.optimizeNames($,v))continue;VM($,U.names),b.splice(D,1)}return b.length>0?this:void 0}get names(){return this.nodes.reduce(($,v)=>$4($,v.names),{})}}class S6 extends FX{render($){return"{"+$._n+super.render($)+"}"+$._n}}class x3 extends FX{}class Jb extends S6{}Jb.kind="else";class av extends S6{constructor($,v){super(v);this.condition=$}render($){let v=`if(${this.condition})`+super.render($);if(this.else)v+="else "+this.else.render($);return v}optimizeNodes(){super.optimizeNodes();let $=this.condition;if($===!0)return this.nodes;let v=this.else;if(v){let b=v.optimizeNodes();v=this.else=Array.isArray(b)?new Jb(b):b}if(v){if($===!1)return v instanceof av?v:v.nodes;if(this.nodes.length)return this;return new av(i3($),v instanceof av?[v]:v.nodes)}if($===!1||!this.nodes.length)return;return this}optimizeNames($,v){var b;if(this.else=(b=this.else)===null||b===void 0?void 0:b.optimizeNames($,v),!(super.optimizeNames($,v)||this.else))return;return this.condition=I1(this.condition,$,v),this}get names(){let $=super.names;if(KX($,this.condition),this.else)$4($,this.else.names);return $}}av.kind="if";class z1 extends S6{}z1.kind="for";class y3 extends z1{constructor($){super();this.iteration=$}render($){return`for(${this.iteration})`+super.render($)}optimizeNames($,v){if(!super.optimizeNames($,v))return;return this.iteration=I1(this.iteration,$,v),this}get names(){return $4(super.names,this.iteration.names)}}class l3 extends z1{constructor($,v,b,D){super();this.varKind=$,this.name=v,this.from=b,this.to=D}render($){let v=$.es5?Vv.varKinds.var:this.varKind,{name:b,from:D,to:U}=this;return`for(${v} ${b}=${D}; ${b}<${U}; ${b}++)`+super.render($)}get names(){let $=KX(super.names,this.from);return KX($,this.to)}}class MY extends z1{constructor($,v,b,D){super();this.loop=$,this.varKind=v,this.name=b,this.iterable=D}render($){return`for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})`+super.render($)}optimizeNames($,v){if(!super.optimizeNames($,v))return;return this.iterable=I1(this.iterable,$,v),this}get names(){return $4(super.names,this.iterable.names)}}class wX extends S6{constructor($,v,b){super();this.name=$,this.args=v,this.async=b}render($){return`${this.async?"async ":""}function ${this.name}(${this.args})`+super.render($)}}wX.kind="func";class OX extends FX{render($){return"return "+super.render($)}}OX.kind="return";class u3 extends S6{render($){let v="try"+super.render($);if(this.catch)v+=this.catch.render($);if(this.finally)v+=this.finally.render($);return v}optimizeNodes(){var $,v;return super.optimizeNodes(),($=this.catch)===null||$===void 0||$.optimizeNodes(),(v=this.finally)===null||v===void 0||v.optimizeNodes(),this}optimizeNames($,v){var b,D;return super.optimizeNames($,v),(b=this.catch)===null||b===void 0||b.optimizeNames($,v),(D=this.finally)===null||D===void 0||D.optimizeNames($,v),this}get names(){let $=super.names;if(this.catch)$4($,this.catch.names);if(this.finally)$4($,this.finally.names);return $}}class LX extends S6{constructor($){super();this.error=$}render($){return`catch(${this.error})`+super.render($)}}LX.kind="catch";class qX extends S6{render($){return"finally"+super.render($)}}qX.kind="finally";class n3{constructor($,v={}){this._values={},this._blockStarts=[],this._constants={},this.opts={...v,_n:v.lines?`
2
2
  `:""},this._extScope=$,this._scope=new Vv.Scope({parent:$}),this._nodes=[new x3]}toString(){return this._root.render(this.opts)}name($){return this._scope.name($)}scopeName($){return this._extScope.name($)}scopeValue($,v){let b=this._extScope.value($,v);return(this._values[b.prefix]||(this._values[b.prefix]=new Set)).add(b),b}getScopeValue($,v){return this._extScope.getValue($,v)}scopeRefs($){return this._extScope.scopeRefs($,this._values)}scopeCode(){return this._extScope.scopeCode(this._values)}_def($,v,b,D){let U=this._scope.toName(v);if(b!==void 0&&D)this._constants[U.str]=b;return this._leafNode(new _3($,U,b)),U}const($,v,b){return this._def(Vv.varKinds.const,$,v,b)}let($,v,b){return this._def(Vv.varKinds.let,$,v,b)}var($,v,b){return this._def(Vv.varKinds.var,$,v,b)}assign($,v,b){return this._leafNode(new VY($,v,b))}add($,v){return this._leafNode(new g3($,Uv.operators.ADD,v))}code($){if(typeof $=="function")$();else if($!==D$.nil)this._leafNode(new f3($));return this}object(...$){let v=["{"];for(let[b,D]of $){if(v.length>1)v.push(",");if(v.push(b),b!==D||this.opts.es5)v.push(":"),(0,D$.addCodeArg)(v,D)}return v.push("}"),new D$._Code(v)}if($,v,b){if(this._blockNode(new av($)),v&&b)this.code(v).else().code(b).endIf();else if(v)this.code(v).endIf();else if(b)throw Error('CodeGen: "else" body without "then" body');return this}elseIf($){return this._elseNode(new av($))}else(){return this._elseNode(new Jb)}endIf(){return this._endBlockNode(av,Jb)}_for($,v){if(this._blockNode($),v)this.code(v).endFor();return this}for($,v){return this._for(new y3($),v)}forRange($,v,b,D,U=this.opts.es5?Vv.varKinds.var:Vv.varKinds.let){let J=this._scope.toName($);return this._for(new l3(U,J,v,b),()=>D(J))}forOf($,v,b,D=Vv.varKinds.const){let U=this._scope.toName($);if(this.opts.es5){let J=v instanceof D$.Name?v:this.var("_arr",v);return this.forRange("_i",0,D$._`${J}.length`,(X)=>{this.var(U,D$._`${J}[${X}]`),b(U)})}return this._for(new MY("of",D,U,v),()=>b(U))}forIn($,v,b,D=this.opts.es5?Vv.varKinds.var:Vv.varKinds.const){if(this.opts.ownProperties)return this.forOf($,D$._`Object.keys(${v})`,b);let U=this._scope.toName($);return this._for(new MY("in",D,U,v),()=>b(U))}endFor(){return this._endBlockNode(z1)}label($){return this._leafNode(new T3($))}break($){return this._leafNode(new Z3($))}return($){let v=new OX;if(this._blockNode(v),this.code($),v.nodes.length!==1)throw Error('CodeGen: "return" should have one node');return this._endBlockNode(OX)}try($,v,b){if(!v&&!b)throw Error('CodeGen: "try" without "catch" and "finally"');let D=new u3;if(this._blockNode(D),this.code($),v){let U=this.name("e");this._currNode=D.catch=new LX(U),v(U)}if(b)this._currNode=D.finally=new qX,this.code(b);return this._endBlockNode(LX,qX)}throw($){return this._leafNode(new C3($))}block($,v){if(this._blockStarts.push(this._nodes.length),$)this.code($).endBlock(v);return this}endBlock($){let v=this._blockStarts.pop();if(v===void 0)throw Error("CodeGen: not in self-balancing block");let b=this._nodes.length-v;if(b<0||$!==void 0&&b!==$)throw Error(`CodeGen: wrong number of nodes: ${b} vs ${$} expected`);return this._nodes.length=v,this}func($,v=D$.nil,b,D){if(this._blockNode(new wX($,v,b)),D)this.code(D).endFunc();return this}endFunc(){return this._endBlockNode(wX)}optimize($=1){while($-- >0)this._root.optimizeNodes(),this._root.optimizeNames(this._root.names,this._constants)}_leafNode($){return this._currNode.nodes.push($),this}_blockNode($){this._currNode.nodes.push($),this._nodes.push($)}_endBlockNode($,v){let b=this._currNode;if(b instanceof $||v&&b instanceof v)return this._nodes.pop(),this;throw Error(`CodeGen: not in block "${v?`${$.kind}/${v.kind}`:$.kind}"`)}_elseNode($){let v=this._currNode;if(!(v instanceof av))throw Error('CodeGen: "else" without "if"');return this._currNode=v.else=$,this}get _root(){return this._nodes[0]}get _currNode(){let $=this._nodes;return $[$.length-1]}set _currNode($){let v=this._nodes;v[v.length-1]=$}}Uv.CodeGen=n3;function $4($,v){for(let b in v)$[b]=($[b]||0)+(v[b]||0);return $}function KX($,v){return v instanceof D$._CodeOrName?$4($,v.names):$}function I1($,v,b){if($ instanceof D$.Name)return D($);if(!U($))return $;return new D$._Code($._items.reduce((J,X)=>{if(X instanceof D$.Name)X=D(X);if(X instanceof D$._Code)J.push(...X._items);else J.push(X);return J},[]));function D(J){let X=b[J.str];if(X===void 0||v[J.str]!==1)return J;return delete v[J.str],X}function U(J){return J instanceof D$._Code&&J._items.some((X)=>X instanceof D$.Name&&v[X.str]===1&&b[X.str]!==void 0)}}function VM($,v){for(let b in v)$[b]=($[b]||0)-(v[b]||0)}function i3($){return typeof $=="boolean"||typeof $=="number"||$===null?!$:D$._`!${SY($)}`}Uv.not=i3;var PM=h3(Uv.operators.AND);function EM(...$){return $.reduce(PM)}Uv.and=EM;var RM=h3(Uv.operators.OR);function kM(...$){return $.reduce(RM)}Uv.or=kM;function h3($){return(v,b)=>v===D$.nil?b:b===D$.nil?v:D$._`${SY(v)} ${$} ${SY(b)}`}function SY($){return $ instanceof D$.Name?$:D$._`(${$})`}});var J$=Z((e3)=>{Object.defineProperty(e3,"__esModule",{value:!0});e3.checkStrictMode=e3.getErrorPath=e3.Type=e3.useFunc=e3.setEvaluated=e3.evaluatedPropsToName=e3.mergeEvaluated=e3.eachItem=e3.unescapeJsonPointer=e3.escapeJsonPointer=e3.escapeFragment=e3.unescapeFragment=e3.schemaRefOrVal=e3.schemaHasRulesButRef=e3.schemaHasRules=e3.checkUnknownRules=e3.alwaysValidSchema=e3.toHash=void 0;var O$=a(),ZM=Db();function CM($){let v={};for(let b of $)v[b]=!0;return v}e3.toHash=CM;function fM($,v){if(typeof v=="boolean")return v;if(Object.keys(v).length===0)return!0;return d3($,v),!c3(v,$.self.RULES.all)}e3.alwaysValidSchema=fM;function d3($,v=$.schema){let{opts:b,self:D}=$;if(!b.strictSchema)return;if(typeof v==="boolean")return;let U=D.RULES.keywords;for(let J in v)if(!U[J])a3($,`unknown keyword: "${J}"`)}e3.checkUnknownRules=d3;function c3($,v){if(typeof $=="boolean")return!$;for(let b in $)if(v[b])return!0;return!1}e3.schemaHasRules=c3;function xM($,v){if(typeof $=="boolean")return!$;for(let b in $)if(b!=="$ref"&&v.all[b])return!0;return!1}e3.schemaHasRulesButRef=xM;function yM({topSchemaRef:$,schemaPath:v},b,D,U){if(!U){if(typeof b=="number"||typeof b=="boolean")return b;if(typeof b=="string")return O$._`${b}`}return O$._`${$}${v}${(0,O$.getProperty)(D)}`}e3.schemaRefOrVal=yM;function lM($){return o3(decodeURIComponent($))}e3.unescapeFragment=lM;function uM($){return encodeURIComponent(EY($))}e3.escapeFragment=uM;function EY($){if(typeof $=="number")return`${$}`;return $.replace(/~/g,"~0").replace(/\//g,"~1")}e3.escapeJsonPointer=EY;function o3($){return $.replace(/~1/g,"/").replace(/~0/g,"~")}e3.unescapeJsonPointer=o3;function nM($,v){if(Array.isArray($))for(let b of $)v(b);else v($)}e3.eachItem=nM;function r3({mergeNames:$,mergeToName:v,mergeValues:b,resultToName:D}){return(U,J,X,W)=>{let Q=X===void 0?J:X instanceof O$.Name?(J instanceof O$.Name?$(U,J,X):v(U,J,X),X):J instanceof O$.Name?(v(U,X,J),J):b(J,X);return W===O$.Name&&!(Q instanceof O$.Name)?D(U,Q):Q}}e3.mergeEvaluated={props:r3({mergeNames:($,v,b)=>$.if(O$._`${b} !== true && ${v} !== undefined`,()=>{$.if(O$._`${v} === true`,()=>$.assign(b,!0),()=>$.assign(b,O$._`${b} || {}`).code(O$._`Object.assign(${b}, ${v})`))}),mergeToName:($,v,b)=>$.if(O$._`${b} !== true`,()=>{if(v===!0)$.assign(b,!0);else $.assign(b,O$._`${b} || {}`),RY($,b,v)}),mergeValues:($,v)=>$===!0?!0:{...$,...v},resultToName:t3}),items:r3({mergeNames:($,v,b)=>$.if(O$._`${b} !== true && ${v} !== undefined`,()=>$.assign(b,O$._`${v} === true ? true : ${b} > ${v} ? ${b} : ${v}`)),mergeToName:($,v,b)=>$.if(O$._`${b} !== true`,()=>$.assign(b,v===!0?!0:O$._`${b} > ${v} ? ${b} : ${v}`)),mergeValues:($,v)=>$===!0?!0:Math.max($,v),resultToName:($,v)=>$.var("items",v)})};function t3($,v){if(v===!0)return $.var("props",!0);let b=$.var("props",O$._`{}`);if(v!==void 0)RY($,b,v);return b}e3.evaluatedPropsToName=t3;function RY($,v,b){Object.keys(b).forEach((D)=>$.assign(O$._`${v}${(0,O$.getProperty)(D)}`,!0))}e3.setEvaluated=RY;var p3={};function iM($,v){return $.scopeValue("func",{ref:v,code:p3[v.code]||(p3[v.code]=new ZM._Code(v.code))})}e3.useFunc=iM;var PY;(function($){$[$.Num=0]="Num",$[$.Str=1]="Str"})(PY||(e3.Type=PY={}));function hM($,v,b){if($ instanceof O$.Name){let D=v===PY.Num;return b?D?O$._`"[" + ${$} + "]"`:O$._`"['" + ${$} + "']"`:D?O$._`"/" + ${$}`:O$._`"/" + ${$}.replace(/~/g, "~0").replace(/\\//g, "~1")`}return b?(0,O$.getProperty)($).toString():"/"+EY($)}e3.getErrorPath=hM;function a3($,v,b=$.opts.strictSchema){if(!b)return;if(v=`strict mode: ${v}`,b===!0)throw Error(v);$.self.logger.warn(v)}e3.checkStrictMode=a3});var ev=Z(($H)=>{Object.defineProperty($H,"__esModule",{value:!0});var u$=a(),WS={data:new u$.Name("data"),valCxt:new u$.Name("valCxt"),instancePath:new u$.Name("instancePath"),parentData:new u$.Name("parentData"),parentDataProperty:new u$.Name("parentDataProperty"),rootData:new u$.Name("rootData"),dynamicAnchors:new u$.Name("dynamicAnchors"),vErrors:new u$.Name("vErrors"),errors:new u$.Name("errors"),this:new u$.Name("this"),self:new u$.Name("self"),scope:new u$.Name("scope"),json:new u$.Name("json"),jsonPos:new u$.Name("jsonPos"),jsonLen:new u$.Name("jsonLen"),jsonPart:new u$.Name("jsonPart")};$H.default=WS});var Xb=Z((DH)=>{Object.defineProperty(DH,"__esModule",{value:!0});DH.extendErrors=DH.resetErrorsCount=DH.reportExtraError=DH.reportError=DH.keyword$DataError=DH.keywordError=void 0;var X$=a(),MX=J$(),p$=ev();DH.keywordError={message:({keyword:$})=>X$.str`must pass "${$}" keyword validation`};DH.keyword$DataError={message:({keyword:$,schemaType:v})=>v?X$.str`"${$}" keyword must be ${v} ($data)`:X$.str`"${$}" keyword is invalid ($data)`};function GS($,v=DH.keywordError,b,D){let{it:U}=$,{gen:J,compositeRule:X,allErrors:W}=U,Q=bH($,v,b);if(D!==null&&D!==void 0?D:X||W)vH(J,Q);else UH(U,X$._`[${Q}]`)}DH.reportError=GS;function YS($,v=DH.keywordError,b){let{it:D}=$,{gen:U,compositeRule:J,allErrors:X}=D,W=bH($,v,b);if(vH(U,W),!(J||X))UH(D,p$.default.vErrors)}DH.reportExtraError=YS;function zS($,v){$.assign(p$.default.errors,v),$.if(X$._`${p$.default.vErrors} !== null`,()=>$.if(v,()=>$.assign(X$._`${p$.default.vErrors}.length`,v),()=>$.assign(p$.default.vErrors,null)))}DH.resetErrorsCount=zS;function IS({gen:$,keyword:v,schemaValue:b,data:D,errsCount:U,it:J}){if(U===void 0)throw Error("ajv implementation error");let X=$.name("err");$.forRange("i",U,p$.default.errors,(W)=>{if($.const(X,X$._`${p$.default.vErrors}[${W}]`),$.if(X$._`${X}.instancePath === undefined`,()=>$.assign(X$._`${X}.instancePath`,(0,X$.strConcat)(p$.default.instancePath,J.errorPath))),$.assign(X$._`${X}.schemaPath`,X$.str`${J.errSchemaPath}/${v}`),J.opts.verbose)$.assign(X$._`${X}.schema`,b),$.assign(X$._`${X}.data`,D)})}DH.extendErrors=IS;function vH($,v){let b=$.const("err",v);$.if(X$._`${p$.default.vErrors} === null`,()=>$.assign(p$.default.vErrors,X$._`[${b}]`),X$._`${p$.default.vErrors}.push(${b})`),$.code(X$._`${p$.default.errors}++`)}function UH($,v){let{gen:b,validateName:D,schemaEnv:U}=$;if(U.$async)b.throw(X$._`new ${$.ValidationError}(${v})`);else b.assign(X$._`${D}.errors`,v),b.return(!1)}var v4={keyword:new X$.Name("keyword"),schemaPath:new X$.Name("schemaPath"),params:new X$.Name("params"),propertyName:new X$.Name("propertyName"),message:new X$.Name("message"),schema:new X$.Name("schema"),parentSchema:new X$.Name("parentSchema")};function bH($,v,b){let{createErrors:D}=$.it;if(D===!1)return X$._`{}`;return HS($,v,b)}function HS($,v,b={}){let{gen:D,it:U}=$,J=[BS(U,b),NS($,b)];return wS($,v,J),D.object(...J)}function BS({errorPath:$},{instancePath:v}){let b=v?X$.str`${$}${(0,MX.getErrorPath)(v,MX.Type.Str)}`:$;return[p$.default.instancePath,(0,X$.strConcat)(p$.default.instancePath,b)]}function NS({keyword:$,it:{errSchemaPath:v}},{schemaPath:b,parentSchema:D}){let U=D?v:X$.str`${v}/${$}`;if(b)U=X$.str`${U}${(0,MX.getErrorPath)(b,MX.Type.Str)}`;return[v4.schemaPath,U]}function wS($,{params:v,message:b},D){let{keyword:U,data:J,schemaValue:X,it:W}=$,{opts:Q,propertyName:G,topSchemaRef:Y,schemaPath:z}=W;if(D.push([v4.keyword,U],[v4.params,typeof v=="function"?v($):v||X$._`{}`]),Q.messages)D.push([v4.message,typeof b=="function"?b($):b]);if(Q.verbose)D.push([v4.schema,X],[v4.parentSchema,X$._`${Y}${z}`],[p$.default.data,J]);if(G)D.push([v4.propertyName,G])}});var GH=Z((WH)=>{Object.defineProperty(WH,"__esModule",{value:!0});WH.boolOrEmptySchema=WH.topBoolOrEmptySchema=void 0;var jS=Xb(),FS=a(),AS=ev(),MS={message:"boolean schema is false"};function SS($){let{gen:v,schema:b,validateName:D}=$;if(b===!1)XH($,!1);else if(typeof b=="object"&&b.$async===!0)v.return(AS.default.data);else v.assign(FS._`${D}.errors`,null),v.return(!0)}WH.topBoolOrEmptySchema=SS;function VS($,v){let{gen:b,schema:D}=$;if(D===!1)b.var(v,!1),XH($);else b.var(v,!0)}WH.boolOrEmptySchema=VS;function XH($,v){let{gen:b,data:D}=$,U={gen:b,keyword:"false schema",data:D,schema:!1,schemaCode:!1,schemaValue:!1,params:{},it:$};(0,jS.reportError)(U,MS,void 0,v)}});var _Y=Z((YH)=>{Object.defineProperty(YH,"__esModule",{value:!0});YH.getRules=YH.isJSONType=void 0;var ES=["string","number","integer","boolean","null","object","array"],RS=new Set(ES);function kS($){return typeof $=="string"&&RS.has($)}YH.isJSONType=kS;function _S(){let $={number:{type:"number",rules:[]},string:{type:"string",rules:[]},array:{type:"array",rules:[]},object:{type:"object",rules:[]}};return{types:{...$,integer:!0,boolean:!0,null:!0},rules:[{rules:[]},$.number,$.string,$.array,$.object],post:{rules:[]},all:{},keywords:{}}}YH.getRules=_S});var gY=Z((BH)=>{Object.defineProperty(BH,"__esModule",{value:!0});BH.shouldUseRule=BH.shouldUseGroup=BH.schemaHasRulesForType=void 0;function TS({schema:$,self:v},b){let D=v.RULES.types[b];return D&&D!==!0&&IH($,D)}BH.schemaHasRulesForType=TS;function IH($,v){return v.rules.some((b)=>HH($,b))}BH.shouldUseGroup=IH;function HH($,v){var b;return $[v.keyword]!==void 0||((b=v.definition.implements)===null||b===void 0?void 0:b.some((D)=>$[D]!==void 0))}BH.shouldUseRule=HH});var Wb=Z((qH)=>{Object.defineProperty(qH,"__esModule",{value:!0});qH.reportTypeError=qH.checkDataTypes=qH.checkDataType=qH.coerceAndCheckDataType=qH.getJSONTypes=qH.getSchemaTypes=qH.DataType=void 0;var fS=_Y(),xS=gY(),yS=Xb(),t=a(),wH=J$(),H1;(function($){$[$.Correct=0]="Correct",$[$.Wrong=1]="Wrong"})(H1||(qH.DataType=H1={}));function lS($){let v=OH($.type);if(v.includes("null")){if($.nullable===!1)throw Error("type: null contradicts nullable: false")}else{if(!v.length&&$.nullable!==void 0)throw Error('"nullable" cannot be used without "type"');if($.nullable===!0)v.push("null")}return v}qH.getSchemaTypes=lS;function OH($){let v=Array.isArray($)?$:$?[$]:[];if(v.every(fS.isJSONType))return v;throw Error("type must be JSONType or JSONType[]: "+v.join(","))}qH.getJSONTypes=OH;function uS($,v){let{gen:b,data:D,opts:U}=$,J=nS(v,U.coerceTypes),X=v.length>0&&!(J.length===0&&v.length===1&&(0,xS.schemaHasRulesForType)($,v[0]));if(X){let W=ZY(v,D,U.strictNumbers,H1.Wrong);b.if(W,()=>{if(J.length)iS($,v,J);else CY($)})}return X}qH.coerceAndCheckDataType=uS;var LH=new Set(["string","number","integer","boolean","null"]);function nS($,v){return v?$.filter((b)=>LH.has(b)||v==="array"&&b==="array"):[]}function iS($,v,b){let{gen:D,data:U,opts:J}=$,X=D.let("dataType",t._`typeof ${U}`),W=D.let("coerced",t._`undefined`);if(J.coerceTypes==="array")D.if(t._`${X} == 'object' && Array.isArray(${U}) && ${U}.length == 1`,()=>D.assign(U,t._`${U}[0]`).assign(X,t._`typeof ${U}`).if(ZY(v,U,J.strictNumbers),()=>D.assign(W,U)));D.if(t._`${W} !== undefined`);for(let G of b)if(LH.has(G)||G==="array"&&J.coerceTypes==="array")Q(G);D.else(),CY($),D.endIf(),D.if(t._`${W} !== undefined`,()=>{D.assign(U,W),hS($,W)});function Q(G){switch(G){case"string":D.elseIf(t._`${X} == "number" || ${X} == "boolean"`).assign(W,t._`"" + ${U}`).elseIf(t._`${U} === null`).assign(W,t._`""`);return;case"number":D.elseIf(t._`${X} == "boolean" || ${U} === null
3
3
  || (${X} == "string" && ${U} && ${U} == +${U})`).assign(W,t._`+${U}`);return;case"integer":D.elseIf(t._`${X} === "boolean" || ${U} === null
4
4
  || (${X} === "string" && ${U} && ${U} == +${U} && !(${U} % 1))`).assign(W,t._`+${U}`);return;case"boolean":D.elseIf(t._`${U} === "false" || ${U} === 0 || ${U} === null`).assign(W,!1).elseIf(t._`${U} === "true" || ${U} === 1`).assign(W,!0);return;case"null":D.elseIf(t._`${U} === "" || ${U} === 0 || ${U} === false`),D.assign(W,null);return;case"array":D.elseIf(t._`${X} === "string" || ${X} === "number"
@@ -128,8 +128,8 @@ Content-Length: 0\r
128
128
  `),D=U;if(U>0&&W[0]!==10)D+=Buffer.byteLength(C.shift()??"","binary")+1;for(let O of C){let B=Buffer.from(O,"binary"),_=(B[B.length-1]===13?B.subarray(0,B.length-1):B).toString("utf8"),H=D+B.length+1;if(_)try{let T=JSON.parse(_);if(T&&typeof T==="object"&&!Array.isArray(T)){let A=T;if(A.service===Q||A.service===G){let R=typeof A.id==="string"?A.id:this.compatibilityId(Z,Q,D,_);if(!z||n0(R,z))X.push({...A,service:Q,id:R},_.length)}}}catch{}D=H}return K}bucket($){let Z=this.buckets.get($);if(!Z){let Q=this.historyFile($,"log"),X=this.historyFile($,"request"),G=this.legacyHistoryFile($,"log"),J=this.legacyHistoryFile($,"request");if(Z={logs:new $8(t1,this.maxHistoryBytes),requests:new $8(r1,this.maxHistoryBytes),stats:j4(),latencyTotal:0,logFile:void 0,reqFile:void 0,persistenceDiagnosticEmitted:!1},G!==Q)this.loadHistory(G,"log",$,Z.logs);if(J!==X)this.loadHistory(J,"request",$,Z.requests);if($.startsWith("standalone:")){let N=$.slice(11),U=this.legacyHistoryFile(N,"log"),W=this.legacyHistoryFile(N,"request");if(U!==Q&&U!==G)this.loadHistory(U,"log",$,Z.logs,N);if(W!==X&&W!==J)this.loadHistory(W,"request",$,Z.requests,N)}let V=`${Q}.1`,z=`${X}.1`,Y=(()=>{try{return f.statSync(Q).size}catch{return 0}})(),K=(()=>{try{return f.statSync(X).size}catch{return 0}})();if(this.loadHistory(V,"log",$,Z.logs,void 0,Math.max(0,this.maxFileBytes-Math.min(Y,this.maxFileBytes))),this.loadHistory(Q,"log",$,Z.logs,void 0,this.maxFileBytes),this.loadHistory(z,"request",$,Z.requests,void 0,Math.max(0,this.maxFileBytes-Math.min(K,this.maxFileBytes))),this.loadHistory(X,"request",$,Z.requests,void 0,this.maxFileBytes),Z.logFile=this.persistenceStream($,"log",Q),Z.reqFile=this.persistenceStream($,"request",X),this.buckets.set($,Z),Z.logFile.failedDuringCreate)this.reportPersistenceFailure($,Z,"log");if(Z.reqFile.failedDuringCreate)this.reportPersistenceFailure($,Z,"request")}return Z}resetStats($){let Z=this.bucket($);Z.stats=j4(),Z.latencyTotal=0}stats($){return this.bucket($).stats}log($){let Z={...$,id:this.nextId()},Q=this.bucket(Z.service),X=JSON.stringify(Z);if(Q.logs.push(Z,X.length),Q.stats.logLines++,Z.stream==="stderr"||F6.test(Z.line))Q.stats.errorLines++;return this.persist(Z.service,Q,Q.logFile,X+`
129
129
  `),this.emitEvent({type:"log",log:Z}),Z}request($){let Z={...$,id:this.nextId()},Q=this.bucket(Z.service),X=JSON.stringify(Z);Q.requests.push(Z,X.length);let G=Q.stats;if(G.requests++,G.lastRequestAt=Z.ts,Z.error)G.proxyErrors++;else if(Z.status>=500)G.serverErrors++;else if(Z.status>=400)G.clientErrors++;else G.ok++;return Q.latencyTotal+=Z.durationMs,G.avgLatencyMs=Math.round(Q.latencyTotal/G.requests),this.persist(Z.service,Q,Q.reqFile,X+`
130
130
  `),this.emitEvent({type:"request",request:Z}),Z}logs($,Z=200){return this.bucket($).logs.last(Z)}requests($,Z=200){return this.bucket($).requests.last(Z)}historyBoundary($,Z){let Q=`${this.historyFile($,Z==="logs"?"log":"request")}.cleared`;return f.existsSync(Q)?f.readFileSync(Q,"utf8"):void 0}async clearHistory($,Z){if(this.closing)throw Error("History is unavailable during shutdown");let Q=this.bucket($),X=Z==="logs"?Q.logFile:Q.reqFile,G=this.nextId(),J=`${X.file}.cleared`;if(f.writeFileSync(`${J}.tmp`,G,{mode:384}),f.renameSync(`${J}.tmp`,J),Q[Z].clear(),Z==="requests")this.responseBodies.clear($);let V=X.queue.then(async()=>{await this.closeStream(X.stream),f.writeFileSync(X.file,"",{mode:384}),f.rmSync(`${X.file}.1`,{force:!0}),X.bytes=0,X.stream=this.streamFactory(X.file,{flags:"a",mode:384,highWaterMark:65536}),X.disabled=!1,X.stream.on("error",()=>{X.disabled=!0,this.reportPersistenceFailure($,Q,"history")})});X.queue=V.catch(()=>{X.disabled=!0,this.reportPersistenceFailure($,Q,"history clear")});let z=this.emitEvent({type:"history:cleared",service:$,kind:Z,beforeId:G});return await V,z}emitEvent($){let Z={...$,eventId:this.nextId()};return this.activity.capture(Z),this.emit("event",Z),Z}activityBoundary(){return this.nextId()}activityCoverage($){let Z=this.bucket($),Q=[];if(this.historyBoundary($,"logs")||this.historyBoundary($,"requests"))Q.push("Some history was explicitly cleared.");if(Z.logs.last(t1).length===t1||Z.requests.last(r1).length===r1||f.existsSync(`${Z.logFile.file}.1`)||f.existsSync(`${Z.reqFile.file}.1`))Q.push("Older logs or requests may have expired from bounded history.");if(Z.persistenceDiagnosticEmitted)Q.push("Some log or request history could not be persisted.");return{reasons:Q}}close(){if(!this.closePromise){this.closing=!0,this.responseBodies.clear();let $=[...this.buckets.values()];this.closePromise=(async()=>{let Z=$.flatMap((G)=>[G.logFile,G.reqFile]);Z.forEach((G)=>{G.accepting=!1});let Q=await Promise.all(Z.map((G)=>e1(G.queue,this.closeAfterMs)));Z.forEach((G,J)=>{if(!Q[J]){G.closing=!0;try{G.stream.destroy()}catch{}}});let X=$.flatMap((G)=>[G.logFile.stream,G.reqFile.stream]);await Promise.allSettled(X.map((G)=>this.closeStream(G)))})()}return this.closePromise}async closeStream($){let Z=A6($).then(()=>{return},()=>{return});try{if(!$.destroyed&&!$.writableEnded)$.end()}catch{try{$.destroy()}catch{}}if(await e1(Z,this.closeAfterMs))return;try{$.destroy()}catch{}await e1(Z,this.closeAfterMs)}persistenceStream($,Z,Q){let X,G=!1;try{if(this.closing)G=!0,X=new w4({write(V,z,Y){Y()}}),X.end();else X=this.streamFactory(Q,{flags:"a",mode:384,highWaterMark:65536})}catch{G=!0,X=new w4({write(V,z,Y){Y()}})}try{if(f.existsSync(Q))f.chmodSync(Q,384)}catch{}let J={stream:X,file:Q,bytes:(()=>{try{return f.statSync(Q).size}catch{return 0}})(),queue:Promise.resolve(),pending:0,closing:!1,accepting:!0,disabled:G,backpressured:!1,failedDuringCreate:G};return X.on("error",()=>{if(J.disabled)return;J.disabled=!0,J.backpressured=!1;let V=this.buckets.get($);if(V)this.reportPersistenceFailure($,V,Z)}),X.on("drain",()=>{J.backpressured=!1}),J}persist($,Z,Q,X){if(Q.disabled||!Q.accepting)return;if(Q.pending++,Q.pending>1e4){Q.pending--,Q.disabled=!0,this.reportPersistenceFailure($,Z,"history");return}Q.queue=Q.queue.then(async()=>{if(Q.disabled){Q.pending--;return}try{let G=Buffer.byteLength(X);if(G>this.maxFileBytes){this.reportPersistenceFailure($,Z,"history record too large");return}if(Q.bytes>0&&Q.bytes+G>this.maxFileBytes)await this.rotate($,Z,Q);if(!Q.stream.write(X))Q.backpressured=!0,await new Promise((J)=>{let V=()=>{Q.stream.off("drain",V),Q.stream.off("error",V),Q.stream.off("close",V),J()};Q.stream.once("drain",V),Q.stream.once("error",V),Q.stream.once("close",V)}),Q.backpressured=!1;Q.bytes+=G}catch{Q.disabled=!0,this.reportPersistenceFailure($,Z,"history")}finally{Q.pending--}})}async rotate($,Z,Q){if(await this.closeStream(Q.stream),Q.closing)throw Q.disabled=!0,Error("history rotation interrupted");let X=`${Q.file}.1`;try{f.rmSync(X,{force:!0}),f.renameSync(Q.file,X)}catch{throw Q.disabled=!0,this.reportPersistenceFailure($,Z,"history rotation"),Error("history rotation failed")}Q.stream=this.streamFactory(Q.file,{flags:"a",mode:384,highWaterMark:65536});try{f.chmodSync(Q.file,384)}catch{}Q.bytes=0,Q.stream.on("error",()=>{Q.disabled=!0,this.reportPersistenceFailure($,Z,"history")}),Q.stream.on("drain",()=>{Q.backpressured=!1})}reportPersistenceFailure($,Z,Q){if(Z.persistenceDiagnosticEmitted)return;Z.persistenceDiagnosticEmitted=!0;let X={id:this.nextId(),ts:Date.now(),service:$,stream:"system",line:`LocalDeck: ${Q} persistence unavailable; continuing with in-memory history`};Z.logs.push(X),Z.stats.logLines++,Z.stats.errorLines++,this.emitEvent({type:"log",log:X})}}function e1($,Z){return new Promise((Q)=>{let X=!1,G=(V)=>{if(X)return;X=!0,clearTimeout(J),Q(V)},J=setTimeout(()=>G(!1),Z);J.unref(),$.then(()=>G(!0),()=>G(!0))})}import{spawn as f6}from"node:child_process";import X1 from"node:path";import b6 from"node:fs";function h4($){let Z=$.replace(/\x1b\[[0-9;]*m/g,"");if(!/\bEADDRINUSE\b|\b(?:port|address)\b[^\n]*already in use/i.test(Z))return;let Q=/\bport\s+(\d+)\s+is already in use/i.exec(Z)?.[1]??/\b(?:listen|address already in use)[^\n]*:(\d+)\b/i.exec(Z)?.[1],X=Q&&Number(Q)>0&&Number(Q)<=65535?Q:void 0,G=X?`Port ${X} is already in use.`:"The service’s port is already in use.",J=/\bvite\b|\bhttpServerStart\b/.test(Z);return{title:G,steps:J?["Check server.port and server.strictPort in your Vite config. With strictPort: true, Vite exits when that port is occupied.",`To use LocalDeck’s assigned port, set server.port to Number(process.env.PORT) || ${X??"5173"}. You can keep strictPort: true.`,"Alternatively, stop the other instance, or set strictPort: false to let Vite try another port. Automatic port detection must be enabled in LocalDeck (leave upstream unset)."]:["Stop the other instance, or configure the app to listen on the PORT environment variable supplied by LocalDeck.","If the app requires a fixed port, choose an unused port in the app and set LocalDeck’s upstream to match."]}}import g4 from"node:fs";import E0 from"node:path";function X8($,Z,Q){let X=new Set,G=(V,z)=>{if(X.size>=16)return;let Y=typeof V==="string"?M6(V):V;if(!Y?.length)return;let K=E0.basename(Y[0]).replace(/\.cmd$/,"");if(Y[0].includes("=")||["echo","printf"].includes(K))return;if(["npm","pnpm","yarn","bun"].includes(K)){let C=z,D,O;for(let H=1;H<Y.length;H++){let T=Y[H];if(T==="--")break;if(T==="run"||T==="run-script")continue;let A=/^(--prefix|--cwd|--dir|-C|--workspace|-w)(?:=(.*))?$/.exec(T);if(A){let R=A[2]??Y[++H];if(!R||/[$`]/.test(R))return;if(A[1]==="--workspace"||A[1]==="-w"){if(D)return;D=R}else C=E0.resolve(z,R)}else if(T.startsWith("-")||O)return;else O=T}if(!O||/[$`]/.test(O))return;if(D){let H=x6(C,D);if(!H)return;C=H}let B=`${C}\x00${O}`;if(X.has(B))return;X.add(B);let _=Q8(C)?.scripts?.[O];return typeof _==="string"?G(_,C):void 0}let N=Y.slice(1).flatMap((C,D)=>C==="--port"?[Y[D+2]??""]:C.startsWith("--port=")?[C.slice(7)]:[]);if(N.length!==1)return;let U=/^(?:\$([A-Za-z_][A-Za-z0-9_]*)|\$\{([A-Za-z_][A-Za-z0-9_]*)(?::?-\d+)?\})$/.exec(N[0]),W=U?.[1]??U?.[2];if(W&&W!=="PORT"&&!W.startsWith("LOCALDECK_"))return W},J=G($,E0.resolve(Z));return J?{[J]:String(Q)}:{}}function M6($){let Z=[],Q="",X="",G=!1;for(let J=0;J<$.length;J++){let V=$[J];if(V==="`"||V==="\\"||V===`
131
- `||$.slice(J,J+2)==="$(")return;if(X)if(V===X)X="";else Q+=X==="'"&&V==="$"?"\x00":V;else if(V==='"'||V==="'")X=V,G=!0;else if(/\s/.test(V)){if(G)Z.push(Q);Q="",G=!1}else{if(/[;&|<>()#]/.test(V))return;Q+=V,G=!0}}if(X)return;if(G)Z.push(Q);return Z}function Q8($){try{let Z=JSON.parse(g4.readFileSync(E0.join($,"package.json"),"utf8"));return Z&&typeof Z==="object"&&!Array.isArray(Z)?Z:void 0}catch{return}}function x6($,Z){let Q=Q8($)?.workspaces,X=Array.isArray(Q)?Q:Q?.packages;if(!Array.isArray(X))return;let G=new Set;for(let J of X.slice(0,100)){if(typeof J!=="string"||E0.isAbsolute(J))continue;let V=J.replace(/^\.\//,"").replace(/\/$/,"").split("/");if(V.some((Y)=>!Y||Y===".."||/[^\w@.*-]/.test(Y)||Y.includes("**")))continue;let z=[$];for(let Y of V){let K=new RegExp(`^${Y.replace(/\./g,"\\.").replace(/\*/g,".*")}$`),N=[];for(let U of z)try{for(let W of g4.readdirSync(U,{withFileTypes:!0})){if(W.isDirectory()&&!["node_modules",".git"].includes(W.name)&&K.test(W.name))N.push(E0.join(U,W.name));if(N.length>100)return}}catch{}z=N}for(let Y of z){let K=Q8(Y);if(K&&(Y===E0.resolve($,Z)||K.name===Z))G.add(Y)}}return G.size===1?[...G][0]:void 0}import P6 from"node:http";import{spawn as I6}from"node:child_process";async function G8($,Z,Q={}){let X=Date.now()+$.ready.timeoutMs;for(;;){w6($.name,Q.signal);let G=await Z();if(!G||G.status==="stopped")throw Error(`${$.name} exited before it became ready`);let J=X-Date.now();if(J<=0)throw Error(`${$.name} readiness timed out after ${$.ready.timeoutMs}ms`);let V=!1;if(G.upstreamReady)if($.ready.type==="tcp")V=!0;else if($.ready.type==="http")V=await S6(G,$.ready.path,$.ready.status,J,Q.signal);else V=await q6($.ready.run,$.ready.expectedOutput,G,Q.cwd,J,Q.signal,Q.env);if(V)return{...G,urls:[...G.urls],stats:{...G.stats}};let z=X-Date.now();if(z<=0)throw Error(`${$.name} readiness timed out after ${$.ready.timeoutMs}ms`);await E6(Math.min($.ready.intervalMs,z),$.name,Q.signal)}}function S6($,Z,Q,X,G){return new Promise((J,V)=>{if(G?.aborted)return V(Error(`${$.name} readiness cancelled`));let z=!1,Y=(U,W)=>{if(z)return;if(z=!0,G?.removeEventListener("abort",N),W)V(W);else J(U)},K=P6.request({host:$.upstreamHost,port:$.upstreamPort,path:Z,method:"GET",timeout:Math.max(1,Math.min(X,2000))},(U)=>{U.resume();let W=U.statusCode??0;Y(Q===void 0?W>=200&&W<400:W===Q)}),N=()=>{K.destroy(),Y(!1,Error(`${$.name} readiness cancelled`))};G?.addEventListener("abort",N,{once:!0}),K.once("timeout",()=>K.destroy()),K.once("error",()=>Y(!1)),K.end()})}function q6($,Z,Q,X,G,J,V){return new Promise((z,Y)=>{if(J?.aborted)return Y(Error(`${Q.name} readiness cancelled`));let K=$.replaceAll("{upstream}",String(Q.upstreamPort)).replaceAll("{port}",String(Q.stablePort)),N=V$(K),U=!1,W=I6(N[0],N.slice(1),{cwd:X,stdio:["ignore","pipe","ignore"],detached:process.platform!=="win32",env:{...process.env,...V,PORT:String(Q.upstreamPort),LOCALDECK_PORT:String(Q.stablePort),LOCALDECK_SERVICE:Q.name,LOCALDECK_URL:Q.urls[0]}}),C=[],D=0;W.stdout?.on("data",(_)=>{if(D>=8192)return;let H=_.subarray(0,8192-D);C.push(H),D+=H.length});let O=(_,H)=>{if(U)return;if(U=!0,clearTimeout(L),J?.removeEventListener("abort",B),H)Y(H);else z(_)},B=()=>{f4(W),O(!1,Error(`${Q.name} readiness cancelled`))},L=setTimeout(()=>{f4(W),O(!1)},Math.max(1,Math.min(G,2000)));L.unref(),J?.addEventListener("abort",B,{once:!0}),W.once("error",()=>O(!1)),W.once("close",(_)=>O(_===0&&(Z===void 0||Buffer.concat(C).toString("utf8").trim()===Z)))})}function f4($){if(!$.pid)return;try{if(process.platform!=="win32")process.kill(-$.pid,"SIGKILL");else $.kill("SIGKILL")}catch{}}function E6($,Z,Q){return new Promise((X,G)=>{if(Q?.aborted)return G(Error(`${Z} readiness cancelled`));let J=setTimeout(z,$),V=()=>{clearTimeout(J),Q?.removeEventListener("abort",V),G(Error(`${Z} readiness cancelled`))};function z(){Q?.removeEventListener("abort",V),X()}Q?.addEventListener("abort",V,{once:!0})})}function w6($,Z){if(Z?.aborted)throw Error(`${$} readiness cancelled`)}import{Transform as j6}from"node:stream";import{StringDecoder as h6}from"node:string_decoder";import{stripVTControlCharacters as g6}from"node:util";function Q1($){let Z=new h6("utf8"),Q="",X="text";function G(V){if(!$.size)return V;let z="";for(let Y of V)if(X==="text")if(Y==="\x1B")X="escape";else if(Y==="›")X="csi";else z+=Y;else if(X==="escape")X=Y==="["?"csi":Y==="]"?"osc":Y>=" "&&Y<="/"?"intermediate":"text";else if(X==="intermediate"){if(Y>="0"&&Y<="~")X="text"}else if(X==="csi"){if(Y>="@"&&Y<="~")X="text"}else if(X==="osc"){if(Y==="\x07")X="text";else if(Y==="\x1B")X="osc-escape"}else X=Y==="\\"||Y==="\x07"?"text":Y==="\x1B"?"osc-escape":"osc";return z}function J(V){let z=[...$].map(g6).filter(Boolean).sort((N,U)=>U.length-N.length);if(!z.length){let N=Q;return Q="",N}let Y="",K=0;while(K<Q.length){let N=Q.slice(K);if(!V&&z.some((W)=>W.length>N.length&&W.startsWith(N)))break;let U=z.find((W)=>Q.startsWith(W,K));if(U)Y+="[REDACTED]",K+=U.length;else Y+=Q[K++]}return Q=Q.slice(K),Y}return new j6({transform(V,z,Y){Q+=G(Z.write(V)),Y(null,J(!1))},flush(V){Q+=G(Z.end()),V(null,J(!0))}})}var y6=5000,v6=300,k6=5000,u6=20,m6=4000;class J1{projects;registry;store;active=new Map;pending=new Map;forceAfterMs;detectAfterMs;terminalStopAfterMs;killTree;shareLifecycle;allocatePort;resolveSecrets;upstreamReservations=new Set;retries=new Map;redactionValues=new Set;retryDelayMs;shuttingDown=!1;shutdownPromise;constructor($,Z,Q,X={}){this.projects=$;this.registry=Z;this.store=Q;this.retryDelayMs=X.retryDelayMs??3000,this.forceAfterMs=X.forceAfterMs??y6,this.detectAfterMs=X.detectAfterMs??v6,this.terminalStopAfterMs=X.terminalStopAfterMs??k6,this.killTree=X.killProcessTree??l1,this.shareLifecycle=X.shareLifecycle,this.allocatePort=X.getFreePort??K$,this.resolveSecrets=X.resolveProjectSecrets??z0}start($,Z){let Q=Z.toLowerCase();return this.startSelection($,[Q]).then((X)=>X.find((G)=>G.name===Q)??h(u($,Q),Q,`Project ${$} has no service named ${Z}`))}stop($,Z){return this.cancelRetries($),this.enqueue($,()=>this.stopNow($,Z))}async restart($,Z){let Q=Z.toLowerCase(),X=u($,Q);if(this.shuttingDown)return h(X,Q,"daemon is shutting down");let G=await this.stop(X,"restart");if(!G.ok)return G;return this.start($,Q)}startAll($){return this.startSelection($)}async startSelection($,Z){let Q=this.projects.details($);if(!Q.available)throw new q("invalid",Q.error);let X=u$(Q.commands,Z),G=new Set(X.flat().map((K)=>K.name));if(this.shuttingDown)return Q.commands.filter((K)=>G.has(K.name)).map((K)=>h(u($,K.name),K.name,"daemon is shutting down"));let J=new Map,V=new Map,z=new Map(Q.commands.map((K)=>[K.name,K])),Y=(K)=>{let N=V.get(K.name);if(N)return N;let U=(async()=>{let W=K.after.map((H)=>Y(z.get(H))),C=W.length?await Promise.all(W):[],D=K.after.filter((H,T)=>!C[T].ok);if(D.length)return h(u($,K.name),K.name,`${K.name} was not started because ${D.join(", ")} failed`);let O=u($,K.name),B;try{B=await this.enqueue(O,()=>this.startOne($,K.name,O))}catch(H){if(Z&&H instanceof q)throw H;return h(O,K.name,l(H))}if(!B.ok)return B;let L=Q.commands.some((H)=>H.after.includes(K.name));if(K.ready.type==="tcp"&&!L){let H=K.cwd?X1.resolve(Q.directory,K.cwd):Q.directory;return this.verifyReadiness(K,O,H),B}let _=K.cwd?X1.resolve(Q.directory,K.cwd):Q.directory;return this.verifyReadiness(K,O,_,B)})();return V.set(K.name,U),U};await Promise.all(Q.commands.filter((K)=>G.has(K.name)).map(async(K)=>{let N=await Y(K);J.set(K.name,N)}));for(let K of Q.commands){if(!G.has(K.name)||J.has(K.name))continue;let N=K.after.filter((U)=>!J.get(U)?.ok);J.set(K.name,h(u($,K.name),K.name,N.length?`${K.name} was not started because ${N.join(", ")} failed`:"daemon is shutting down"))}return Q.commands.filter((K)=>G.has(K.name)).map((K)=>J.get(K.name))}async verifyReadiness($,Z,Q,X){let G=this.registry.get(Z),J=this.active.get(Z),V=()=>G!==void 0&&this.registry.get(Z)===G&&(J?this.active.get(Z)===J:G.managedBy==="terminal");this.setReadiness(Z,"checking",$.ready.type==="tcp"?"Waiting for the service to listen":"Running configured readiness check"),this.store.log({ts:Date.now(),service:Z,stream:"system",line:`LocalDeck: checking readiness for ${$.name}`});try{let z=J?.commandEnv;if(!z&&G){let N=this.resolveSecrets(G.projectId,$.secrets??[]);for(let U of Object.values(N))this.redactionValues.add(U);z={...this.expandCommandEnv($.env,$.after,G.projectId),...N}}if(await G8($,()=>V()?G:void 0,{cwd:Q,env:z}),!V()||G.status==="stopped"||G.status==="stopping")return h(Z,$.name,"readiness cancelled");let Y=$.ready.type==="tcp"?"Listening on its upstream port":"Configured readiness check passed";this.setReadiness(Z,"ready",Y),this.store.log({ts:Date.now(),service:Z,stream:"system",line:`LocalDeck: ${$.name} ${$.ready.type==="tcp"?"is listening":"passed its configured readiness check"}`});let K=this.registry.get(Z)??X?.service;return K?A$(K):h(Z,$.name,"service exited before it became ready")}catch(z){let Y=l(z);if(!V()||G.status==="stopped"||G.status==="stopping")return h(Z,$.name,Y);return this.setReadiness(Z,"failed",Y),this.setLastError(Z,Y),await this.stop(Z,"readiness failed"),h(Z,$.name,Y,this.registry.get(Z))}}async stopAll($){let Z=this.projects.details($),Q=new Map(this.registry.list($).filter((J)=>J.status!=="stopped"||J.share!==void 0).map((J)=>[J.key,{key:J.key,name:J.name}]));for(let J of new Set([...this.active.keys(),...this.retries.keys()]))if(J.startsWith(`${$}:`)&&!Q.has(J)){let V=J.slice(J.lastIndexOf(":")+1);Q.set(J,{key:J,name:V})}let X=[];if(Z.available)for(let J of S1(Z.commands)){let V=u($,J.name),z=Q.get(V);if(z)X.push(z),Q.delete(V)}X.push(...Q.values());for(let J of X)this.cancelRetries(J.key);let G=[];for(let J of X)try{G.push(await this.stop(J.key,"stop all"))}catch(V){G.push(h(J.key,J.name,l(V)))}return G}shutdown(){if(this.shutdownPromise)return this.shutdownPromise;this.shuttingDown=!0;for(let $ of this.retries.keys())this.cancelRetries($);return this.shutdownPromise=this.shutdownNow(),this.shutdownPromise}async shutdownNow(){await Promise.allSettled([...this.pending.values()]);let $=await Promise.allSettled([...this.active.keys()].map((Q)=>this.stop(Q,"daemon shutdown")));await Promise.allSettled([...this.pending.values()]);let Z=[];for(let Q of $)if(Q.status==="rejected")Z.push(p6(Q.reason));else if(!Q.value.ok)Z.push(Error(`${Q.value.key}: ${Q.value.error??"stop failed"}`));for(let Q of this.active.values())if(y4(Q.child))Z.push(Error(`${Q.key}: supervised child ${Q.child.pid??"?"} is still running`));if(Z.length)throw AggregateError(Z,"failed to stop all supervised processes during shutdown")}enqueue($,Z){let Q=this.pending.get($),G=(Q?Q.then(Z,Z):Z()).finally(()=>{if(this.pending.get($)===G)this.pending.delete($)});return this.pending.set($,G),G}async startOne($,Z,Q){if(this.shuttingDown)return h(Q,Z,"daemon is shutting down");let X=this.active.get(Q);if(X){if(X.child.exitCode===null&&X.child.signalCode===null){let F=this.registry.get(Q);return F?A$(F):h(Q,Z,"service process has no registry entry")}if(await X.completion,this.active.get(Q)===X)return h(Q,Z,"previous process cleanup is incomplete; stop the service again before restarting")}if(this.retries.get(Q)?.timer)this.cancelRetries(Q);let J=this.registry.get(Q);if(J&&J.status!=="stopped")return A$(J);let V=this.retries.get(Q)??{attempts:0,cancelled:!1};this.retries.set(Q,V);let z=this.projects.resolve($,Z),Y=this.projects.details($);if(!Y.available)throw new q("invalid",Y.error);let K=z.cwd?X1.resolve(Y.directory,z.cwd):Y.directory;try{if(!b6.statSync(K).isDirectory())throw Error("not a directory")}catch{throw new q("invalid",`configured working directory does not exist or is not a directory: ${K}`)}let N;try{N=this.resolveSecrets($,z.secrets??[]);for(let F of Object.values(N))this.redactionValues.add(F)}catch(F){return h(Q,Z,l(F))}let U;try{U=z.upstream??await this.reserveAutomaticUpstream()}catch(F){return h(Q,Z,l(F))}let W=z.upstream===void 0?U:void 0,C;try{C={...this.expandCommandEnv(z.env,z.after,$),...N}}catch(F){return this.releaseAutomaticUpstream(W),h(Q,Z,l(F))}let D;try{D=await this.registry.register({key:Q,projectId:$,projectName:Y.name,projectSlug:Y.slug,name:Z,managedBy:"daemon",stablePort:z.port,upstreamPort:U,upstreamSource:z.upstream===void 0?"assigned":"manual",cwd:K,command:z.run,serviceType:z.serviceType,...Y.activeProfiles?.length?{profiles:Y.activeProfiles}:{},configFingerprint:P0(z)},()=>void this.stop(Q,"stop requested"))}catch(F){return this.releaseAutomaticUpstream(W),h(Q,Z,l(F))}let O=V$(z.run.replaceAll("{port}",String(U))),B=D.serviceType!==void 0&&D.serviceType!=="http",L=B?{}:X8(z.run,K,U);C={...L,...C};for(let F of Object.keys(L))if(C[F]===L[F])this.store.log({ts:Date.now(),service:Q,stream:"system",line:`LocalDeck: supplying assigned port ${U} through ${F}`});let _={...process.env,...C,PORT:String(U),LOCALDECK_PORT:String(D.stablePort),LOCALDECK_SERVICE:D.name,...B?{}:{LOCALDECK_URL:`http://localhost:${D.stablePort}`}};this.setReadiness(Q,"waiting","Waiting for process to listen");let H;try{H=f6(O[0],O.slice(1),{cwd:K,env:_,detached:process.platform!=="win32",stdio:["ignore","pipe","pipe"]})}catch(F){return this.setLastError(Q,l(F)),await this.registry.unregister(Q),this.releaseAutomaticUpstream(W),h(Q,Z,l(F))}let T,A={key:Q,name:Z,child:H,stderr:[],completion:new Promise((F)=>{T=F}),reservedUpstreamPort:W,commandEnv:C};this.active.set(Q,A);let R=!1,M,E=async(F,w,m)=>{if(R)return;R=!0;let p=!1;if(A.detectTimer)clearTimeout(A.detectTimer);this.releaseAutomaticUpstream(A.reservedUpstreamPort);try{if(this.active.get(Q)!==A)return;if(A.stopping){p=!0;return}else if(!await this.cleanupLeaderFirstExit(A))A.cleanupError=Error(`process group ${A.child.pid??"?"} survived forced cleanup after its leader exited`),p=!0;let k=l6(A.stderr),g=this.registry.get(Q)?.status==="starting";if(!A.stopping&&(m||F!==0||w!==null||g&&k)){this.setLastError(Q,k||m?.message||`process exited (${w??`code ${F}`})`);let b=h4(k);if(b)this.store.log({ts:Date.now(),service:Q,stream:"system",line:[b.title,...b.steps].join(`
131
+ `||$.slice(J,J+2)==="$(")return;if(X)if(V===X)X="";else Q+=X==="'"&&V==="$"?"\x00":V;else if(V==='"'||V==="'")X=V,G=!0;else if(/\s/.test(V)){if(G)Z.push(Q);Q="",G=!1}else{if(/[;&|<>()#]/.test(V))return;Q+=V,G=!0}}if(X)return;if(G)Z.push(Q);return Z}function Q8($){try{let Z=JSON.parse(g4.readFileSync(E0.join($,"package.json"),"utf8"));return Z&&typeof Z==="object"&&!Array.isArray(Z)?Z:void 0}catch{return}}function x6($,Z){let Q=Q8($)?.workspaces,X=Array.isArray(Q)?Q:Q?.packages;if(!Array.isArray(X))return;let G=new Set;for(let J of X.slice(0,100)){if(typeof J!=="string"||E0.isAbsolute(J))continue;let V=J.replace(/^\.\//,"").replace(/\/$/,"").split("/");if(V.some((Y)=>!Y||Y===".."||/[^\w@.*-]/.test(Y)||Y.includes("**")))continue;let z=[$];for(let Y of V){let K=new RegExp(`^${Y.replace(/\./g,"\\.").replace(/\*/g,".*")}$`),N=[];for(let U of z)try{for(let W of g4.readdirSync(U,{withFileTypes:!0})){if(W.isDirectory()&&!["node_modules",".git"].includes(W.name)&&K.test(W.name))N.push(E0.join(U,W.name));if(N.length>100)return}}catch{}z=N}for(let Y of z){let K=Q8(Y);if(K&&(Y===E0.resolve($,Z)||K.name===Z))G.add(Y)}}return G.size===1?[...G][0]:void 0}import P6 from"node:http";import{spawn as I6}from"node:child_process";async function G8($,Z,Q={}){let X=Date.now()+$.ready.timeoutMs;for(;;){w6($.name,Q.signal);let G=await Z();if(!G||G.status==="stopped")throw Error(`${$.name} exited before it became ready`);let J=X-Date.now();if(J<=0)throw Error(`${$.name} readiness timed out after ${$.ready.timeoutMs}ms`);let V=!1;if($.ready.type==="command")V=await q6($.ready.run,$.ready.expectedOutput,G,Q.cwd,J,Q.signal,Q.env);else if(G.upstreamReady)V=$.ready.type==="tcp"||await S6(G,$.ready.path,$.ready.status,J,Q.signal);if(V)return{...G,urls:[...G.urls],stats:{...G.stats}};let z=X-Date.now();if(z<=0)throw Error(`${$.name} readiness timed out after ${$.ready.timeoutMs}ms`);await E6(Math.min($.ready.intervalMs,z),$.name,Q.signal)}}function S6($,Z,Q,X,G){return new Promise((J,V)=>{if(G?.aborted)return V(Error(`${$.name} readiness cancelled`));let z=!1,Y=(U,W)=>{if(z)return;if(z=!0,G?.removeEventListener("abort",N),W)V(W);else J(U)},K=P6.request({host:$.upstreamHost,port:$.upstreamPort,path:Z,method:"GET",timeout:Math.max(1,Math.min(X,2000))},(U)=>{U.resume();let W=U.statusCode??0;Y(Q===void 0?W>=200&&W<400:W===Q)}),N=()=>{K.destroy(),Y(!1,Error(`${$.name} readiness cancelled`))};G?.addEventListener("abort",N,{once:!0}),K.once("timeout",()=>K.destroy()),K.once("error",()=>Y(!1)),K.end()})}function q6($,Z,Q,X,G,J,V){return new Promise((z,Y)=>{if(J?.aborted)return Y(Error(`${Q.name} readiness cancelled`));let K=$.replaceAll("{upstream}",String(Q.upstreamPort)).replaceAll("{port}",String(Q.stablePort)),N=V$(K),U=!1,W=I6(N[0],N.slice(1),{cwd:X,stdio:["ignore","pipe","ignore"],detached:process.platform!=="win32",env:{...process.env,...V,PORT:String(Q.upstreamPort),LOCALDECK_PORT:String(Q.stablePort),LOCALDECK_SERVICE:Q.name,LOCALDECK_URL:Q.urls[0]}}),C=[],D=0;W.stdout?.on("data",(_)=>{if(D>=8192)return;let H=_.subarray(0,8192-D);C.push(H),D+=H.length});let O=(_,H)=>{if(U)return;if(U=!0,clearTimeout(L),J?.removeEventListener("abort",B),H)Y(H);else z(_)},B=()=>{f4(W),O(!1,Error(`${Q.name} readiness cancelled`))},L=setTimeout(()=>{f4(W),O(!1)},Math.max(1,Math.min(G,2000)));L.unref(),J?.addEventListener("abort",B,{once:!0}),W.once("error",()=>O(!1)),W.once("close",(_)=>O(_===0&&(Z===void 0||Buffer.concat(C).toString("utf8").trim()===Z)))})}function f4($){if(!$.pid)return;try{if(process.platform!=="win32")process.kill(-$.pid,"SIGKILL");else $.kill("SIGKILL")}catch{}}function E6($,Z,Q){return new Promise((X,G)=>{if(Q?.aborted)return G(Error(`${Z} readiness cancelled`));let J=setTimeout(z,$),V=()=>{clearTimeout(J),Q?.removeEventListener("abort",V),G(Error(`${Z} readiness cancelled`))};function z(){Q?.removeEventListener("abort",V),X()}Q?.addEventListener("abort",V,{once:!0})})}function w6($,Z){if(Z?.aborted)throw Error(`${$} readiness cancelled`)}import{Transform as j6}from"node:stream";import{StringDecoder as h6}from"node:string_decoder";import{stripVTControlCharacters as g6}from"node:util";function Q1($){let Z=new h6("utf8"),Q="",X="text";function G(V){if(!$.size)return V;let z="";for(let Y of V)if(X==="text")if(Y==="\x1B")X="escape";else if(Y==="›")X="csi";else z+=Y;else if(X==="escape")X=Y==="["?"csi":Y==="]"?"osc":Y>=" "&&Y<="/"?"intermediate":"text";else if(X==="intermediate"){if(Y>="0"&&Y<="~")X="text"}else if(X==="csi"){if(Y>="@"&&Y<="~")X="text"}else if(X==="osc"){if(Y==="\x07")X="text";else if(Y==="\x1B")X="osc-escape"}else X=Y==="\\"||Y==="\x07"?"text":Y==="\x1B"?"osc-escape":"osc";return z}function J(V){let z=[...$].map(g6).filter(Boolean).sort((N,U)=>U.length-N.length);if(!z.length){let N=Q;return Q="",N}let Y="",K=0;while(K<Q.length){let N=Q.slice(K);if(!V&&z.some((W)=>W.length>N.length&&W.startsWith(N)))break;let U=z.find((W)=>Q.startsWith(W,K));if(U)Y+="[REDACTED]",K+=U.length;else Y+=Q[K++]}return Q=Q.slice(K),Y}return new j6({transform(V,z,Y){Q+=G(Z.write(V)),Y(null,J(!1))},flush(V){Q+=G(Z.end()),V(null,J(!0))}})}var y6=5000,v6=300,k6=5000,u6=20,m6=4000;class J1{projects;registry;store;active=new Map;pending=new Map;forceAfterMs;detectAfterMs;terminalStopAfterMs;killTree;shareLifecycle;allocatePort;resolveSecrets;upstreamReservations=new Set;retries=new Map;redactionValues=new Set;retryDelayMs;shuttingDown=!1;shutdownPromise;constructor($,Z,Q,X={}){this.projects=$;this.registry=Z;this.store=Q;this.retryDelayMs=X.retryDelayMs??3000,this.forceAfterMs=X.forceAfterMs??y6,this.detectAfterMs=X.detectAfterMs??v6,this.terminalStopAfterMs=X.terminalStopAfterMs??k6,this.killTree=X.killProcessTree??l1,this.shareLifecycle=X.shareLifecycle,this.allocatePort=X.getFreePort??K$,this.resolveSecrets=X.resolveProjectSecrets??z0}start($,Z){let Q=Z.toLowerCase();return this.startSelection($,[Q]).then((X)=>X.find((G)=>G.name===Q)??h(u($,Q),Q,`Project ${$} has no service named ${Z}`))}stop($,Z){return this.cancelRetries($),this.enqueue($,()=>this.stopNow($,Z))}async restart($,Z){let Q=Z.toLowerCase(),X=u($,Q);if(this.shuttingDown)return h(X,Q,"daemon is shutting down");let G=await this.stop(X,"restart");if(!G.ok)return G;return this.start($,Q)}startAll($){return this.startSelection($)}async startSelection($,Z){let Q=this.projects.details($);if(!Q.available)throw new q("invalid",Q.error);let X=u$(Q.commands,Z),G=new Set(X.flat().map((K)=>K.name));if(this.shuttingDown)return Q.commands.filter((K)=>G.has(K.name)).map((K)=>h(u($,K.name),K.name,"daemon is shutting down"));let J=new Map,V=new Map,z=new Map(Q.commands.map((K)=>[K.name,K])),Y=(K)=>{let N=V.get(K.name);if(N)return N;let U=(async()=>{let W=K.after.map((H)=>Y(z.get(H))),C=W.length?await Promise.all(W):[],D=K.after.filter((H,T)=>!C[T].ok);if(D.length)return h(u($,K.name),K.name,`${K.name} was not started because ${D.join(", ")} failed`);let O=u($,K.name),B;try{B=await this.enqueue(O,()=>this.startOne($,K.name,O))}catch(H){if(Z&&H instanceof q)throw H;return h(O,K.name,l(H))}if(!B.ok)return B;let L=Q.commands.some((H)=>H.after.includes(K.name));if(K.ready.type==="tcp"&&!L){let H=K.cwd?X1.resolve(Q.directory,K.cwd):Q.directory;return this.verifyReadiness(K,O,H),B}let _=K.cwd?X1.resolve(Q.directory,K.cwd):Q.directory;return this.verifyReadiness(K,O,_,B)})();return V.set(K.name,U),U};await Promise.all(Q.commands.filter((K)=>G.has(K.name)).map(async(K)=>{let N=await Y(K);J.set(K.name,N)}));for(let K of Q.commands){if(!G.has(K.name)||J.has(K.name))continue;let N=K.after.filter((U)=>!J.get(U)?.ok);J.set(K.name,h(u($,K.name),K.name,N.length?`${K.name} was not started because ${N.join(", ")} failed`:"daemon is shutting down"))}return Q.commands.filter((K)=>G.has(K.name)).map((K)=>J.get(K.name))}async verifyReadiness($,Z,Q,X){let G=this.registry.get(Z),J=this.active.get(Z),V=()=>G!==void 0&&this.registry.get(Z)===G&&(J?this.active.get(Z)===J:G.managedBy==="terminal");if(G)G.readinessCheck=$.ready.type;this.setReadiness(Z,"checking",$.ready.type==="tcp"?"Waiting for the service to listen":"Running configured readiness check"),this.store.log({ts:Date.now(),service:Z,stream:"system",line:`LocalDeck: checking readiness for ${$.name}`});try{let z=J?.commandEnv;if(!z&&G){let N=this.resolveSecrets(G.projectId,$.secrets??[]);for(let U of Object.values(N))this.redactionValues.add(U);z={...this.expandCommandEnv($.env,$.after,G.projectId),...N}}if(await G8($,()=>V()?G:void 0,{cwd:Q,env:z}),!V()||G.status==="stopped"||G.status==="stopping")return h(Z,$.name,"readiness cancelled");let Y=$.ready.type==="tcp"?"Listening on its upstream port":"Configured readiness check passed";if(G.status==="starting")G.status="running";this.setReadiness(Z,"ready",Y),this.store.log({ts:Date.now(),service:Z,stream:"system",line:`LocalDeck: ${$.name} ${$.ready.type==="tcp"?"is listening":"passed its configured readiness check"}`});let K=this.registry.get(Z)??X?.service;return K?A$(K):h(Z,$.name,"service exited before it became ready")}catch(z){let Y=l(z);if(!V()||G.status==="stopped"||G.status==="stopping")return h(Z,$.name,Y);return this.setReadiness(Z,"failed",Y),this.setLastError(Z,Y),await this.stop(Z,"readiness failed"),h(Z,$.name,Y,this.registry.get(Z))}}async stopAll($){let Z=this.projects.details($),Q=new Map(this.registry.list($).filter((J)=>J.status!=="stopped"||J.share!==void 0).map((J)=>[J.key,{key:J.key,name:J.name}]));for(let J of new Set([...this.active.keys(),...this.retries.keys()]))if(J.startsWith(`${$}:`)&&!Q.has(J)){let V=J.slice(J.lastIndexOf(":")+1);Q.set(J,{key:J,name:V})}let X=[];if(Z.available)for(let J of S1(Z.commands)){let V=u($,J.name),z=Q.get(V);if(z)X.push(z),Q.delete(V)}X.push(...Q.values());for(let J of X)this.cancelRetries(J.key);let G=[];for(let J of X)try{G.push(await this.stop(J.key,"stop all"))}catch(V){G.push(h(J.key,J.name,l(V)))}return G}shutdown(){if(this.shutdownPromise)return this.shutdownPromise;this.shuttingDown=!0;for(let $ of this.retries.keys())this.cancelRetries($);return this.shutdownPromise=this.shutdownNow(),this.shutdownPromise}async shutdownNow(){await Promise.allSettled([...this.pending.values()]);let $=await Promise.allSettled([...this.active.keys()].map((Q)=>this.stop(Q,"daemon shutdown")));await Promise.allSettled([...this.pending.values()]);let Z=[];for(let Q of $)if(Q.status==="rejected")Z.push(p6(Q.reason));else if(!Q.value.ok)Z.push(Error(`${Q.value.key}: ${Q.value.error??"stop failed"}`));for(let Q of this.active.values())if(y4(Q.child))Z.push(Error(`${Q.key}: supervised child ${Q.child.pid??"?"} is still running`));if(Z.length)throw AggregateError(Z,"failed to stop all supervised processes during shutdown")}enqueue($,Z){let Q=this.pending.get($),G=(Q?Q.then(Z,Z):Z()).finally(()=>{if(this.pending.get($)===G)this.pending.delete($)});return this.pending.set($,G),G}async startOne($,Z,Q){if(this.shuttingDown)return h(Q,Z,"daemon is shutting down");let X=this.active.get(Q);if(X){if(X.child.exitCode===null&&X.child.signalCode===null){let F=this.registry.get(Q);return F?A$(F):h(Q,Z,"service process has no registry entry")}if(await X.completion,this.active.get(Q)===X)return h(Q,Z,"previous process cleanup is incomplete; stop the service again before restarting")}if(this.retries.get(Q)?.timer)this.cancelRetries(Q);let J=this.registry.get(Q);if(J&&J.status!=="stopped")return A$(J);let V=this.retries.get(Q)??{attempts:0,cancelled:!1};this.retries.set(Q,V);let z=this.projects.resolve($,Z),Y=this.projects.details($);if(!Y.available)throw new q("invalid",Y.error);let K=z.cwd?X1.resolve(Y.directory,z.cwd):Y.directory;try{if(!b6.statSync(K).isDirectory())throw Error("not a directory")}catch{throw new q("invalid",`configured working directory does not exist or is not a directory: ${K}`)}let N;try{N=this.resolveSecrets($,z.secrets??[]);for(let F of Object.values(N))this.redactionValues.add(F)}catch(F){return h(Q,Z,l(F))}let U;try{U=z.upstream??await this.reserveAutomaticUpstream()}catch(F){return h(Q,Z,l(F))}let W=z.upstream===void 0?U:void 0,C;try{C={...this.expandCommandEnv(z.env,z.after,$),...N}}catch(F){return this.releaseAutomaticUpstream(W),h(Q,Z,l(F))}let D;try{D=await this.registry.register({key:Q,projectId:$,projectName:Y.name,projectSlug:Y.slug,name:Z,managedBy:"daemon",stablePort:z.port,upstreamPort:U,upstreamSource:z.upstream===void 0?"assigned":"manual",cwd:K,command:z.run,serviceType:z.serviceType,...Y.activeProfiles?.length?{profiles:Y.activeProfiles}:{},configFingerprint:P0(z)},()=>void this.stop(Q,"stop requested"))}catch(F){return this.releaseAutomaticUpstream(W),h(Q,Z,l(F))}let O=V$(z.run.replaceAll("{port}",String(U))),B=D.serviceType!==void 0&&D.serviceType!=="http",L=B?{}:X8(z.run,K,U);C={...L,...C};for(let F of Object.keys(L))if(C[F]===L[F])this.store.log({ts:Date.now(),service:Q,stream:"system",line:`LocalDeck: supplying assigned port ${U} through ${F}`});let _={...process.env,...C,PORT:String(U),LOCALDECK_PORT:String(D.stablePort),LOCALDECK_SERVICE:D.name,...B?{}:{LOCALDECK_URL:`http://localhost:${D.stablePort}`}};this.setReadiness(Q,"waiting","Waiting for process to listen");let H;try{H=f6(O[0],O.slice(1),{cwd:K,env:_,detached:process.platform!=="win32",stdio:["ignore","pipe","pipe"]})}catch(F){return this.setLastError(Q,l(F)),await this.registry.unregister(Q),this.releaseAutomaticUpstream(W),h(Q,Z,l(F))}let T,A={key:Q,name:Z,child:H,stderr:[],completion:new Promise((F)=>{T=F}),reservedUpstreamPort:W,commandEnv:C};this.active.set(Q,A);let R=!1,M,E=async(F,w,m)=>{if(R)return;R=!0;let p=!1;if(A.detectTimer)clearTimeout(A.detectTimer);this.releaseAutomaticUpstream(A.reservedUpstreamPort);try{if(this.active.get(Q)!==A)return;if(A.stopping){p=!0;return}else if(!await this.cleanupLeaderFirstExit(A))A.cleanupError=Error(`process group ${A.child.pid??"?"} survived forced cleanup after its leader exited`),p=!0;let k=l6(A.stderr),g=this.registry.get(Q)?.status==="starting";if(!A.stopping&&(m||F!==0||w!==null||g&&k)){this.setLastError(Q,k||m?.message||`process exited (${w??`code ${F}`})`);let b=h4(k);if(b)this.store.log({ts:Date.now(),service:Q,stream:"system",line:[b.title,...b.steps].join(`
132
132
  `)})}if(this.store.log({ts:Date.now(),service:Q,stream:"system",line:U$(`process exited (${m?m.message:w??`code ${F}`})`,[...this.redactionValues])}),p){let b=this.registry.get(Q);if(b)b.status="stopping",this.store.emitEvent({type:"service",service:b});return}await this.registry.unregister(Q)}catch(k){A.cleanupError=k,p=!0}finally{if(!p&&this.active.get(Q)===A)this.active.delete(Q);if(T(),!p&&!A.stopping&&!V.cancelled&&!this.shuttingDown&&!["SIGINT","SIGTERM","SIGHUP"].includes(w??"")&&![130,143,129].includes(F??-1))this.scheduleRetry($,Z,Q,V)}};e$(H.stdout.pipe(Q1(this.redactionValues)),(F)=>{this.store.log({ts:Date.now(),service:Q,stream:"stdout",line:$1(F)})}),e$(H.stderr.pipe(Q1(this.redactionValues)),(F)=>{let w=$1(F);if(A.stderr.push(w),A.stderr.length>u6)A.stderr.shift();this.store.log({ts:Date.now(),service:Q,stream:"stderr",line:w})}),H.once("close",(F,w)=>void E(F,w,M)),H.once("error",(F)=>{M=F});try{await new Promise((F,w)=>{H.once("spawn",F),H.once("error",w)})}catch(F){return await A.completion,h(Q,Z,l(A.cleanupError??F))}if(!H.pid){let F=Error(`failed to start ${O[0]}`);return await E(null,null,F),h(Q,Z,F.message)}if(this.registry.setPid(Q,H.pid),z.upstream===void 0)this.scheduleDetection(A,U);return A$(this.registry.get(Q)??D)}cancelRetries($){let Z=this.retries.get($);if(!Z)return;if(Z.cancelled=!0,Z.timer)clearTimeout(Z.timer);let Q=this.registry.get($);if(Q&&!this.active.has($)&&Q.status==="starting")Q.status="stopped",this.store.emitEvent({type:"service",service:Q});this.retries.delete($)}scheduleRetry($,Z,Q,X){if(X.cancelled||this.shuttingDown||X.timer)return;if(X.attempts>=3){let z=this.registry.get(Q)?.lastError;this.setLastError(Q,[z,"Service exited after 3 automatic restart attempts. Start it manually to try again."].filter(Boolean).join(`
133
133
  `)),this.store.log({ts:Date.now(),service:Q,stream:"system",line:"LocalDeck: automatic restart limit reached (3/3)"}),this.retries.delete(Q);return}let G=++X.attempts,J=`Restarting in ${this.retryDelayMs/1000} seconds (attempt ${G}/3)`,V=this.registry.get(Q);if(V)V.status="starting",V.readinessStatus="waiting",V.readinessMessage=J,this.store.emitEvent({type:"service",service:V});this.store.log({ts:Date.now(),service:Q,stream:"system",line:`LocalDeck: ${J}`}),X.timer=setTimeout(()=>{X.timer=void 0,this.enqueue(Q,async()=>{if(X.cancelled||this.shuttingDown)return h(Q,Z,"restart cancelled");let z=this.registry.get(Q);if(z)z.status="stopped";try{let Y=await this.startOne($,Z,Q);if(!Y.ok)this.scheduleRetry($,Z,Q,X);else{let K=this.projects.resolve($,Z),N=this.projects.details($),U=K.cwd?X1.resolve(N.directory,K.cwd):N.directory;this.verifyReadiness(K,Q,U)}return Y}catch(Y){return this.setLastError(Q,l(Y)),this.scheduleRetry($,Z,Q,X),h(Q,Z,l(Y))}})},this.retryDelayMs),X.timer.unref()}async stopNow($,Z){let Q=this.registry.get($),X=Q?.name??$.slice($.lastIndexOf(":")+1);if(Z==="restart"&&Q?.managedBy==="terminal"&&Q.status!=="stopped")return h($,X,"This service is owned by a terminal. Restart it there with Ctrl-C, then rerun its LocalDeck command.");let G=await this.stopShare($,Z),J=this.active.get($);if(!J){if(Q&&Q.status!=="stopped"&&Q.managedBy==="terminal"){let Y=await this.stopTerminal(Q);return G?h($,X,b4(G,Y.error),this.registry.get($)??Q):Y}if(G)return h($,X,G,Q);return{key:$,name:X,ok:!0,...Q?{service:G1(Q)}:{}}}let V=Q?.status==="stopping"?Q.upstreamReady?"running":"starting":Q?.status,z=()=>{J.stopping=!1;let Y=this.registry.get($);if(Y&&this.active.get($)===J&&y4(J.child)&&Y.status==="stopping")Y.status=V??(Y.upstreamReady?"running":"starting"),this.store.emitEvent({type:"service",service:Y})};try{if(J.stopping=!0,Q&&Q.status!=="stopped")Q.status="stopping",this.store.emitEvent({type:"service",service:Q});if(Z)this.store.log({ts:Date.now(),service:$,stream:"system",line:`LocalDeck: stopping ${X} (${Z})`});if(await w0(Promise.resolve().then(()=>this.killTree(J.child,"SIGTERM")),this.forceAfterMs),!await w0(J.completion,this.forceAfterMs)){if(await w0(Promise.resolve().then(()=>this.killTree(J.child,"SIGKILL")),this.forceAfterMs),!await w0(J.completion,this.forceAfterMs))return z(),h($,X,`service did not exit within ${this.forceAfterMs}ms after forced termination`,this.registry.get($))}if(process.platform!=="win32"&&!await this.cleanupLeaderFirstExit(J))throw Error(`process group ${J.child.pid??"?"} survived forced cleanup after its leader exited`);if(J.cleanupError=void 0,await this.registry.unregister($),this.active.get($)===J)this.active.delete($);let K=this.registry.get($);if(G)return h($,X,G,K);return{key:$,name:X,ok:!0,...K?{service:G1(K)}:{}}}catch(Y){return z(),h($,X,b4(G,l(Y)),this.registry.get($))}}async stopShare($,Z){if(!this.shareLifecycle)return;try{await this.shareLifecycle.stop($,Z==="restart"?"service restarting":"service stopping");return}catch(Q){return l(Q)}}async cleanupLeaderFirstExit($){if(!$.child.pid)return!0;if(process.platform==="win32")return await w0(Promise.resolve().then(()=>this.killTree($.child,"SIGTERM")),this.forceAfterMs),!0;if(!k4($.child.pid))return!0;if(await w0(Promise.resolve().then(()=>this.killTree($.child,"SIGTERM")),this.forceAfterMs),await v4($.child.pid,this.forceAfterMs))return!0;return await w0(Promise.resolve().then(()=>this.killTree($.child,"SIGKILL")),this.forceAfterMs),v4($.child.pid,this.forceAfterMs)}async stopTerminal($){let Z=await new Promise((X)=>{let G=!1,J=(Y)=>{if(G)return;G=!0,clearTimeout(z),this.store.off("event",V),X(Y)},V=(Y)=>{if(Y.type==="service"&&Y.service.key===$.key&&Y.service.status==="stopped")J(!0);if(Y.type==="service:removed"&&Y.name===$.key)J(!0)},z=setTimeout(()=>J(!1),this.terminalStopAfterMs);if(z.unref(),this.store.on("event",V),!this.registry.requestStop($.key))J(!1)}),Q=this.registry.get($.key);if(!Z)return h($.key,$.name,`terminal service did not stop within ${this.terminalStopAfterMs}ms`,Q??$);return Q?A$(Q):{key:$.key,name:$.name,ok:!0}}scheduleDetection($,Z){let Q,X,G=0,J=async()=>{if(this.active.get($.key)!==$||$.child.exitCode!==null||$.child.signalCode)return;try{let V=await B$(await C$($.child.pid)),z=k1(V,Z),Y=z?void 0:u1(V);if(Y&&Y!==X)this.store.log({ts:Date.now(),service:$.key,stream:"system",line:`LocalDeck: ${Y}`}),this.setLastError($.key,Y);else if(z&&X&&this.registry.get($.key)?.lastError===X)this.setLastError($.key,void 0);if(X=Y,z){let K=m1(z),N=`${K}:${z.port}`;if(N!==Q)Q=N,this.registry.setUpstream($.key,z.port,K),this.releaseAutomaticUpstream($.reservedUpstreamPort),$.reservedUpstreamPort=void 0;G++}}catch{}if(this.active.get($.key)===$)$.detectTimer=setTimeout(J,Q?Math.min(2000+G*500,1e4):400),$.detectTimer.unref()};$.detectTimer=setTimeout(J,this.detectAfterMs),$.detectTimer.unref()}setLastError($,Z){let Q=this.registry.get($);if(!Q)return;Q.lastError=Z,this.store.emitEvent({type:"service",service:Q})}setReadiness($,Z,Q){let X=this.registry.get($);if(!X)return;X.readinessStatus=Z,X.readinessMessage=Q,this.store.emitEvent({type:"service",service:X})}expandCommandEnv($,Z,Q){if(!$)return{};let X=new Set(Z),G=/\{service:([^}:]+):(port|url)\}/g,J={};for(let[V,z]of Object.entries($))if(J[V]=z.replace(G,(Y,K,N)=>{let U=K.toLowerCase();if(!X.has(U))throw Error(`environment variable ${V} references undeclared prerequisite "${K}"`);let W=this.registry.get(u(Q,U));if(!W)throw Error(`environment variable ${V} references unresolved prerequisite "${K}"`);if(N==="port")return String(W.serviceType&&W.serviceType!=="http"?W.upstreamPort:W.stablePort);if(W.serviceType&&W.serviceType!=="http")throw Error(`environment variable ${V} cannot use a URL for database prerequisite "${K}"`);return`http://localhost:${W.stablePort}`}),J[V].includes("{service:"))throw Error(`environment variable ${V} has an invalid service reference`);return J}async reserveAutomaticUpstream(){for(let $=0;$<32;$++){let Z=await this.allocatePort();if(!Number.isInteger(Z)||Z<1||Z>65535)throw Error("upstream allocator returned an invalid port");if(this.upstreamReservations.has(Z))continue;return this.upstreamReservations.add(Z),Z}throw Error("could not reserve a unique automatic upstream port after 32 attempts")}releaseAutomaticUpstream($){if($!==void 0)this.upstreamReservations.delete($)}}function A$($){return{key:$.key,name:$.name,ok:!0,service:G1($)}}function h($,Z,Q,X,G){return{key:$,name:Z,ok:!1,...X?{service:G1(X)}:{},error:Q,...G?{status:G}:{}}}function G1($){return{...$,urls:[...$.urls],stats:{...$.stats},...$.share?{share:{...$.share}}:{}}}function l6($){return $.join(`
134
- `).slice(-m6)}function l($){return $ instanceof Error?$.message:String($)}function b4($,Z){return[$,Z].filter(Boolean).join("; ")||"stop failed"}function p6($){return $ instanceof Error?$:Error(String($))}function y4($){return $.exitCode===null&&$.signalCode===null}function w0($,Z){return new Promise((Q)=>{let X=setTimeout(()=>Q(!1),Z);$.then(()=>{clearTimeout(X),Q(!0)},()=>{clearTimeout(X),Q(!0)})})}function k4($){try{return process.kill(-$,0),!0}catch(Z){return Z.code==="EPERM"}}async function v4($,Z){let Q=Date.now()+Z;while(k4($)){if(Date.now()>=Q)return!1;await new Promise((X)=>setTimeout(X,Math.min(20,Z)))}return!0}var u4="1.7.0";var l4=u4;async function uX($={}){J$(),y$();let Z={createStore:()=>new Z8,createRegistry:(M,E)=>new a1(M,E,(F)=>Y.nickname(F)),createShareManager:(M,E)=>new v1(M,E),createProjectRegistry:(M)=>new l$({catalogFile:M}),createProcessSupervisor:(M,E,F,w)=>new J1(M,E,F,{shareLifecycle:w}),createApiServer:L4,writePrivateState:K0,...$.dependencies},Q=$.homeDir?m4.join($.homeDir,"daemon.json"):b$,X=$.homeDir?m4.join($.homeDir,"projects.json"):Q$,G=$.apiPort??G$,J=Z.createStore(),V=Z.createRegistry(J,G),z=Z.createShareManager(V,J),Y=Z.createProjectRegistry(X),K=Z.createProcessSupervisor(Y,V,J,z),N=n6(),U=Date.now(),W=i6.randomBytes(32).toString("base64url"),C=!1,D,O,B,L=new Promise((M,E)=>{O=M,B=E});L.catch(()=>{});let _,H=!1,T,A=(M,E)=>{C=!0;let F=[],w=(g)=>{try{return Promise.resolve(g())}catch(b){F.push(p4(b));return}},m=w(()=>z.stopAll()),p=w(()=>K.shutdown()),k=w(async()=>{if(await E,_?.listening)await new Promise((g,b)=>_.close((D0)=>D0?b(D0):g()))});return(async()=>{let g=async(b)=>{if(!b)return;try{await b}catch(D0){F.push(p4(D0))}};return await g(m),await g(p),await g(k),await g(w(()=>N.waitForIdle())),await g(w(()=>V.closeAll())),await g(w(()=>J.close())),await g(w(()=>{if(M==="failed-write"){if(!H)return;if(X0.rmSync(`${Q}.${process.pid}.tmp`,{force:!0}),T)c6(Q,T.contents,T.mode);else X0.rmSync(Q,{force:!0});return}if(r(Q,null)?.pid===process.pid)X0.unlinkSync(Q)})),F})()},R=(M)=>{if(D)return D;return C=!0,D=A("owned",M).then((E)=>{if(E.length)throw AggregateError(E,"daemon shutdown cleanup failed")}),D.then(O,B),D};_=Z.createApiServer({registry:V,store:J,shares:z,projects:Y,supervisor:K,controlToken:W,isShuttingDown:()=>C,trackAttachOperation:N.track,dashboardDir:$.dashboardDir,allowedBrowserOrigins:$.allowedBrowserOrigins,version:l4,startedAt:U,shutdown:R,listProjectSecrets:A0,setProjectSecret:D$,deleteProjectSecret:O$,resolveProjectSecrets:z0});try{if(await new Promise((M,E)=>{_.once("error",E),_.listen(G,"127.0.0.1",()=>{_.off("error",E),M()})}),_.on("error",(M)=>console.error(`LocalDeck: API server error: ${M.message}`)),X0.existsSync(Q)){let M=X0.statSync(Q);T={contents:X0.readFileSync(Q),mode:M.mode&511}}return H=!0,Z.writePrivateState(Q,{pid:process.pid,apiPort:G,startedAt:U,version:l4,controlToken:W}),{apiPort:G,stop:R,stopped:L}}catch(M){let E=await A("failed-write");if(E.length)throw AggregateError([M,...E],"daemon startup failed and cleanup encountered errors",{cause:M});throw M}}function c6($,Z,Q){let X=`${$}.${process.pid}.restore.tmp`;X0.writeFileSync(X,Z,{mode:Q}),X0.chmodSync(X,Q),X0.renameSync(X,$)}function p4($){return $ instanceof Error?$:Error(String($))}function n6(){let $=new Set;return{track:(X)=>{return $.add(X),X.then(()=>$.delete(X),()=>$.delete(X)),X},waitForIdle:async()=>{while($.size)await Promise.allSettled([...$])}}}async function J8($=b$){let Z;try{Z=JSON.parse(X0.readFileSync($,"utf8"))}catch(Q){let X=Q.code;if(X==="EACCES"||X==="EPERM")throw Error(`Cannot read LocalDeck daemon state at ${$}: permission denied. The daemon may still be running under another user (often after sudo). If it was started with sudo, run sudo localdeck daemon stop, then localdeck daemon start without sudo. Do not make the state file world-readable; it contains a private control token.`);if(X==="ENOENT"||Q instanceof SyntaxError)return null;throw Error(`Cannot read LocalDeck daemon state at ${$}${X?` (${X})`:""}. Check the file and directory permissions.`)}if(!Z)return null;try{let Q=await fetch(`http://127.0.0.1:${Z.apiPort}/api/status`,{signal:AbortSignal.timeout(1000)});if(!Q.ok)return null;return(await Q.json()).pid===Z.pid?Z:null}catch{return null}}import{spawn as a6,spawnSync as o6}from"node:child_process";import V1 from"node:fs";import j0 from"node:path";import{fileURLToPath as d4}from"node:url";function VG(){let $=j0.dirname(d4(import.meta.url));return[j0.resolve($,"../dashboard"),j0.resolve($,"../../dashboard/dist")].find((Q)=>V1.existsSync(j0.join(Q,"index.html")))}function s6(){let $=process.argv[1];if(Boolean(process.versions.bun)){let Q=j0.resolve(j0.dirname(d4(import.meta.url)),"../dist/index.js"),X=o6("node",["--version"],{stdio:"ignore"}).status===0;if(V1.existsSync(Q)&&X)return["node",[Q,"daemon","run"]];console.warn("LocalDeck: starting daemon under Bun — WebSocket proxying (HMR) will not work. Run `bun run build` and make sure `node` is on PATH.")}if(!$||$.startsWith("/$bunfs")||$.includes("~BUN"))return[process.execPath,["daemon","run"]];return[process.execPath,[$,"daemon","run"]]}async function YG(){J$();let $=await J8();if($)return $;V1.mkdirSync(j0.dirname(X$),{recursive:!0});let Z=V1.openSync(X$,"a"),[Q,X]=s6();a6(Q,X,{detached:!0,stdio:["ignore",Z,Z],env:process.env}).unref();let J=Date.now()+8000;while(Date.now()<J){await new Promise((z)=>setTimeout(z,150));let V=await J8();if(V)return V}throw Error(`LocalDeck daemon did not start on port ${G$}. See ${X$}`)}class t6{port;fetch;timeoutMs;constructor($,Z=globalThis.fetch,Q){this.port=$;this.fetch=Z;this.timeoutMs=Q}get base(){return`http://127.0.0.1:${this.port}`}async call($,Z,Q,X){let G=await this.fetch(this.base+Z,{method:$,...this.timeoutMs?{signal:AbortSignal.timeout(this.timeoutMs)}:{},headers:{...Q?{"content-type":"application/json"}:{},...X},body:Q?JSON.stringify(Q):void 0}),J=await G.json().catch(()=>({}));if(!G.ok){let V=Array.isArray(J.alternatives)&&J.alternatives.every((z)=>typeof z==="string")?`; alternatives: ${J.alternatives.join(", ")}`:"";throw Error(`${J.error??`${$} ${Z} → ${G.status}`}${V}`)}return J}projects=()=>this.call("GET","/api/projects");project=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}`);timeline=($,Z={})=>{let Q=new URLSearchParams;if(Z.services)Q.set("services",Z.services.join(","));for(let X of["filter","query","cursor","limit"])if(Z[X]!==void 0)Q.set(X,String(Z[X]));return this.call("GET",`/api/projects/${encodeURIComponent($)}/activity?${Q}`)};markBaseline=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/baselines`,Z);baselines=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/baselines`);compareBaseline=($,Z)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/baselines/${encodeURIComponent(Z)}`);environments=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/environments`);registerEnvironment=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/environments/${encodeURIComponent(Z)}/register`,{});exportRequest=($,Z)=>this.call("GET",`/api/services/${encodeURIComponent($)}/reproduction?requestId=${encodeURIComponent(Z)}`);saveCheck=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/checks`,Z);checks=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/checks`);runCheck=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/checks/${encodeURIComponent(Z)}/run`,{});serviceAction=($,Z,Q)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/services/${encodeURIComponent(Z)}/${Q}`,{});shareInfo=($)=>this.call("GET",`/api/services/${encodeURIComponent($)}/share`);replay=($,Z)=>this.call("POST",`/api/services/${encodeURIComponent($)}/replay`,{requestId:Z});services=()=>this.call("GET","/api/services");forwarder=()=>this.call("GET","/api/forwarder");profiles=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/profiles`);setActiveProfiles=($,Z)=>this.call("PUT",`/api/projects/${encodeURIComponent($)}/profiles/active`,{profiles:Z});rememberProject=($,Z)=>this.call("POST","/api/projects/remember",{file:$},{authorization:`Bearer ${Z}`});async servicePath($){let Z=$.lastIndexOf("/");if(Z===-1)return encodeURIComponent($);let Q=$.slice(0,Z).toLowerCase(),X=$.slice(Z+1).toLowerCase(),G=(await this.services()).filter((J)=>J.name===X&&(J.projectId.toLowerCase()===Q||J.projectName.toLowerCase()===Q||J.projectSlug.toLowerCase()===Q));if(G.length===1)return encodeURIComponent(G[0].key);if(G.length>1)throw Error(`service reference "${$}" is ambiguous; alternatives: ${G.map((J)=>J.key).join(", ")}`);return encodeURIComponent($)}service=async($)=>this.call("GET",`/api/services/${await this.servicePath($)}`);logs=async($,Z)=>this.call("GET",`/api/services/${await this.servicePath($)}/logs?limit=${Z}`);response=($,Z)=>this.call("GET",`/api/services/${encodeURIComponent($)}/response?requestId=${encodeURIComponent(Z)}`);requests=async($,Z)=>this.call("GET",`/api/services/${await this.servicePath($)}/requests?limit=${Z}`);stop=async($)=>this.call("POST",`/api/services/${await this.servicePath($)}/stop`);share=async($,Z,Q=!1,X=!1)=>this.call("POST",`/api/services/${await this.servicePath($)}/share${Q?"/new":""}`,X?{public:!0}:{password:Z});unshare=async($)=>this.call("DELETE",`/api/services/${await this.servicePath($)}/share`);shutdown=()=>this.call("POST","/api/shutdown")}
134
+ `).slice(-m6)}function l($){return $ instanceof Error?$.message:String($)}function b4($,Z){return[$,Z].filter(Boolean).join("; ")||"stop failed"}function p6($){return $ instanceof Error?$:Error(String($))}function y4($){return $.exitCode===null&&$.signalCode===null}function w0($,Z){return new Promise((Q)=>{let X=setTimeout(()=>Q(!1),Z);$.then(()=>{clearTimeout(X),Q(!0)},()=>{clearTimeout(X),Q(!0)})})}function k4($){try{return process.kill(-$,0),!0}catch(Z){return Z.code==="EPERM"}}async function v4($,Z){let Q=Date.now()+Z;while(k4($)){if(Date.now()>=Q)return!1;await new Promise((X)=>setTimeout(X,Math.min(20,Z)))}return!0}var u4="1.7.1";var l4=u4;async function uX($={}){J$(),y$();let Z={createStore:()=>new Z8,createRegistry:(M,E)=>new a1(M,E,(F)=>Y.nickname(F)),createShareManager:(M,E)=>new v1(M,E),createProjectRegistry:(M)=>new l$({catalogFile:M}),createProcessSupervisor:(M,E,F,w)=>new J1(M,E,F,{shareLifecycle:w}),createApiServer:L4,writePrivateState:K0,...$.dependencies},Q=$.homeDir?m4.join($.homeDir,"daemon.json"):b$,X=$.homeDir?m4.join($.homeDir,"projects.json"):Q$,G=$.apiPort??G$,J=Z.createStore(),V=Z.createRegistry(J,G),z=Z.createShareManager(V,J),Y=Z.createProjectRegistry(X),K=Z.createProcessSupervisor(Y,V,J,z),N=n6(),U=Date.now(),W=i6.randomBytes(32).toString("base64url"),C=!1,D,O,B,L=new Promise((M,E)=>{O=M,B=E});L.catch(()=>{});let _,H=!1,T,A=(M,E)=>{C=!0;let F=[],w=(g)=>{try{return Promise.resolve(g())}catch(b){F.push(p4(b));return}},m=w(()=>z.stopAll()),p=w(()=>K.shutdown()),k=w(async()=>{if(await E,_?.listening)await new Promise((g,b)=>_.close((D0)=>D0?b(D0):g()))});return(async()=>{let g=async(b)=>{if(!b)return;try{await b}catch(D0){F.push(p4(D0))}};return await g(m),await g(p),await g(k),await g(w(()=>N.waitForIdle())),await g(w(()=>V.closeAll())),await g(w(()=>J.close())),await g(w(()=>{if(M==="failed-write"){if(!H)return;if(X0.rmSync(`${Q}.${process.pid}.tmp`,{force:!0}),T)c6(Q,T.contents,T.mode);else X0.rmSync(Q,{force:!0});return}if(r(Q,null)?.pid===process.pid)X0.unlinkSync(Q)})),F})()},R=(M)=>{if(D)return D;return C=!0,D=A("owned",M).then((E)=>{if(E.length)throw AggregateError(E,"daemon shutdown cleanup failed")}),D.then(O,B),D};_=Z.createApiServer({registry:V,store:J,shares:z,projects:Y,supervisor:K,controlToken:W,isShuttingDown:()=>C,trackAttachOperation:N.track,dashboardDir:$.dashboardDir,allowedBrowserOrigins:$.allowedBrowserOrigins,version:l4,startedAt:U,shutdown:R,listProjectSecrets:A0,setProjectSecret:D$,deleteProjectSecret:O$,resolveProjectSecrets:z0});try{if(await new Promise((M,E)=>{_.once("error",E),_.listen(G,"127.0.0.1",()=>{_.off("error",E),M()})}),_.on("error",(M)=>console.error(`LocalDeck: API server error: ${M.message}`)),X0.existsSync(Q)){let M=X0.statSync(Q);T={contents:X0.readFileSync(Q),mode:M.mode&511}}return H=!0,Z.writePrivateState(Q,{pid:process.pid,apiPort:G,startedAt:U,version:l4,controlToken:W}),{apiPort:G,stop:R,stopped:L}}catch(M){let E=await A("failed-write");if(E.length)throw AggregateError([M,...E],"daemon startup failed and cleanup encountered errors",{cause:M});throw M}}function c6($,Z,Q){let X=`${$}.${process.pid}.restore.tmp`;X0.writeFileSync(X,Z,{mode:Q}),X0.chmodSync(X,Q),X0.renameSync(X,$)}function p4($){return $ instanceof Error?$:Error(String($))}function n6(){let $=new Set;return{track:(X)=>{return $.add(X),X.then(()=>$.delete(X),()=>$.delete(X)),X},waitForIdle:async()=>{while($.size)await Promise.allSettled([...$])}}}async function J8($=b$){let Z;try{Z=JSON.parse(X0.readFileSync($,"utf8"))}catch(Q){let X=Q.code;if(X==="EACCES"||X==="EPERM")throw Error(`Cannot read LocalDeck daemon state at ${$}: permission denied. The daemon may still be running under another user (often after sudo). If it was started with sudo, run sudo localdeck daemon stop, then localdeck daemon start without sudo. Do not make the state file world-readable; it contains a private control token.`);if(X==="ENOENT"||Q instanceof SyntaxError)return null;throw Error(`Cannot read LocalDeck daemon state at ${$}${X?` (${X})`:""}. Check the file and directory permissions.`)}if(!Z)return null;try{let Q=await fetch(`http://127.0.0.1:${Z.apiPort}/api/status`,{signal:AbortSignal.timeout(1000)});if(!Q.ok)return null;return(await Q.json()).pid===Z.pid?Z:null}catch{return null}}import{spawn as a6,spawnSync as o6}from"node:child_process";import V1 from"node:fs";import j0 from"node:path";import{fileURLToPath as d4}from"node:url";function VG(){let $=j0.dirname(d4(import.meta.url));return[j0.resolve($,"../dashboard"),j0.resolve($,"../../dashboard/dist")].find((Q)=>V1.existsSync(j0.join(Q,"index.html")))}function s6(){let $=process.argv[1];if(Boolean(process.versions.bun)){let Q=j0.resolve(j0.dirname(d4(import.meta.url)),"../dist/index.js"),X=o6("node",["--version"],{stdio:"ignore"}).status===0;if(V1.existsSync(Q)&&X)return["node",[Q,"daemon","run"]];console.warn("LocalDeck: starting daemon under Bun — WebSocket proxying (HMR) will not work. Run `bun run build` and make sure `node` is on PATH.")}if(!$||$.startsWith("/$bunfs")||$.includes("~BUN"))return[process.execPath,["daemon","run"]];return[process.execPath,[$,"daemon","run"]]}async function YG(){J$();let $=await J8();if($)return $;V1.mkdirSync(j0.dirname(X$),{recursive:!0});let Z=V1.openSync(X$,"a"),[Q,X]=s6();a6(Q,X,{detached:!0,stdio:["ignore",Z,Z],env:process.env}).unref();let J=Date.now()+8000;while(Date.now()<J){await new Promise((z)=>setTimeout(z,150));let V=await J8();if(V)return V}throw Error(`LocalDeck daemon did not start on port ${G$}. See ${X$}`)}class t6{port;fetch;timeoutMs;constructor($,Z=globalThis.fetch,Q){this.port=$;this.fetch=Z;this.timeoutMs=Q}get base(){return`http://127.0.0.1:${this.port}`}async call($,Z,Q,X){let G=await this.fetch(this.base+Z,{method:$,...this.timeoutMs?{signal:AbortSignal.timeout(this.timeoutMs)}:{},headers:{...Q?{"content-type":"application/json"}:{},...X},body:Q?JSON.stringify(Q):void 0}),J=await G.json().catch(()=>({}));if(!G.ok){let V=Array.isArray(J.alternatives)&&J.alternatives.every((z)=>typeof z==="string")?`; alternatives: ${J.alternatives.join(", ")}`:"";throw Error(`${J.error??`${$} ${Z} → ${G.status}`}${V}`)}return J}projects=()=>this.call("GET","/api/projects");project=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}`);timeline=($,Z={})=>{let Q=new URLSearchParams;if(Z.services)Q.set("services",Z.services.join(","));for(let X of["filter","query","cursor","limit"])if(Z[X]!==void 0)Q.set(X,String(Z[X]));return this.call("GET",`/api/projects/${encodeURIComponent($)}/activity?${Q}`)};markBaseline=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/baselines`,Z);baselines=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/baselines`);compareBaseline=($,Z)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/baselines/${encodeURIComponent(Z)}`);environments=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/environments`);registerEnvironment=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/environments/${encodeURIComponent(Z)}/register`,{});exportRequest=($,Z)=>this.call("GET",`/api/services/${encodeURIComponent($)}/reproduction?requestId=${encodeURIComponent(Z)}`);saveCheck=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/checks`,Z);checks=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/checks`);runCheck=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/checks/${encodeURIComponent(Z)}/run`,{});serviceAction=($,Z,Q)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/services/${encodeURIComponent(Z)}/${Q}`,{});shareInfo=($)=>this.call("GET",`/api/services/${encodeURIComponent($)}/share`);replay=($,Z)=>this.call("POST",`/api/services/${encodeURIComponent($)}/replay`,{requestId:Z});services=()=>this.call("GET","/api/services");forwarder=()=>this.call("GET","/api/forwarder");profiles=($)=>this.call("GET",`/api/projects/${encodeURIComponent($)}/profiles`);setActiveProfiles=($,Z)=>this.call("PUT",`/api/projects/${encodeURIComponent($)}/profiles/active`,{profiles:Z});rememberProject=($,Z)=>this.call("POST","/api/projects/remember",{file:$},{authorization:`Bearer ${Z}`});async servicePath($){let Z=$.lastIndexOf("/");if(Z===-1)return encodeURIComponent($);let Q=$.slice(0,Z).toLowerCase(),X=$.slice(Z+1).toLowerCase(),G=(await this.services()).filter((J)=>J.name===X&&(J.projectId.toLowerCase()===Q||J.projectName.toLowerCase()===Q||J.projectSlug.toLowerCase()===Q));if(G.length===1)return encodeURIComponent(G[0].key);if(G.length>1)throw Error(`service reference "${$}" is ambiguous; alternatives: ${G.map((J)=>J.key).join(", ")}`);return encodeURIComponent($)}service=async($)=>this.call("GET",`/api/services/${await this.servicePath($)}`);logs=async($,Z)=>this.call("GET",`/api/services/${await this.servicePath($)}/logs?limit=${Z}`);response=($,Z)=>this.call("GET",`/api/services/${encodeURIComponent($)}/response?requestId=${encodeURIComponent(Z)}`);requests=async($,Z)=>this.call("GET",`/api/services/${await this.servicePath($)}/requests?limit=${Z}`);stop=async($)=>this.call("POST",`/api/services/${await this.servicePath($)}/stop`);share=async($,Z,Q=!1,X=!1)=>this.call("POST",`/api/services/${await this.servicePath($)}/share${Q?"/new":""}`,X?{public:!0}:{password:Z});unshare=async($)=>this.call("DELETE",`/api/services/${await this.servicePath($)}/share`);shutdown=()=>this.call("POST","/api/shutdown")}
135
135
  export{O0 as J,d as K,r6 as L,y as M,TZ as N,o as O,b$ as P,G$ as Q,J$ as R,Y$ as S,K$ as T,K5 as U,z5 as V,q3 as W,L0 as X,I1 as Y,V$ as Z,U$ as _,c$ as $,A0 as aa,z0 as ba,L5 as ca,u as da,C$ as ea,B$ as fa,k1 as ga,u1 as ha,m1 as ia,e$ as ja,l1 as ka,$1 as la,h4 as ma,X8 as na,u$ as oa,G8 as pa,Q1 as qa,l4 as ra,uX as sa,J8 as ta,VG as ua,YG as va,t6 as wa};
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import{M as $0,N as d,O as H1,Q as J1,S as Q1,T as a0,V as I0,W as A0,X as x0,Y as y0,Z as b0,ba as n0,ca as k0,da as C0,ea as _0,fa as M0,ga as O0,ha as D0,ia as G0,ja as s0,ka as L0,la as R0,ma as r0,na as e0,oa as q0,pa as $1,qa as Y1,ra as V0,sa as U1,ta as Y0,ua as z1,va as u,wa as K0}from"./index-2da1tyad.js";import{spawn as x1}from"node:child_process";import y1 from"node:crypto";import{parseArgs as v0}from"node:util";import{spawn as V1}from"node:child_process";import W1 from"node:fs";var q1=process.stdout.isTTY&&!process.env.NO_COLOR,v=($)=>(Y)=>q1?`\x1B[${$}m${Y}\x1B[0m`:Y,U={bold:v(1),dim:v(2),red:v(31),green:v(32),yellow:v(33),cyan:v(36),magenta:v(35),blue:v(34)};function M($){console.error(`${U.red("error")} ${$}`),process.exit(1)}function i($,Y){let K=[Y,...$],X=Y.map((q,z)=>Math.max(...K.map((W)=>c0(W[z]??"")))),Q=(q)=>q.map((z,W)=>z+" ".repeat(X[W]-c0(z))).join(" ");return[U.dim(Q(Y)),...$.map(Q)].join(`
1
+ import{M as $0,N as d,O as H1,Q as J1,S as Q1,T as a0,V as I0,W as A0,X as x0,Y as y0,Z as b0,ba as n0,ca as k0,da as C0,ea as _0,fa as M0,ga as O0,ha as D0,ia as G0,ja as s0,ka as L0,la as R0,ma as r0,na as e0,oa as q0,pa as $1,qa as Y1,ra as V0,sa as U1,ta as Y0,ua as z1,va as u,wa as K0}from"./index-scnd2pq4.js";import{spawn as x1}from"node:child_process";import y1 from"node:crypto";import{parseArgs as v0}from"node:util";import{spawn as V1}from"node:child_process";import W1 from"node:fs";var q1=process.stdout.isTTY&&!process.env.NO_COLOR,v=($)=>(Y)=>q1?`\x1B[${$}m${Y}\x1B[0m`:Y,U={bold:v(1),dim:v(2),red:v(31),green:v(32),yellow:v(33),cyan:v(36),magenta:v(35),blue:v(34)};function M($){console.error(`${U.red("error")} ${$}`),process.exit(1)}function i($,Y){let K=[Y,...$],X=Y.map((q,z)=>Math.max(...K.map((W)=>c0(W[z]??"")))),Q=(q)=>q.map((z,W)=>z+" ".repeat(X[W]-c0(z))).join(" ");return[U.dim(Q(Y)),...$.map(Q)].join(`
2
2
  `)}var c0=($)=>$.replace(/\x1b\[[0-9;]*m/g,"").length;function F0($){let Y=Math.max(0,Math.round((Date.now()-$)/1000));if(Y<60)return`${Y}s`;if(Y<3600)return`${Math.round(Y/60)}m`;if(Y<86400)return`${Math.round(Y/3600)}h`;return`${Math.round(Y/86400)}d`}async function o0($,Y,K=fetch,X=console.log){if(Y)X("LocalDeck: preparing app links. macOS may ask once to allow localhost port 80; cancelling keeps port-number links.");try{let Q=await K(`http://127.0.0.1:${$}/api/forwarder`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({install:Y,automatic:!0}),signal:AbortSignal.timeout(135000)}),q=await Q.json();if(Q.ok&&q?.ready===!0)return!0;if(Y)X(`LocalDeck: using port-number links. ${q?.error??"Forwarding is unavailable."}`)}catch{if(Y)X("LocalDeck: using port-number links; forwarding setup was unavailable.")}return!1}var t0=8000,S1=500,_1=1000;async function M1($,Y={}){let K={ensureDaemon:u,getFreePort:a0,createWebSocket:(_,D)=>new d(_,D),spawn:V1,fetch:globalThis.fetch,...Y};if(!$.command.length)throw Error(`nothing to run for "${$.name}"`);let X=$.cwd??process.cwd();try{if(!W1.statSync(X).isDirectory())throw Error("not a directory")}catch{throw Error(`working directory does not exist or is not a directory: ${X}`)}let Q=await K.ensureDaemon(),q=$.project??{id:"standalone",name:"standalone",slug:"standalone"},z={},W=K.resolveProjectSecrets??n0;if($.secrets?.length&&q.id!=="standalone")z=W(q.id,$.secrets);let G=$.upstreamPort??await K.getFreePort(),B=$.color??U.cyan,Z=$.prefix?B(`[${$.name}] `):"",V=await L1($.env,$.after??[],q.id,Q.apiPort,K.fetch);V={...V,...z};let S=K.createWebSocket(`ws://127.0.0.1:${Q.apiPort}/api/attach`,{headers:{authorization:`Bearer ${Q.controlToken}`}}),H=(_)=>S.readyState===d.OPEN&&S.send(JSON.stringify(_)),J=await new Promise((_,D)=>{S.once("open",()=>{H({type:"register",key:C0(q.id,$.name.toLowerCase()),projectId:q.id,projectName:q.name,projectSlug:q.slug,name:$.name,managedBy:"terminal",stablePort:$.stablePort,upstreamPort:G,upstreamSource:$.upstreamPort===void 0?"assigned":"manual",cwd:X,command:$.displayCommand??$.command.join(" "),...$.project?{profiles:$.profiles??[]}:{}})}),S.on("message",(C)=>{let I=JSON.parse(C.toString());if(I.type==="registered")_(I.service);else if(I.type==="error")D(Error(I.message))}),S.once("error",D)}),O=$.command.map((_)=>_.replaceAll("{port}",String(G))),L=J.serviceType!==void 0&&J.serviceType!=="http",N=L?{}:e0($.displayCommand??$.command,X,G);V={...N,...V};for(let _ of Object.keys(N))if(V[_]===N[_]){let D=`LocalDeck: supplying assigned port ${G} through ${_}`;console.log(`${Z}${U.dim(D)}`),H({type:"log",stream:"stdout",line:D})}let R={...process.env,...V,...z,PORT:String(G),LOCALDECK_PORT:String(J.stablePort),LOCALDECK_SERVICE:J.name,...L?{}:{LOCALDECK_URL:`http://localhost:${J.stablePort}`}},b=new Set(Object.values(z));if(L)console.log(`${Z}${U.bold("LocalDeck")} ${U.dim("›")} ${B(J.name)} ${U.dim("→")} ${U.green(`database localhost:${J.upstreamPort}`)} ${U.dim("(published port · no HTTP proxy)")}`);else{let _=$.cleanUrls?J.urls[0].replace(/^(http:\/\/[a-z0-9-]+(?:\.[a-z0-9-]+)?\.localhost):\d+(?=\/|$)/i,"$1"):J.urls[0];console.log(`${Z}${U.bold("LocalDeck")} ${U.dim("›")} ${B(J.name)} ${U.dim("→")} ${U.green(_)} ${U.dim(`(also ${J.urls[1]} · dashboard http://localhost:${Q.apiPort})`)}`)}let B0=process.platform!=="win32",F,h=(_,D,C)=>{let I=b.size?_.pipe(Y1(b)):_;I.on("data",(g)=>{let y=R0(g.toString());if(w=(w+y).slice(-16000),$.prefix)C.write(y.replace(/^(?=.)/gm,Z));else C.write(g)}),s0(I,(g)=>{for(let y of N1(R0(g)))H({type:"log",stream:D,line:y})})},x=!1,w="",o=(_)=>{if(x)return;let D=_.toString();if(/EADDRINUSE|address already in use|already in use/i.test(D)&&D.includes(String(J.stablePort)))x=!0,console.error(`${Z}${U.yellow(`LocalDeck: your process tried to use port ${J.stablePort}, which LocalDeck is holding as the stable port for "${J.name}".`)}`),console.error(`${Z}${U.yellow(` Fix: run without --port (LocalDeck finds the tool's own port automatically), or pick a different stable port, e.g. --port ${J.stablePort+1000}.`)}`)},H0,t,u0,p,a=0,n=!1,j=!1,W0,k,f=!1,J0,G1=new Promise((_)=>{J0=_}),m0=(_)=>W0??=O1(F,_),l0=async(_)=>{if(f||n||!k)return;if(n=!0,!await m0(_)){W0=void 0,n=!1,j=!1,console.error(`${Z}${U.red("LocalDeck: process descendants survived cleanup; retry Stop")}`);return}if(f)return;if(H0)clearTimeout(H0);H({type:"log",stream:"stderr",line:`process exited (${k.signal??`code ${k.code}`})`});let D=["SIGINT","SIGTERM","SIGHUP"].includes(k.signal??"")||[130,143,129].includes(k.code??-1);if(!j&&!D&&a<3&&S.readyState===d.OPEN){let C=`LocalDeck: restarting in ${(K.retryDelayMs??3000)/1000} seconds (attempt ${++a}/3)`;console.log(`${Z}${U.yellow(C)}`),H({type:"log",stream:"stderr",line:C}),H({type:"readiness",status:"checking",message:C}),p=setTimeout(()=>{if(p=void 0,j||f)return;try{p0()}catch(I){f=!0,console.error(`${Z}${U.red(`LocalDeck: restart failed: ${I instanceof Error?I.message:I}`)}`),S.close(),J0(1)}},K.retryDelayMs??3000),n=!1;return}if(!j&&!D&&a===3)console.error(`${Z}${U.red("LocalDeck: automatic restart limit reached (3/3). Start the service manually to try again.")}`),H({type:"log",stream:"stderr",line:"LocalDeck: automatic restart limit reached (3/3). Start the service manually to try again."});f=!0,setTimeout(()=>{S.close(),J0(k.code??(k.signal?1:0))},50)},U0=(_="SIGTERM")=>{if(f||j)return;if(j=!0,p)clearTimeout(p),p=void 0;m0(_).then(()=>l0(_))};S.on("message",(_)=>{let D=JSON.parse(_.toString());if(D.type==="error")console.error(`${Z}${U.yellow(`LocalDeck: ${D.message}`)}`),t=void 0;else if(D.type==="stop")console.log(`${Z}${U.dim("LocalDeck: stop requested from dashboard/CLI")}`),U0()}),S.on("close",()=>{if(p){U0();return}if(!j&&!f)console.error(`${Z}${U.yellow("LocalDeck: lost connection to daemon; the stable port is no longer proxied. Process keeps running.")}`)});function p0(){if(a>0&&$.secrets?.length&&q.id!=="standalone"){z=W(q.id,$.secrets);for(let _ of Object.values(z))b.add(_);V={...V,...z},R={...process.env,...V,PORT:String(G),LOCALDECK_PORT:String(J.stablePort),LOCALDECK_SERVICE:J.name,...L?{}:{LOCALDECK_URL:`http://localhost:${J.stablePort}`}}}if(k=void 0,W0=void 0,n=!1,t=void 0,w="",x=!1,F=K.spawn(O[0],O.slice(1),{cwd:X,env:R,stdio:[$.prefix?"ignore":"inherit","pipe","pipe"],shell:!B0,detached:B0}),F.pid)H({type:"pid",pid:F.pid});if(h(F.stdout,"stdout",process.stdout),h(F.stderr,"stderr",process.stderr),F.stdout.on("data",o),F.stderr.on("data",o),!$.upstreamPort&&F.pid){let _=F,D=F.pid,C=0,I=async()=>{if(F!==_||F.exitCode!==null||F.signalCode)return;try{let g=await M0(await _0(D)),y=O0(g,G),s=y?void 0:D0(g);if(s&&s!==u0)console.error(`${Z}${U.yellow(`LocalDeck: ${s}`)}`),H({type:"log",stream:"stderr",line:`LocalDeck: ${s}`});if(u0=s,y){let S0=`${G0(y)}:${y.port}`;if(S0!==t){if(t=S0,H({type:"upstream",port:y.port,host:G0(y)}),y.port!==G)console.log(`${Z}${U.dim(`LocalDeck: process is listening on ${S0} (ignored $PORT) — ${J.urls[0]} now points there`)}`)}C++}}catch{}if(F!==_||F.exitCode!==null||j||k)return;H0=setTimeout(I,t?Math.min(2000+C*500,1e4):400)};H0=setTimeout(I,300)}if(F.on("exit",(_,D)=>{if(_!==0&&!x){let C=r0(w);if(C)console.error(`${Z}${U.yellow(["LocalDeck: "+C.title,...C.steps].join(`
3
3
  `))}`)}k={code:_,signal:D},l0("SIGTERM")}),F.on("error",(_)=>{j=!0,f=!0,console.error(`${Z}${U.red(`LocalDeck: failed to start "${O[0]}": ${_.message}`)}`),S.close(),J0(1)}),a>0)i0().catch(()=>U0())}p0();let z0=$.ready,i0=()=>z0?(async()=>{H({type:"readiness",status:"checking",message:z0.type==="tcp"?"Waiting for the service to listen":"Running configured readiness check"});try{let _=await $1({name:J.name,run:$.displayCommand??$.command.join(" "),tags:[],after:$.after??[],ready:z0},async()=>{let D=await K.fetch(`http://127.0.0.1:${Q.apiPort}/api/services/${encodeURIComponent(J.key)}`);if(D.status===404)return;if(!D.ok)throw Error(`readiness status request failed (${D.status})`);return D.json()},{cwd:X,env:V});return H({type:"readiness",status:"ready",message:z0.type==="tcp"?"Listening on its upstream port":"Configured readiness check passed"}),_}catch(_){throw H({type:"readiness",status:"failed",message:_ instanceof Error?_.message.slice(0,500):"Readiness check failed"}),_}})():Promise.resolve(J),d0=i0();return d0.catch(()=>{}),{name:$.name,service:J,get child(){return F},stop:U0,done:G1,ready:d0}}async function O1($,Y){if(await L0($,Y),process.platform==="win32")return!0;let K=$.pid;if(!K||!T0(K))return!0;if(await F1($,K,S1))return!0;return await L0($,"SIGKILL"),D1(K,_1)}function T0($){try{return process.kill(-$,0),!0}catch(Y){return Y.code==="EPERM"}}async function D1($,Y){let K=Date.now()+Y;while(T0($)){if(Date.now()>=K)return!1;await new Promise((X)=>setTimeout(X,Math.min(20,Y)))}return!0}async function F1($,Y,K){let X=Date.now()+K;while(T0(Y)){if($.exitCode!==null||$.signalCode!==null||Date.now()>=X)return!1;await new Promise((Q)=>setTimeout(Q,Math.min(20,K)))}return!0}function N1($){if(Buffer.byteLength($)<=t0)return[$];let Y=[],K=[],X=0;for(let Q of $){let q=Buffer.byteLength(Q);if(K.length&&X+q>t0)Y.push(K.join("")),K=[],X=0;K.push(Q),X+=q}if(K.length)Y.push(K.join(""));return Y}async function L1($,Y,K,X,Q){if(!$)return{};let q=new Set(Y),z=new Map,W=async(Z)=>{let V=Z.toLowerCase();if(!q.has(V))throw Error(`environment references undeclared prerequisite "${Z}"`);let S=z.get(V);if(S)return S;let H=await Q(`http://127.0.0.1:${X}/api/services/${encodeURIComponent(C0(K,V))}`);if(H.status===404)throw Error(`environment references unresolved prerequisite "${Z}"`);if(!H.ok)throw Error(`could not resolve prerequisite "${Z}" (${H.status})`);let J=await H.json();return z.set(V,J),J},G=/\{service:([^}:]+):(port|url)\}/g,B={};for(let[Z,V]of Object.entries($)){let S=0,H="";for(let J of V.matchAll(G)){H+=V.slice(S,J.index);let O=await W(J[1]);if(J[2]==="port")H+=String(O.serviceType&&O.serviceType!=="http"?O.upstreamPort:O.stablePort);else{if(O.serviceType&&O.serviceType!=="http")throw Error(`environment variable ${Z} cannot use a URL for database prerequisite "${J[1]}"`);H+=`http://localhost:${O.stablePort}`}S=J.index+J[0].length}if(B[Z]=H+V.slice(S),B[Z].includes("{service:"))throw Error(`environment variable ${Z} has an invalid service reference`)}return B}async function K1($){let Y=await u(),K=await o0(Y.apiPort,Boolean(process.stdin.isTTY&&process.stdout.isTTY&&!process.env.CI)),X=[],Q=new AbortController,q=(G)=>{Q.abort(),X.forEach((B)=>B.stop(G))};for(let G of["SIGINT","SIGTERM","SIGHUP"])process.on(G,()=>q(G));let z=await R1($,async(G)=>{let B=await M1({...G,cleanUrls:K});return X.push(B),B},{signal:Q.signal});for(let G of z.failed)console.error(`${U.red("error")} starting "${G.name}": ${G.error.message}`);let W=await Promise.all(X.map((G)=>G.done));process.exit(W.find((G)=>G!==0)??(z.failed.length?1:0))}async function R1($,Y,K={}){let X=new Map($.map((W)=>[W.name.toLowerCase(),W])),Q=new Map,q=(W,G=new Set)=>{let B=W.name.toLowerCase();if(G.has(B))return Promise.resolve({error:Error("project dependency graph contains a cycle")});let Z=Q.get(B);if(Z)return Z;let V,S=new Promise((H)=>{V=H});return Q.set(B,S),(async()=>{let H=W.after??[],J=new Set(G).add(B),L=(await Promise.all(H.map((R)=>{let b=X.get(R.toLowerCase());if(!b)return Promise.resolve({error:Error(`${W.name} starts after unknown service ${R}`)});return q(b,J)}))).find((R)=>R.error);if(L)return V({error:Error(`${W.name} was not started because a prerequisite failed: ${L.error.message}`)});if(K.signal?.aborted)return V({error:Error(`${W.name} was not started because startup was cancelled`)});let N;try{N=await Y(W)}catch(R){return V({error:N0(R)})}if(K.signal?.aborted)return N.stop("SIGTERM"),V({error:Error(`${W.name} was stopped because startup was cancelled`)});if($.some((R)=>(R.after??[]).some((b)=>b.toLowerCase()===B)))console.log(`${U.dim(`LocalDeck: waiting for ${N.name} before starting its dependents`)}`);try{await N.ready}catch(R){return N.stop("SIGTERM"),V({error:N0(R)})}if(K.signal?.aborted)return N.stop("SIGTERM"),V({error:Error(`${W.name} was stopped because startup was cancelled`)});console.log(`${U.green("✓")} ${N.name} ${W.ready?.type==="tcp"?"is listening":"passed readiness"}`),V({service:N})})().catch((H)=>V({error:N0(H)})),S},z=await Promise.all($.map((W)=>q(W)));return{running:z.flatMap((W)=>W.service?[W.service]:[]),failed:$.flatMap((W,G)=>z[G].error?[{name:W.name,error:z[G].error}]:[])}}function N0($){return $ instanceof Error?$:Error(String($))}import m from"node:fs";import E from"node:path";function r($,Y){return $.commands.find((K)=>K.name===Y.toLowerCase())}function E0($=process.cwd()){let Y=e($);if(!Y)return[];let K=P0(Y),Q=C1(Y).flatMap(({file:Z,cwd:V})=>{let H=w0(Z)?.scripts;return H&&typeof H==="object"?Object.entries(H).filter(([,J])=>typeof J==="string").map(([J,O])=>({name:J,run:O,cwd:V})):[]}),q=Q.some((Z)=>Z.cwd),z=Q.filter((Z)=>!(q&&!Z.cwd&&/\b(?:turbo|nx|lerna)\b|\b(?:pnpm|npm|yarn|bun)\s+(?:-r|--recursive|workspaces?)/i.test(Z.run))),W=z.filter((Z)=>z.some((V)=>V.cwd===Z.cwd&&/^dev([:_-]|$)/.test(V.name))?/^dev([:_-]|$)/.test(Z.name):/^(start|serve|preview)([:_-]|$)/.test(Z.name)),G=[],B=new Set;for(let Z of W){let V=Z.name,[S,...H]=V.split(/[:_-]/),J=(Z.cwd&&!H.length?E.basename(Z.cwd):H.join("-")||S).replace(/[^a-z0-9_-]/gi,"-").toLowerCase().replace(/^[^a-z0-9]+/,"");if(!J)J="service";if(B.has(J))J=V.replace(/[^a-z0-9_-]/gi,"-").toLowerCase().replace(/^[^a-z0-9]+/,"");if(J=J.slice(0,41),B.has(J)){let O=2,L=J.replace(/-+$/,"").slice(0,37);while(B.has(J))J=`${L}-${O++}`.slice(0,41)}B.add(J),G.push({name:J,run:`${K} run ${V}`,tags:[],after:[],...Z.cwd?{cwd:Z.cwd}:{},ready:{type:"tcp",timeoutMs:60000,intervalMs:400}})}return G}function e($=process.cwd()){let Y=E.resolve($);for(;;){if(m.existsSync(E.join(Y,"package.json")))return Y;let K=E.dirname(Y);if(K===Y)return;Y=K}}function P0($){let Y=w0(E.join($,"package.json"));if(typeof Y?.packageManager==="string"){let X=Y.packageManager.split("@")[0];if(["npm","bun","pnpm","yarn"].includes(X))return X}return[["bun.lock","bun"],["bun.lockb","bun"],["pnpm-lock.yaml","pnpm"],["yarn.lock","yarn"],["package-lock.json","npm"]].find(([X])=>m.existsSync(E.join($,X)))?.[1]??"npm"}function w0($){try{let Y=JSON.parse(m.readFileSync($,"utf8"));if(!Y||typeof Y!=="object"||Array.isArray(Y))throw Error("manifest must contain an object");return Y}catch(Y){if(m.existsSync($))throw Error(`${$} is not valid JSON: ${Y.message}`);return}}function C1($){let Y=E.join($,"package.json"),K=w0(Y),X=[{file:Y}],z=(Array.isArray(K?.workspaces)?K.workspaces:Array.isArray(K?.packages)?K.packages:Array.isArray(K?.workspaces?.packages)?K.workspaces.packages:[]).filter((G)=>typeof G==="string"&&!G.includes("..")&&!E.isAbsolute(G)).map((G)=>{let B=G.replace(/\\/g,"/").replace(/^\.\//,"").replace(/\/$/,""),Z=B.split("/"),V=Z.map((S,H)=>S==="**"?H===Z.length-1?".*":"(?:[^/]+/)*":S.split("*").map((J)=>J.replace(/[.+?^${}()|[\]\\]/g,"\\$&")).join("[^/]*")+(H<Z.length-1?"/":"")).join("");return{regex:new RegExp(`^${V}$`),prefix:B.split("*")[0],depth:Z.includes("**")?1/0:Z.length}}),W=(G,B)=>{if(!z.some((Z)=>Z.depth>=B))return;for(let Z of m.readdirSync(G,{withFileTypes:!0}).sort((V,S)=>V.name.localeCompare(S.name))){if(!Z.isDirectory()||Z.isSymbolicLink()||["node_modules",".git",".superpowers","dist"].includes(Z.name))continue;let V=E.join(G,Z.name),S=E.relative($,V).replace(/\\/g,"/");if(!z.some((H)=>H.prefix.startsWith(`${S}/`)||S.startsWith(H.prefix)||H.prefix===S))continue;if(z.some((H)=>H.regex.test(S))){let H=E.join(V,"package.json");if(m.existsSync(H)&&m.lstatSync(H).isFile())X.push({file:H,cwd:S})}W(V,B+1)}};return W($,1),X}import j0 from"node:fs";import P from"node:path";import T from"node:fs";import A from"node:path";import{spawnSync as T1}from"node:child_process";async function X1($=process.cwd(),Y={}){let K=Y.executable??((B,Z,V)=>T1(B,Z,{encoding:"utf8",timeout:V})),X=[],Q=K("node",["--version"],2000),q=String(Q.stdout??"").trim().replace(/^v/,""),z=Number(q.split(".")[0]);X.push({name:"node",ok:Q.status===0&&z>=20,message:Q.status===0?`Node.js ${q}`:"Node.js executable is unavailable",fix:Q.status===0&&z>=20?void 0:"Install Node.js 20 or newer and put it on PATH."});let W=e($);if(!W)X.push({name:"package-manager",ok:!0,message:"No package.json; using explicitly configured commands."});else{let B="npm";try{B=P0(W)}catch(H){X.push({name:"package.json",ok:!1,message:H.message,fix:"Fix package.json syntax."})}let Z=K(B,["--version"],2000).status===0;X.push({name:"package-manager",ok:Z,message:`${B} ${Z?"is available":"is not available"}`,fix:Z?void 0:`Install ${B} or put it on PATH.`});let V;try{if(V=JSON.parse(T.readFileSync(A.join(W,"package.json"),"utf8")),!V||typeof V!=="object"||Array.isArray(V))throw Error("manifest must contain an object")}catch(H){X.push({name:"package.json",ok:!1,message:`${A.join(W,"package.json")} is not valid JSON: ${H.message}`,fix:"Fix package.json syntax."}),V={}}let S={...V.dependencies??{},...V.devDependencies??{},...V.optionalDependencies??{}};if(Object.keys(S).length){let H=T.existsSync(A.join(W,"node_modules"))||T.existsSync(A.join(W,".pnp.cjs"));X.push({name:"dependencies",ok:H,message:H?"node_modules exists":"dependencies are not installed",fix:H?void 0:`Run ${B} install.`})}}let G=I0($);if(!G)X.push({name:"config",ok:!1,message:"No LocalDeck config found",fix:"Run localdeck init."});else try{let B=x0(G);X.push({name:"config",ok:!0,message:`${A.basename(G)}: ${B.commands.length} service(s)`});let Z=[...new Set(B.commands.map((J)=>A.resolve(B.dir,J.cwd??".")))];for(let J of Z){let O=T.existsSync(J)&&T.statSync(J).isDirectory();X.push({name:`working-directory:${A.relative(B.dir,J)||"."}`,ok:O,message:O?"directory exists":"directory does not exist",fix:O?void 0:"Fix the command cwd in your LocalDeck config."})}for(let J of new Set([B.dir,...Z])){if(!T.existsSync(J)||!T.statSync(J).isDirectory())continue;let O=A.relative(B.dir,J)||".",L=A.join(J,"package.json");if(J!==W&&T.existsSync(L))try{let x=JSON.parse(T.readFileSync(L,"utf8"));if(Object.keys({...x.dependencies,...x.devDependencies}).length){let w=[J,W??B.dir].some((o)=>T.existsSync(A.join(o,"node_modules"))||T.existsSync(A.join(o,".pnp.cjs")));X.push({name:`dependencies:${O}`,ok:w,message:w?"Dependency installation found":"Dependencies are not installed",fix:w?void 0:"Run the project's package manager install command."})}}catch{X.push({name:`package.json:${O}`,ok:!1,message:"Invalid package.json",fix:"Fix this workspace's package.json syntax."})}let N=A.join(J,".env.example");if(!T.existsSync(N))continue;let R=I1(T.readFileSync(N,"utf8")),b=A.join(J,".env"),B0=A1(T.existsSync(b)?T.readFileSync(b,"utf8"):""),F=B.commands.filter((x)=>A.resolve(B.dir,x.cwd??".")===J),h=[...R].filter((x)=>!process.env[x]&&!B0.get(x)&&(!F.length||!F.every((w)=>Boolean(w.env?.[x]))));X.push({name:O==="."?"environment":`environment:${O}`,ok:!h.length,message:h.length?`missing variable names: ${h.join(", ")}`:"required variable names are present",fix:h.length?"Set the variables in this folder's .env or the environment.":void 0})}for(let J of B.commands)if(J.run.includes("docker")||J.serviceType==="compose"){let O=K("docker",["--version"],2000).status===0,L=O&&K("docker",["info"],3000).status===0;X.push({name:"docker",ok:L,message:L?"Docker executable and daemon are available":O?"Docker executable found but daemon is unavailable":"Docker executable is unavailable",fix:L?void 0:"Start Docker Desktop or the Docker daemon."});break}let V=B.commands.map((J)=>J.port).filter((J)=>Number.isInteger(J)),S=[...new Set(V.filter((J,O)=>V.indexOf(J)!==O))];X.push({name:"stable-ports",ok:!S.length,message:S.length?`conflicting configured ports: ${S.join(", ")}`:"configured stable ports are unique",fix:S.length?"Assign each service a different stable port.":void 0});let H=Y.portFree??Q1;for(let J of[...new Set(V)])if(!await H(J))X.push({name:`stable-port:${J}`,ok:!1,message:`port ${J} is already in use`,fix:"Choose another stable port or stop the process using it."});for(let J of B.commands){let O=J.serviceType,L=J.ready.type==="command"&&/^(pg_isready|redis-cli)\b/.exec(J.ready.run)?.[1];if(L){let N=L,R=K(N,["--version"],2000).status===0;X.push({name:N,ok:R,message:R?`${N} is available`:`${N} is unavailable for configured ${O} checks`,fix:R?void 0:`Install ${N} or use a configured container check.`})}}}catch(B){X.push({name:"config",ok:!1,message:B.message,fix:"Fix the config JSON and run doctor again."})}return{ok:X.every((B)=>B.ok),checks:X}}function I1($){return new Set($.split(/\r?\n/).map((Y)=>Y.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/)?.[1]).filter((Y)=>Boolean(Y)))}function A1($){return new Map($.split(/\r?\n/).map((Y)=>Y.match(/^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/)).filter((Y)=>Boolean(Y)).map((Y)=>[Y[1],Y[2].trim().replace(/^(['"])(.*)\1$/,"$2")]))}var Z1=`${U.bold("localdeck")} ${U.dim(`v${V0}`)} — stable ports, shareable links and logs for local dev servers
4
4
 
@@ -45,7 +45,7 @@ ${U.bold(".localdeck")} (JSON, at the project root)
45
45
  "after" is the beginner-friendly startup order. LocalDeck verifies each
46
46
  prerequisite is ready before starting its dependents. Omit "ready" to use
47
47
  automatic port readiness; HTTP paths and advanced checks are optional.
48
- `,b1={loadProject:A0,ensureDaemon:u,createApi:($)=>new K0($),findDaemon:Y0,createWebSocket:($)=>new d($),runForeground:K1,log:($)=>console.log($),warn:($)=>console.warn($)};async function E1($,Y={}){let K={...b1,...Y},[X,...Q]=$;switch(X){case void 0:console.log(Z1),await f0(!1,K);return;case"help":case"-h":case"--h":case"--help":console.log(Z1);return;case"--update":if(Q.length)throw Error("Usage: localdeck --update");return(await import("./update-zhsjwnrw.js")).updateLocalDeck();case"up":return P1(Q,K);case"profile":case"profiles":return w1(Q,K);case"init":return k1(Q,K);case"mcp":return(await import("./mcp-59a41rj3.js")).runMcp(Q);case"quarry":return(await import("./quarry-23qjnaj9.js")).runQuarry(Q);case"doctor":return j1(Q);case"forward":return f1(Q);case"commands":case"cmds":return f0(!0,K);case"-v":case"--v":case"--version":console.log(V0);return;case"run":return h1(Q,K);case"ps":case"ls":case"ports":return u1(K);case"port":return m1(Q[0]);case"logs":return l1(Q,K);case"requests":return p1(Q);case"share":return i1(Q);case"unshare":return d1(Q[0]);case"stop":return c1(Q[0]);case"open":return o1(Q[0]);case"daemon":return t1(Q[0]);default:{let q=Q0(K),z=q&&r(q,X);if(z){let G=await X0(q,K),B=await g0(q,G,K),Z=q0(q.commands,[z.name]).flat();return K.runForeground(Z.map((V,S)=>h0(B.effective(V),q,G,{prefix:Z.length>1,color:c[S%c.length],...B.options})))}let W=q?` Commands in ${P.basename(q.file)}: ${q.commands.map((G)=>G.name).join(", ")||"(none)"}`:"";M(`unknown command "${X}". Run localdeck --help.${W}`)}}}function Q0($){try{return $.loadProject()}catch(Y){M(Y.message)}}function h0($,Y,K,X={}){return{name:$.name,...K?{project:K}:{},stablePort:$.port,upstreamPort:$.upstream,command:b0($.run),displayCommand:$.run,cwd:$.cwd?P.resolve(Y.dir,$.cwd):Y.dir,after:$.after,ready:$.ready,...$.env?{env:$.env}:{},...$.secrets?{secrets:$.secrets}:{},...$.serviceType?{serviceType:$.serviceType}:{},...X}}async function X0($,Y){try{let K=await Y.ensureDaemon();return await Y.createApi(K.apiPort).rememberProject($.file,K.controlToken)}catch(K){let X=K instanceof Error?K.message:String(K);Y.warn(`LocalDeck: could not remember this project: ${X}`);return}}async function g0($,Y,K){let X=[];if($.profiles?.length&&Y)try{let z=await K.ensureDaemon();X=(await K.createApi(z.apiPort).profiles(Y.id)).active}catch(z){K.warn(`LocalDeck: could not read active profiles, running without them: ${z instanceof Error?z.message:String(z)}`)}let Q;try{Q=y0($,X)}catch(z){M(z instanceof Error?z.message:String(z))}if(Q.active.length)K.log(U.dim(`Profiles: ${Q.active.join(" + ")}`));for(let z of Q.clashes)K.warn(`LocalDeck: ${z.profiles.join(" and ")} both set ${z.service} ${z.field}; ${z.winner} wins because it is listed later.`);let q=new Map(Q.commands.map((z)=>[z.name,z]));return{effective:(z)=>q.get(z.name)??z,options:Y?{profiles:Q.active}:{}}}async function f0($,Y){let K=Q0(Y);if(!K){if($)M("no .localdeck file found here or in a parent folder. Create one with: localdeck init");return}await X0(K,Y),console.log(`${U.bold("Project commands")} ${U.dim(`(${P.relative(process.cwd(),K.file)||P.basename(K.file)})`)}`);let X=K.commands.map((Q)=>[U.cyan(Q.name),Q.port?String(Q.port):U.dim("auto"),Q.after.join(",")||"",Q.tags.join(",")||"",U.dim(Q.run)]);if(console.log(i(X,["NAME","PORT","AFTER","TAGS","RUN"])),K.profiles?.length)console.log(`
48
+ `,b1={loadProject:A0,ensureDaemon:u,createApi:($)=>new K0($),findDaemon:Y0,createWebSocket:($)=>new d($),runForeground:K1,log:($)=>console.log($),warn:($)=>console.warn($)};async function E1($,Y={}){let K={...b1,...Y},[X,...Q]=$;switch(X){case void 0:console.log(Z1),await f0(!1,K);return;case"help":case"-h":case"--h":case"--help":console.log(Z1);return;case"--update":if(Q.length)throw Error("Usage: localdeck --update");return(await import("./update-2nttbg13.js")).updateLocalDeck();case"up":return P1(Q,K);case"profile":case"profiles":return w1(Q,K);case"init":return k1(Q,K);case"mcp":return(await import("./mcp-w45qck6z.js")).runMcp(Q);case"quarry":return(await import("./quarry-ysrktgjh.js")).runQuarry(Q);case"doctor":return j1(Q);case"forward":return f1(Q);case"commands":case"cmds":return f0(!0,K);case"-v":case"--v":case"--version":console.log(V0);return;case"run":return h1(Q,K);case"ps":case"ls":case"ports":return u1(K);case"port":return m1(Q[0]);case"logs":return l1(Q,K);case"requests":return p1(Q);case"share":return i1(Q);case"unshare":return d1(Q[0]);case"stop":return c1(Q[0]);case"open":return o1(Q[0]);case"daemon":return t1(Q[0]);default:{let q=Q0(K),z=q&&r(q,X);if(z){let G=await X0(q,K),B=await g0(q,G,K),Z=q0(q.commands,[z.name]).flat();return K.runForeground(Z.map((V,S)=>h0(B.effective(V),q,G,{prefix:Z.length>1,color:c[S%c.length],...B.options})))}let W=q?` Commands in ${P.basename(q.file)}: ${q.commands.map((G)=>G.name).join(", ")||"(none)"}`:"";M(`unknown command "${X}". Run localdeck --help.${W}`)}}}function Q0($){try{return $.loadProject()}catch(Y){M(Y.message)}}function h0($,Y,K,X={}){return{name:$.name,...K?{project:K}:{},stablePort:$.port,upstreamPort:$.upstream,command:b0($.run),displayCommand:$.run,cwd:$.cwd?P.resolve(Y.dir,$.cwd):Y.dir,after:$.after,ready:$.ready,...$.env?{env:$.env}:{},...$.secrets?{secrets:$.secrets}:{},...$.serviceType?{serviceType:$.serviceType}:{},...X}}async function X0($,Y){try{let K=await Y.ensureDaemon();return await Y.createApi(K.apiPort).rememberProject($.file,K.controlToken)}catch(K){let X=K instanceof Error?K.message:String(K);Y.warn(`LocalDeck: could not remember this project: ${X}`);return}}async function g0($,Y,K){let X=[];if($.profiles?.length&&Y)try{let z=await K.ensureDaemon();X=(await K.createApi(z.apiPort).profiles(Y.id)).active}catch(z){K.warn(`LocalDeck: could not read active profiles, running without them: ${z instanceof Error?z.message:String(z)}`)}let Q;try{Q=y0($,X)}catch(z){M(z instanceof Error?z.message:String(z))}if(Q.active.length)K.log(U.dim(`Profiles: ${Q.active.join(" + ")}`));for(let z of Q.clashes)K.warn(`LocalDeck: ${z.profiles.join(" and ")} both set ${z.service} ${z.field}; ${z.winner} wins because it is listed later.`);let q=new Map(Q.commands.map((z)=>[z.name,z]));return{effective:(z)=>q.get(z.name)??z,options:Y?{profiles:Q.active}:{}}}async function f0($,Y){let K=Q0(Y);if(!K){if($)M("no .localdeck file found here or in a parent folder. Create one with: localdeck init");return}await X0(K,Y),console.log(`${U.bold("Project commands")} ${U.dim(`(${P.relative(process.cwd(),K.file)||P.basename(K.file)})`)}`);let X=K.commands.map((Q)=>[U.cyan(Q.name),Q.port?String(Q.port):U.dim("auto"),Q.after.join(",")||"",Q.tags.join(",")||"",U.dim(Q.run)]);if(console.log(i(X,["NAME","PORT","AFTER","TAGS","RUN"])),K.profiles?.length)console.log(`
49
49
  ${U.bold("Profiles")} ${K.profiles.map((Q)=>Q.name).join(", ")} ${U.dim("· localdeck profile")}`);console.log(U.dim(`
50
50
  run one: localdeck <name> · run all: localdeck up · by tag: localdeck up <tag>`))}var c=[U.cyan,U.magenta,U.green,U.yellow,U.blue];async function P1($,Y){let K=Q0(Y);if(!K)M("no .localdeck file found here or in a parent folder. Create one with: localdeck init");let X=$.indexOf("--profile"),Q;if(X!==-1){if(Q=$[X+1],!Q)M("--profile needs a profile name");$=$.filter((B,Z)=>Z!==X&&Z!==X+1)}let q=K.legacyProfiles;if(Q&&K.profiles?.some((B)=>B.name===Q))M(`"${Q}" is a profile you turn on, not a group to start: localdeck profile on ${Q}`);if(Q&&(!q||!Object.prototype.hasOwnProperty.call(q,Q)))M(`unknown profile "${Q}". Group services with tags and run: localdeck up <tag>`);if(Q)Y.warn(`LocalDeck: --profile is deprecated. "${Q}" is now a tag; run: localdeck up ${Q}`);let z=K.commands;if(Q){let B=new Set(q[Q]);if(z=K.commands.filter((Z)=>B.has(Z.name)),!z.length)M(`profile "${Q}" selects no configured services`)}if($.length){let B=new Set(z),Z=K.commands.filter((H)=>$.some((J)=>r(K,J)===H||H.tags.includes(J))),V=Z.filter((H)=>!B.has(H));if(Q&&V.length)M(`service outside profile "${Q}": ${V.map((H)=>H.name).join(", ")}`);z=Z.filter((H)=>B.has(H));let S=$.filter((H)=>!r(K,H)&&!K.commands.some((J)=>J.tags.includes(H)));if(S.length)M(`no command or tag named ${S.map((H)=>`"${H}"`).join(", ")} in ${P.basename(K.file)}`)}if(!z.length)M("nothing to run");z=q0(K.commands,z.map((B)=>B.name)).flat();let W=await X0(K,Y),G=await g0(K,W,Y);await Y.runForeground(z.map((B,Z)=>h0(G.effective(B),K,W,{prefix:z.length>1,color:c[Z%c.length],...G.options})))}async function w1($,Y){let K=Q0(Y);if(!K)M("no .localdeck file found here or in a parent folder. Create one with: localdeck init");let[X="list",...Q]=$;if(!["list","ls","on","off","clear"].includes(X))M(`unknown profile action "${X}". Usage: localdeck profile [on|off <name...>|clear]`);if((X==="on"||X==="off")&&!Q.length)M(`localdeck profile ${X} needs at least one profile name`);if(!K.profiles?.length){if(X==="list"||X==="ls"){Y.log(`No profiles in ${P.basename(K.file)}. Add a "profiles" object to run services differently, for example against staging.`);return}M(`${P.basename(K.file)} defines no profiles`)}let q=await X0(K,Y);if(!q)M("the LocalDeck daemon is needed to switch profiles");let z=await Y.ensureDaemon(),W=Y.createApi(z.apiPort),G=await W.profiles(q.id);if(X==="on"||X==="off"||X==="clear"){let B=Q.map((S)=>S.toLowerCase()),Z=B.filter((S)=>!G.profiles.some((H)=>H.name===S));if(Z.length)M(`unknown profile ${Z.map((S)=>`"${S}"`).join(", ")}. Available profiles: ${G.profiles.map((S)=>S.name).join(", ")}`);let V=X==="clear"?[]:X==="on"?[...new Set([...G.active,...B])]:G.active.filter((S)=>!B.includes(S));G=await W.setActiveProfiles(q.id,V),Y.log(G.active.length?`Profiles on: ${U.cyan(G.active.join(" + "))}`:"No profiles on · running base services"),Y.log(U.dim("Running services keep their settings until restarted."))}else{let B=G.profiles.map((Z)=>[Z.active?U.green("on"):U.dim("off"),U.cyan(Z.name),Z.services.join(","),Z.description??""]);Y.log(i(B,["","PROFILE","CHANGES","DESCRIPTION"])),Y.log(U.dim(`
51
51
  turn on: localdeck profile on <name> · off: localdeck profile off <name> · all off: localdeck profile clear`))}for(let B of G.clashes)Y.warn(`LocalDeck: ${B.profiles.join(" and ")} both set ${B.service} ${B.field}; ${B.winner} wins because it is listed later.`);if(G.error)Y.warn(`LocalDeck: ${G.error}`)}async function k1($,Y){let K=e()??process.cwd(),X=[".localdeck",".localdeck.json","localdeck.json"].map((H)=>P.join(K,H)).find((H)=>j0.existsSync(H)),Q=$.find((H)=>H===".localdeck.json"||H==="localdeck.json")??(X?P.basename(X):".localdeck"),q=P.join(K,Q);if((X&&X!==q||j0.existsSync(q))&&!$.includes("--force")&&!$.includes("--dry-run"))M(`${P.basename(X??q)} already exists here (use --force to overwrite)`);let z=$.indexOf("--command"),W=$.indexOf("--name"),G=z>=0?$[z+1]:void 0,B=W>=0?$[W+1]:void 0;if(z>=0&&(!G||G.startsWith("--")))M("--command requires a command value");if(W>=0&&(!B||B.startsWith("--")))M("--name requires a service name");if(G!==void 0&&!G.trim())M("--command must not be empty");if(G&&!B)M("--command requires --name <service>");if(B&&!/^[a-z0-9][a-z0-9_-]{0,40}$/i.test(B))M("--name must start with a letter or number and be at most 41 characters");let Z=G?[{name:B.toLowerCase(),run:G,tags:[],cwd:void 0}]:E0();if(!Z.length)M("could not infer any runnable scripts. Add --command '<command>' --name <service>, then run localdeck init again");let S=Z.map((H)=>({name:H.name,run:H.run,...H.cwd?{cwd:H.cwd}:{},...H.tags.length?{tag:H.tags.length===1?H.tags[0]:H.tags}:{}}));if($.includes("--dry-run")){console.log(JSON.stringify({file:q,commands:S},null,2));return}console.log(i(S.map((H)=>[H.name,H.run,H.cwd??"."]),["SERVICE","COMMAND","FOLDER"])),j0.writeFileSync(q,JSON.stringify({commands:S},null,2)+`
@@ -1,4 +1,4 @@
1
- import{I as N,e as Y}from"./index-fmgnn6mt.js";import{va as C,wa as J}from"./index-2da1tyad.js";import{parseArgs as Z}from"node:util";import y from"node:process";var P=10485760;class Q{constructor(b){this._maxBufferSize=b?.maxBufferSize??P}append(b){if((this._buffer?.length??0)+b.length>this._maxBufferSize)throw this.clear(),Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);this._buffer=this._buffer?Buffer.concat([this._buffer,b]):b}readMessage(){if(!this._buffer)return null;let b=this._buffer.indexOf(`
1
+ import{I as N,e as Y}from"./index-jtd14k8h.js";import{va as C,wa as J}from"./index-scnd2pq4.js";import{parseArgs as Z}from"node:util";import y from"node:process";var P=10485760;class Q{constructor(b){this._maxBufferSize=b?.maxBufferSize??P}append(b){if((this._buffer?.length??0)+b.length>this._maxBufferSize)throw this.clear(),Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);this._buffer=this._buffer?Buffer.concat([this._buffer,b]):b}readMessage(){if(!this._buffer)return null;let b=this._buffer.indexOf(`
2
2
  `);if(b===-1)return null;let q=this._buffer.toString("utf8",0,b).replace(/\r$/,"");return this._buffer=this._buffer.subarray(b+1),X(q)}clear(){this._buffer=void 0}}function X(b){return Y.parse(JSON.parse(b))}function $(b){return JSON.stringify(b)+`
3
3
  `}class V{constructor(b=y.stdin,q=y.stdout,w){this._stdin=b,this._stdout=q,this._started=!1,this._ondata=(K)=>{try{this._readBuffer.append(K),this.processReadBuffer()}catch(H){this.onerror?.(H),this.close().catch(()=>{})}},this._onerror=(K)=>{this.onerror?.(K)},this._readBuffer=new Q({maxBufferSize:w?.maxBufferSize})}async start(){if(this._started)throw Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");this._started=!0,this._stdin.on("data",this._ondata),this._stdin.on("error",this._onerror)}processReadBuffer(){while(!0)try{let b=this._readBuffer.readMessage();if(b===null)break;this.onmessage?.(b)}catch(b){this.onerror?.(b)}}async close(){if(this._stdin.off("data",this._ondata),this._stdin.off("error",this._onerror),this._stdin.listenerCount("data")===0)this._stdin.pause();this._readBuffer.clear(),this.onclose?.()}send(b){return new Promise((q)=>{let w=$(b);if(this._stdout.write(w))q();else this._stdout.once("drain",q)})}}async function T(b){let{values:q}=Z({args:b,strict:!0,allowPositionals:!1,options:{project:{type:"string"},help:{type:"boolean",short:"h"}}});if(q.help){console.log(`Usage: localdeck mcp [--project <id>]
4
4
  Runs an MCP server over stdio for inspection, service control, recorded GET/HEAD replay and quick sharing.
@@ -1,4 +1,4 @@
1
- import{A as R,B as gZ,C as bZ,D as kZ,E as hZ,F as uZ,G as lZ,H as dZ,I as J0,a as C,b as PZ,c as CZ,d as M,f as h,g as jZ,h as FZ,i as zZ,j as LZ,k as AZ,l as _Z,m as qZ,n as xZ,o as MZ,p as IZ,q as r,r as TZ,s as yZ,t as EZ,u as SZ,v as fZ,w as wZ,x as RZ,y as vZ,z as L}from"./index-fmgnn6mt.js";import{N as tZ,U as sZ,X as rZ,ra as GZ,ta as eZ,va as Z0,wa as $0}from"./index-2da1tyad.js";import mZ from"node:crypto";import m from"node:fs";import c from"node:path";class QZ{constructor(Z){this._client=Z}async*callToolStream(Z,H=r,Q){let B=this._client,G={...Q,task:Q?.task??(B.isToolTask(Z.name)?{}:void 0)},W=B.requestStream({method:"tools/call",params:Z},H,G),Y=B.getToolOutputValidator(Z.name);for await(let V of W){if(V.type==="result"&&Y){let P=V.result;if(!P.structuredContent&&!P.isError){yield{type:"error",error:new L(M.InvalidRequest,`Tool ${Z.name} has an output schema but did not return structured content`)};return}if(P.structuredContent)try{let X=Y(P.structuredContent);if(!X.valid){yield{type:"error",error:new L(M.InvalidParams,`Structured content does not match the tool's output schema: ${X.errorMessage}`)};return}}catch(X){if(X instanceof L){yield{type:"error",error:X};return}yield{type:"error",error:new L(M.InvalidParams,`Failed to validate structured content: ${X instanceof Error?X.message:String(X)}`)};return}}yield V}}async getTask(Z,H){return this._client.getTask({taskId:Z},H)}async getTaskResult(Z,H,Q){return this._client.getTaskResult({taskId:Z},H,Q)}async listTasks(Z,H){return this._client.listTasks(Z?{cursor:Z}:void 0,H)}async cancelTask(Z,H){return this._client.cancelTask({taskId:Z},H)}requestStream(Z,H,Q){return this._client.requestStream(Z,H,Q)}}function e(Z,H){if(!Z||H===null||typeof H!=="object")return;if(Z.type==="object"&&Z.properties&&typeof Z.properties==="object"){let Q=H,B=Z.properties;for(let G of Object.keys(B)){let W=B[G];if(Q[G]===void 0&&Object.prototype.hasOwnProperty.call(W,"default"))Q[G]=W.default;if(Q[G]!==void 0)e(W,Q[G])}}if(Array.isArray(Z.anyOf)){for(let Q of Z.anyOf)if(typeof Q!=="boolean")e(Q,H)}if(Array.isArray(Z.oneOf)){for(let Q of Z.oneOf)if(typeof Q!=="boolean")e(Q,H)}}function j0(Z){if(!Z)return{supportsFormMode:!1,supportsUrlMode:!1};let H=Z.form!==void 0,Q=Z.url!==void 0;return{supportsFormMode:H||!H&&!Q,supportsUrlMode:Q}}class WZ extends kZ{constructor(Z,H){super(H);if(this._clientInfo=Z,this._cachedToolOutputValidators=new Map,this._cachedKnownTaskTools=new Set,this._cachedRequiredTaskTools=new Set,this._listChangedDebounceTimers=new Map,this._capabilities=H?.capabilities??{},this._jsonSchemaValidator=H?.jsonSchemaValidator??new uZ,H?.listChanged)this._pendingListChangedConfig=H.listChanged}_setupListChangedHandlers(Z){if(Z.tools&&this._serverCapabilities?.tools?.listChanged)this._setupListChangedHandler("tools",TZ,Z.tools,async()=>{return(await this.listTools()).tools});if(Z.prompts&&this._serverCapabilities?.prompts?.listChanged)this._setupListChangedHandler("prompts",MZ,Z.prompts,async()=>{return(await this.listPrompts()).prompts});if(Z.resources&&this._serverCapabilities?.resources?.listChanged)this._setupListChangedHandler("resources",_Z,Z.resources,async()=>{return(await this.listResources()).resources})}get experimental(){if(!this._experimental)this._experimental={tasks:new QZ(this)};return this._experimental}registerCapabilities(Z){if(this.transport)throw Error("Cannot register capabilities after connecting to transport");this._capabilities=hZ(this._capabilities,Z)}setRequestHandler(Z,H){let B=gZ(Z)?.method;if(!B)throw Error("Schema is missing a method literal");let G=bZ(B);if(typeof G!=="string")throw Error("Schema method literal must be a string");let W=G;if(W==="elicitation/create"){let Y=async(V,P)=>{let X=R(wZ,V);if(!X.success){let x=X.error instanceof Error?X.error.message:String(X.error);throw new L(M.InvalidParams,`Invalid elicitation request: ${x}`)}let{params:O}=X.data;O.mode=O.mode??"form";let{supportsFormMode:j,supportsUrlMode:y}=j0(this._capabilities.elicitation);if(O.mode==="form"&&!j)throw new L(M.InvalidParams,"Client does not support form-mode elicitation requests");if(O.mode==="url"&&!y)throw new L(M.InvalidParams,"Client does not support URL-mode elicitation requests");let f=await Promise.resolve(H(V,P));if(O.task){let x=R(FZ,f);if(!x.success){let p=x.error instanceof Error?x.error.message:String(x.error);throw new L(M.InvalidParams,`Invalid task creation result: ${p}`)}return x.data}let I=R(RZ,f);if(!I.success){let x=I.error instanceof Error?I.error.message:String(I.error);throw new L(M.InvalidParams,`Invalid elicitation result: ${x}`)}let A=I.data,w=O.mode==="form"?O.requestedSchema:void 0;if(O.mode==="form"&&A.action==="accept"&&A.content&&w){if(this._capabilities.elicitation?.form?.applyDefaults)try{e(w,A.content)}catch{}}return A};return super.setRequestHandler(Z,Y)}if(W==="sampling/createMessage"){let Y=async(V,P)=>{let X=R(EZ,V);if(!X.success){let A=X.error instanceof Error?X.error.message:String(X.error);throw new L(M.InvalidParams,`Invalid sampling request: ${A}`)}let{params:O}=X.data,j=await Promise.resolve(H(V,P));if(O.task){let A=R(FZ,j);if(!A.success){let w=A.error instanceof Error?A.error.message:String(A.error);throw new L(M.InvalidParams,`Invalid task creation result: ${w}`)}return A.data}let f=O.tools||O.toolChoice?fZ:SZ,I=R(f,j);if(!I.success){let A=I.error instanceof Error?I.error.message:String(I.error);throw new L(M.InvalidParams,`Invalid sampling result: ${A}`)}return I.data};return super.setRequestHandler(Z,Y)}return super.setRequestHandler(Z,H)}assertCapability(Z,H){if(!this._serverCapabilities?.[Z])throw Error(`Server does not support ${Z} (required for ${H})`)}async connect(Z,H){if(await super.connect(Z),Z.sessionId!==void 0)return;try{let Q=await this.request({method:"initialize",params:{protocolVersion:PZ,capabilities:this._capabilities,clientInfo:this._clientInfo}},jZ,H);if(Q===void 0)throw Error(`Server sent invalid initialize result: ${Q}`);if(!CZ.includes(Q.protocolVersion))throw Error(`Server's protocol version is not supported: ${Q.protocolVersion}`);if(this._serverCapabilities=Q.capabilities,this._serverVersion=Q.serverInfo,Z.setProtocolVersion)Z.setProtocolVersion(Q.protocolVersion);if(this._instructions=Q.instructions,await this.notification({method:"notifications/initialized"}),this._pendingListChangedConfig)this._setupListChangedHandlers(this._pendingListChangedConfig),this._pendingListChangedConfig=void 0}catch(Q){throw this.close(),Q}}getServerCapabilities(){return this._serverCapabilities}getServerVersion(){return this._serverVersion}getInstructions(){return this._instructions}assertCapabilityForMethod(Z){switch(Z){case"logging/setLevel":if(!this._serverCapabilities?.logging)throw Error(`Server does not support logging (required for ${Z})`);break;case"prompts/get":case"prompts/list":if(!this._serverCapabilities?.prompts)throw Error(`Server does not support prompts (required for ${Z})`);break;case"resources/list":case"resources/templates/list":case"resources/read":case"resources/subscribe":case"resources/unsubscribe":if(!this._serverCapabilities?.resources)throw Error(`Server does not support resources (required for ${Z})`);if(Z==="resources/subscribe"&&!this._serverCapabilities.resources.subscribe)throw Error(`Server does not support resource subscriptions (required for ${Z})`);break;case"tools/call":case"tools/list":if(!this._serverCapabilities?.tools)throw Error(`Server does not support tools (required for ${Z})`);break;case"completion/complete":if(!this._serverCapabilities?.completions)throw Error(`Server does not support completions (required for ${Z})`);break;case"initialize":break;case"ping":break}}assertNotificationCapability(Z){switch(Z){case"notifications/roots/list_changed":if(!this._capabilities.roots?.listChanged)throw Error(`Client does not support roots list changed notifications (required for ${Z})`);break;case"notifications/initialized":break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(Z){if(!this._capabilities)return;switch(Z){case"sampling/createMessage":if(!this._capabilities.sampling)throw Error(`Client does not support sampling capability (required for ${Z})`);break;case"elicitation/create":if(!this._capabilities.elicitation)throw Error(`Client does not support elicitation capability (required for ${Z})`);break;case"roots/list":if(!this._capabilities.roots)throw Error(`Client does not support roots capability (required for ${Z})`);break;case"tasks/get":case"tasks/list":case"tasks/result":case"tasks/cancel":if(!this._capabilities.tasks)throw Error(`Client does not support tasks capability (required for ${Z})`);break;case"ping":break}}assertTaskCapability(Z){lZ(this._serverCapabilities?.tasks?.requests,Z,"Server")}assertTaskHandlerCapability(Z){if(!this._capabilities)return;dZ(this._capabilities.tasks?.requests,Z,"Client")}async ping(Z){return this.request({method:"ping"},h,Z)}async complete(Z,H){return this.request({method:"completion/complete",params:Z},vZ,H)}async setLoggingLevel(Z,H){return this.request({method:"logging/setLevel",params:{level:Z}},h,H)}async getPrompt(Z,H){return this.request({method:"prompts/get",params:Z},xZ,H)}async listPrompts(Z,H){return this.request({method:"prompts/list",params:Z},qZ,H)}async listResources(Z,H){return this.request({method:"resources/list",params:Z},zZ,H)}async listResourceTemplates(Z,H){return this.request({method:"resources/templates/list",params:Z},LZ,H)}async readResource(Z,H){return this.request({method:"resources/read",params:Z},AZ,H)}async subscribeResource(Z,H){return this.request({method:"resources/subscribe",params:Z},h,H)}async unsubscribeResource(Z,H){return this.request({method:"resources/unsubscribe",params:Z},h,H)}async callTool(Z,H=r,Q){if(this.isToolTaskRequired(Z.name))throw new L(M.InvalidRequest,`Tool "${Z.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);let B=await this.request({method:"tools/call",params:Z},H,Q),G=this.getToolOutputValidator(Z.name);if(G){if(!B.structuredContent&&!B.isError)throw new L(M.InvalidRequest,`Tool ${Z.name} has an output schema but did not return structured content`);if(B.structuredContent)try{let W=G(B.structuredContent);if(!W.valid)throw new L(M.InvalidParams,`Structured content does not match the tool's output schema: ${W.errorMessage}`)}catch(W){if(W instanceof L)throw W;throw new L(M.InvalidParams,`Failed to validate structured content: ${W instanceof Error?W.message:String(W)}`)}}return B}isToolTask(Z){if(!this._serverCapabilities?.tasks?.requests?.tools?.call)return!1;return this._cachedKnownTaskTools.has(Z)}isToolTaskRequired(Z){return this._cachedRequiredTaskTools.has(Z)}cacheToolMetadata(Z){this._cachedToolOutputValidators.clear(),this._cachedKnownTaskTools.clear(),this._cachedRequiredTaskTools.clear();for(let H of Z){if(H.outputSchema){let B=this._jsonSchemaValidator.getValidator(H.outputSchema);this._cachedToolOutputValidators.set(H.name,B)}let Q=H.execution?.taskSupport;if(Q==="required"||Q==="optional")this._cachedKnownTaskTools.add(H.name);if(Q==="required")this._cachedRequiredTaskTools.add(H.name)}}getToolOutputValidator(Z){return this._cachedToolOutputValidators.get(Z)}async listTools(Z,H){let Q=await this.request({method:"tools/list",params:Z},IZ,H);return this.cacheToolMetadata(Q.tools),Q}_setupListChangedHandler(Z,H,Q,B){let G=yZ.safeParse(Q);if(!G.success)throw Error(`Invalid ${Z} listChanged options: ${G.error.message}`);if(typeof Q.onChanged!=="function")throw Error(`Invalid ${Z} listChanged options: onChanged must be a function`);let{autoRefresh:W,debounceMs:Y}=G.data,{onChanged:V}=Q,P=async()=>{if(!W){V(null,null);return}try{let O=await B();V(null,O)}catch(O){let j=O instanceof Error?O:Error(String(O));V(j,null)}},X=()=>{if(Y){let O=this._listChangedDebounceTimers.get(Z);if(O)clearTimeout(O);let j=setTimeout(P,Y);this._listChangedDebounceTimers.set(Z,j)}else P()};this.setNotificationHandler(H,X)}async sendRootsListChanged(){return this.notification({method:"notifications/roots/list_changed"})}}class u{constructor(){this._messageQueue=[]}static createLinkedPair(){let Z=new u,H=new u;return Z._otherTransport=H,H._otherTransport=Z,[Z,H]}async start(){while(this._messageQueue.length>0){let Z=this._messageQueue.shift();this.onmessage?.(Z.message,Z.extra)}}async close(){let Z=this._otherTransport;this._otherTransport=void 0,await Z?.close(),this.onclose?.()}async send(Z,H){if(!this._otherTransport)throw Error("Not connected");if(this._otherTransport.onmessage)this._otherTransport.onmessage(Z,{authInfo:H?.authInfo});else this._otherTransport._messageQueue.push({message:Z,extra:{authInfo:H?.authInfo}})}}var z0=1,ZZ=1048576,cZ=["list_services","get_service","get_logs","start_service","stop_service","restart_service"],L0="Restart it in the terminal that started it",A0="LocalDeck isn't responding; retrying",pZ=16384,_0=200,nZ=64,d=5000,K0=ZZ-65536,q0=[1000,2000,5000,1e4],x0=/^[a-zA-Z0-9_-]+:[a-zA-Z0-9_-]+$/;class T extends Error{code;constructor(Z,H){super(H);this.code=Z}}var g=C.string().min(1).max(200),iZ=C.string().regex(x0,"Use the exact projectId:service id from services/list"),E={initialize:C.object({protocolVersion:C.number(),quarryVersion:C.string().max(100).optional()}),open:C.object({workspaceId:g,path:C.string().min(1).max(4096).refine((Z)=>c.isAbsolute(Z),"path must be absolute")}),workspace:C.object({workspaceId:g}),action:C.object({workspaceId:g,serviceId:iZ,action:C.enum(["start","stop","restart","share","unshare","open"])}),subscribe:C.object({workspaceId:g,serviceId:iZ,from:C.string().max(200).optional(),limit:C.number().int().min(1).max(d).default(1000)}),unsubscribe:C.object({subscription:C.string().min(1).max(200)}),page:C.object({workspaceId:g,pageId:C.string().min(1).max(100)}),call:C.object({workspaceId:g,name:C.string().min(1).max(100),arguments:C.record(C.string(),C.unknown()).optional()})};function S(Z,H){let Q=Z.safeParse(H??{});if(!Q.success)throw new T(-32602,Q.error.issues.map((B)=>`${B.path.join(".")||"params"}: ${B.message}`).join("; "));return Q.data}function l(Z){return Z instanceof TypeError||Z instanceof Error&&(Z.name==="TimeoutError"||Z.name==="AbortError"||/ECONNREFUSED|ECONNRESET|did not start/.test(Z.message))}function M0(Z){if(Buffer.byteLength(Z)<=pZ)return Z;return new TextDecoder().decode(Buffer.from(Z).subarray(0,pZ-3)).replace(/�+$/,"")+"…"}function H0(Z){return{cursor:Z.id,ts:Z.ts,stream:Z.stream,text:M0(Z.line)}}function oZ(Z,H,Q){let B=0,G=!1;if(H!==void 0){let O=Z.findIndex((j)=>j.id===H);if(O===-1)G=Z.length>0;else B=O+1}let W=Z.slice(B),Y=W.slice(-Q).map(H0),V=0,P=Y.length;while(P>0){if(V+=Buffer.byteLength(JSON.stringify(Y[P-1]))+1,V>K0)break;P--}let X=Y.slice(P);return{lines:X,truncated:G||X.length<W.length}}function I0(Z){for(let H of Z){let Q=H.replace(/^(http:\/\/[a-z0-9-]+(?:\.[a-z0-9-]+)?\.localhost):\d+(?=\/|$)/i,"$1");if(Q!==H)return Q}return}function T0(Z,H,Q,B={}){let G=Q?.status==="running"||Q?.status==="starting",W;if(!Q||Q.status==="stopped")W=Q&&(Q.readinessStatus==="failed"||Q.lastError)?"failed":"stopped";else if(Q.status==="stopping")W="stopping";else if(Q.readinessStatus==="failed")W="failed";else if(Q.status==="starting"||!Q.upstreamReady||Q.readinessStatus==="checking")W="starting";else W="running";let Y=Q?.stablePort??B.command?.port,V=!(Q?.serviceType??B.command?.serviceType)||(Q?.serviceType??B.command?.serviceType)==="http",P=V&&Y?(B.cleanUrls&&Q?I0(Q.urls):void 0)??`http://localhost:${Y}`:void 0,X=Boolean(Q?.share||Q?.shareStartup?.status==="starting"),O=Boolean(G&&Q?.configFingerprint&&B.fingerprint&&Q.configFingerprint!==B.fingerprint),j=[];if(!G&&W!=="stopping")j.push("start");if(G)j.push("stop","restart");if(W==="running"&&V&&B.cloudflared&&!X)j.push("share");if(X)j.push("unshare");if(P)j.push("open");return{id:`${Z}:${H}`,name:H,status:W,...Y?{detail:`:${Y}`}:{},...P?{url:P}:{},...O?{restartNeeded:O}:{},actions:j}}function y0(Z){return`${Z.filter((H)=>H.status==="running").length} of ${Z.length} services running`}function E0(Z,H=process.env){let Q=(G)=>{try{return m.accessSync(G,m.constants.X_OK),m.statSync(G).isFile()}catch{return!1}};if(Z.includes("/")||Z.includes("\\"))return Q(Z);let B=process.platform==="win32"?["",...(H.PATHEXT??".EXE;.CMD;.BAT").split(";")]:[""];return(H.PATH??"").split(c.delimiter).filter(Boolean).some((G)=>B.some((W)=>Q(c.join(G,Z+W))))}function S0(Z){let H=Z.coalesceMs??150,Q=Z.flushMs??50,B=Z.retryMs??q0,G=Z.warn??(()=>{}),W=new Map,Y=new Map,V,P,X=!1,O,j=0,y=!1,f,I;function A(J){if(y)return;let $=JSON.stringify({jsonrpc:"2.0",...J});if(Buffer.byteLength($)>ZZ){if(!("id"in J)){G(`dropped an oversized ${String(J.method)} notification`);return}$=JSON.stringify({jsonrpc:"2.0",id:J.id,error:{code:-32603,message:"Result exceeds 1 MiB"}})}Z.write($+`
1
+ import{A as R,B as gZ,C as bZ,D as kZ,E as hZ,F as uZ,G as lZ,H as dZ,I as J0,a as C,b as PZ,c as CZ,d as M,f as h,g as jZ,h as FZ,i as zZ,j as LZ,k as AZ,l as _Z,m as qZ,n as xZ,o as MZ,p as IZ,q as r,r as TZ,s as yZ,t as EZ,u as SZ,v as fZ,w as wZ,x as RZ,y as vZ,z as L}from"./index-jtd14k8h.js";import{N as tZ,U as sZ,X as rZ,ra as GZ,ta as eZ,va as Z0,wa as $0}from"./index-scnd2pq4.js";import mZ from"node:crypto";import m from"node:fs";import c from"node:path";class QZ{constructor(Z){this._client=Z}async*callToolStream(Z,H=r,Q){let B=this._client,G={...Q,task:Q?.task??(B.isToolTask(Z.name)?{}:void 0)},W=B.requestStream({method:"tools/call",params:Z},H,G),Y=B.getToolOutputValidator(Z.name);for await(let V of W){if(V.type==="result"&&Y){let P=V.result;if(!P.structuredContent&&!P.isError){yield{type:"error",error:new L(M.InvalidRequest,`Tool ${Z.name} has an output schema but did not return structured content`)};return}if(P.structuredContent)try{let X=Y(P.structuredContent);if(!X.valid){yield{type:"error",error:new L(M.InvalidParams,`Structured content does not match the tool's output schema: ${X.errorMessage}`)};return}}catch(X){if(X instanceof L){yield{type:"error",error:X};return}yield{type:"error",error:new L(M.InvalidParams,`Failed to validate structured content: ${X instanceof Error?X.message:String(X)}`)};return}}yield V}}async getTask(Z,H){return this._client.getTask({taskId:Z},H)}async getTaskResult(Z,H,Q){return this._client.getTaskResult({taskId:Z},H,Q)}async listTasks(Z,H){return this._client.listTasks(Z?{cursor:Z}:void 0,H)}async cancelTask(Z,H){return this._client.cancelTask({taskId:Z},H)}requestStream(Z,H,Q){return this._client.requestStream(Z,H,Q)}}function e(Z,H){if(!Z||H===null||typeof H!=="object")return;if(Z.type==="object"&&Z.properties&&typeof Z.properties==="object"){let Q=H,B=Z.properties;for(let G of Object.keys(B)){let W=B[G];if(Q[G]===void 0&&Object.prototype.hasOwnProperty.call(W,"default"))Q[G]=W.default;if(Q[G]!==void 0)e(W,Q[G])}}if(Array.isArray(Z.anyOf)){for(let Q of Z.anyOf)if(typeof Q!=="boolean")e(Q,H)}if(Array.isArray(Z.oneOf)){for(let Q of Z.oneOf)if(typeof Q!=="boolean")e(Q,H)}}function j0(Z){if(!Z)return{supportsFormMode:!1,supportsUrlMode:!1};let H=Z.form!==void 0,Q=Z.url!==void 0;return{supportsFormMode:H||!H&&!Q,supportsUrlMode:Q}}class WZ extends kZ{constructor(Z,H){super(H);if(this._clientInfo=Z,this._cachedToolOutputValidators=new Map,this._cachedKnownTaskTools=new Set,this._cachedRequiredTaskTools=new Set,this._listChangedDebounceTimers=new Map,this._capabilities=H?.capabilities??{},this._jsonSchemaValidator=H?.jsonSchemaValidator??new uZ,H?.listChanged)this._pendingListChangedConfig=H.listChanged}_setupListChangedHandlers(Z){if(Z.tools&&this._serverCapabilities?.tools?.listChanged)this._setupListChangedHandler("tools",TZ,Z.tools,async()=>{return(await this.listTools()).tools});if(Z.prompts&&this._serverCapabilities?.prompts?.listChanged)this._setupListChangedHandler("prompts",MZ,Z.prompts,async()=>{return(await this.listPrompts()).prompts});if(Z.resources&&this._serverCapabilities?.resources?.listChanged)this._setupListChangedHandler("resources",_Z,Z.resources,async()=>{return(await this.listResources()).resources})}get experimental(){if(!this._experimental)this._experimental={tasks:new QZ(this)};return this._experimental}registerCapabilities(Z){if(this.transport)throw Error("Cannot register capabilities after connecting to transport");this._capabilities=hZ(this._capabilities,Z)}setRequestHandler(Z,H){let B=gZ(Z)?.method;if(!B)throw Error("Schema is missing a method literal");let G=bZ(B);if(typeof G!=="string")throw Error("Schema method literal must be a string");let W=G;if(W==="elicitation/create"){let Y=async(V,P)=>{let X=R(wZ,V);if(!X.success){let x=X.error instanceof Error?X.error.message:String(X.error);throw new L(M.InvalidParams,`Invalid elicitation request: ${x}`)}let{params:O}=X.data;O.mode=O.mode??"form";let{supportsFormMode:j,supportsUrlMode:y}=j0(this._capabilities.elicitation);if(O.mode==="form"&&!j)throw new L(M.InvalidParams,"Client does not support form-mode elicitation requests");if(O.mode==="url"&&!y)throw new L(M.InvalidParams,"Client does not support URL-mode elicitation requests");let f=await Promise.resolve(H(V,P));if(O.task){let x=R(FZ,f);if(!x.success){let p=x.error instanceof Error?x.error.message:String(x.error);throw new L(M.InvalidParams,`Invalid task creation result: ${p}`)}return x.data}let I=R(RZ,f);if(!I.success){let x=I.error instanceof Error?I.error.message:String(I.error);throw new L(M.InvalidParams,`Invalid elicitation result: ${x}`)}let A=I.data,w=O.mode==="form"?O.requestedSchema:void 0;if(O.mode==="form"&&A.action==="accept"&&A.content&&w){if(this._capabilities.elicitation?.form?.applyDefaults)try{e(w,A.content)}catch{}}return A};return super.setRequestHandler(Z,Y)}if(W==="sampling/createMessage"){let Y=async(V,P)=>{let X=R(EZ,V);if(!X.success){let A=X.error instanceof Error?X.error.message:String(X.error);throw new L(M.InvalidParams,`Invalid sampling request: ${A}`)}let{params:O}=X.data,j=await Promise.resolve(H(V,P));if(O.task){let A=R(FZ,j);if(!A.success){let w=A.error instanceof Error?A.error.message:String(A.error);throw new L(M.InvalidParams,`Invalid task creation result: ${w}`)}return A.data}let f=O.tools||O.toolChoice?fZ:SZ,I=R(f,j);if(!I.success){let A=I.error instanceof Error?I.error.message:String(I.error);throw new L(M.InvalidParams,`Invalid sampling result: ${A}`)}return I.data};return super.setRequestHandler(Z,Y)}return super.setRequestHandler(Z,H)}assertCapability(Z,H){if(!this._serverCapabilities?.[Z])throw Error(`Server does not support ${Z} (required for ${H})`)}async connect(Z,H){if(await super.connect(Z),Z.sessionId!==void 0)return;try{let Q=await this.request({method:"initialize",params:{protocolVersion:PZ,capabilities:this._capabilities,clientInfo:this._clientInfo}},jZ,H);if(Q===void 0)throw Error(`Server sent invalid initialize result: ${Q}`);if(!CZ.includes(Q.protocolVersion))throw Error(`Server's protocol version is not supported: ${Q.protocolVersion}`);if(this._serverCapabilities=Q.capabilities,this._serverVersion=Q.serverInfo,Z.setProtocolVersion)Z.setProtocolVersion(Q.protocolVersion);if(this._instructions=Q.instructions,await this.notification({method:"notifications/initialized"}),this._pendingListChangedConfig)this._setupListChangedHandlers(this._pendingListChangedConfig),this._pendingListChangedConfig=void 0}catch(Q){throw this.close(),Q}}getServerCapabilities(){return this._serverCapabilities}getServerVersion(){return this._serverVersion}getInstructions(){return this._instructions}assertCapabilityForMethod(Z){switch(Z){case"logging/setLevel":if(!this._serverCapabilities?.logging)throw Error(`Server does not support logging (required for ${Z})`);break;case"prompts/get":case"prompts/list":if(!this._serverCapabilities?.prompts)throw Error(`Server does not support prompts (required for ${Z})`);break;case"resources/list":case"resources/templates/list":case"resources/read":case"resources/subscribe":case"resources/unsubscribe":if(!this._serverCapabilities?.resources)throw Error(`Server does not support resources (required for ${Z})`);if(Z==="resources/subscribe"&&!this._serverCapabilities.resources.subscribe)throw Error(`Server does not support resource subscriptions (required for ${Z})`);break;case"tools/call":case"tools/list":if(!this._serverCapabilities?.tools)throw Error(`Server does not support tools (required for ${Z})`);break;case"completion/complete":if(!this._serverCapabilities?.completions)throw Error(`Server does not support completions (required for ${Z})`);break;case"initialize":break;case"ping":break}}assertNotificationCapability(Z){switch(Z){case"notifications/roots/list_changed":if(!this._capabilities.roots?.listChanged)throw Error(`Client does not support roots list changed notifications (required for ${Z})`);break;case"notifications/initialized":break;case"notifications/cancelled":break;case"notifications/progress":break}}assertRequestHandlerCapability(Z){if(!this._capabilities)return;switch(Z){case"sampling/createMessage":if(!this._capabilities.sampling)throw Error(`Client does not support sampling capability (required for ${Z})`);break;case"elicitation/create":if(!this._capabilities.elicitation)throw Error(`Client does not support elicitation capability (required for ${Z})`);break;case"roots/list":if(!this._capabilities.roots)throw Error(`Client does not support roots capability (required for ${Z})`);break;case"tasks/get":case"tasks/list":case"tasks/result":case"tasks/cancel":if(!this._capabilities.tasks)throw Error(`Client does not support tasks capability (required for ${Z})`);break;case"ping":break}}assertTaskCapability(Z){lZ(this._serverCapabilities?.tasks?.requests,Z,"Server")}assertTaskHandlerCapability(Z){if(!this._capabilities)return;dZ(this._capabilities.tasks?.requests,Z,"Client")}async ping(Z){return this.request({method:"ping"},h,Z)}async complete(Z,H){return this.request({method:"completion/complete",params:Z},vZ,H)}async setLoggingLevel(Z,H){return this.request({method:"logging/setLevel",params:{level:Z}},h,H)}async getPrompt(Z,H){return this.request({method:"prompts/get",params:Z},xZ,H)}async listPrompts(Z,H){return this.request({method:"prompts/list",params:Z},qZ,H)}async listResources(Z,H){return this.request({method:"resources/list",params:Z},zZ,H)}async listResourceTemplates(Z,H){return this.request({method:"resources/templates/list",params:Z},LZ,H)}async readResource(Z,H){return this.request({method:"resources/read",params:Z},AZ,H)}async subscribeResource(Z,H){return this.request({method:"resources/subscribe",params:Z},h,H)}async unsubscribeResource(Z,H){return this.request({method:"resources/unsubscribe",params:Z},h,H)}async callTool(Z,H=r,Q){if(this.isToolTaskRequired(Z.name))throw new L(M.InvalidRequest,`Tool "${Z.name}" requires task-based execution. Use client.experimental.tasks.callToolStream() instead.`);let B=await this.request({method:"tools/call",params:Z},H,Q),G=this.getToolOutputValidator(Z.name);if(G){if(!B.structuredContent&&!B.isError)throw new L(M.InvalidRequest,`Tool ${Z.name} has an output schema but did not return structured content`);if(B.structuredContent)try{let W=G(B.structuredContent);if(!W.valid)throw new L(M.InvalidParams,`Structured content does not match the tool's output schema: ${W.errorMessage}`)}catch(W){if(W instanceof L)throw W;throw new L(M.InvalidParams,`Failed to validate structured content: ${W instanceof Error?W.message:String(W)}`)}}return B}isToolTask(Z){if(!this._serverCapabilities?.tasks?.requests?.tools?.call)return!1;return this._cachedKnownTaskTools.has(Z)}isToolTaskRequired(Z){return this._cachedRequiredTaskTools.has(Z)}cacheToolMetadata(Z){this._cachedToolOutputValidators.clear(),this._cachedKnownTaskTools.clear(),this._cachedRequiredTaskTools.clear();for(let H of Z){if(H.outputSchema){let B=this._jsonSchemaValidator.getValidator(H.outputSchema);this._cachedToolOutputValidators.set(H.name,B)}let Q=H.execution?.taskSupport;if(Q==="required"||Q==="optional")this._cachedKnownTaskTools.add(H.name);if(Q==="required")this._cachedRequiredTaskTools.add(H.name)}}getToolOutputValidator(Z){return this._cachedToolOutputValidators.get(Z)}async listTools(Z,H){let Q=await this.request({method:"tools/list",params:Z},IZ,H);return this.cacheToolMetadata(Q.tools),Q}_setupListChangedHandler(Z,H,Q,B){let G=yZ.safeParse(Q);if(!G.success)throw Error(`Invalid ${Z} listChanged options: ${G.error.message}`);if(typeof Q.onChanged!=="function")throw Error(`Invalid ${Z} listChanged options: onChanged must be a function`);let{autoRefresh:W,debounceMs:Y}=G.data,{onChanged:V}=Q,P=async()=>{if(!W){V(null,null);return}try{let O=await B();V(null,O)}catch(O){let j=O instanceof Error?O:Error(String(O));V(j,null)}},X=()=>{if(Y){let O=this._listChangedDebounceTimers.get(Z);if(O)clearTimeout(O);let j=setTimeout(P,Y);this._listChangedDebounceTimers.set(Z,j)}else P()};this.setNotificationHandler(H,X)}async sendRootsListChanged(){return this.notification({method:"notifications/roots/list_changed"})}}class u{constructor(){this._messageQueue=[]}static createLinkedPair(){let Z=new u,H=new u;return Z._otherTransport=H,H._otherTransport=Z,[Z,H]}async start(){while(this._messageQueue.length>0){let Z=this._messageQueue.shift();this.onmessage?.(Z.message,Z.extra)}}async close(){let Z=this._otherTransport;this._otherTransport=void 0,await Z?.close(),this.onclose?.()}async send(Z,H){if(!this._otherTransport)throw Error("Not connected");if(this._otherTransport.onmessage)this._otherTransport.onmessage(Z,{authInfo:H?.authInfo});else this._otherTransport._messageQueue.push({message:Z,extra:{authInfo:H?.authInfo}})}}var z0=1,ZZ=1048576,cZ=["list_services","get_service","get_logs","start_service","stop_service","restart_service"],L0="Restart it in the terminal that started it",A0="LocalDeck isn't responding; retrying",pZ=16384,_0=200,nZ=64,d=5000,K0=ZZ-65536,q0=[1000,2000,5000,1e4],x0=/^[a-zA-Z0-9_-]+:[a-zA-Z0-9_-]+$/;class T extends Error{code;constructor(Z,H){super(H);this.code=Z}}var g=C.string().min(1).max(200),iZ=C.string().regex(x0,"Use the exact projectId:service id from services/list"),E={initialize:C.object({protocolVersion:C.number(),quarryVersion:C.string().max(100).optional()}),open:C.object({workspaceId:g,path:C.string().min(1).max(4096).refine((Z)=>c.isAbsolute(Z),"path must be absolute")}),workspace:C.object({workspaceId:g}),action:C.object({workspaceId:g,serviceId:iZ,action:C.enum(["start","stop","restart","share","unshare","open"])}),subscribe:C.object({workspaceId:g,serviceId:iZ,from:C.string().max(200).optional(),limit:C.number().int().min(1).max(d).default(1000)}),unsubscribe:C.object({subscription:C.string().min(1).max(200)}),page:C.object({workspaceId:g,pageId:C.string().min(1).max(100)}),call:C.object({workspaceId:g,name:C.string().min(1).max(100),arguments:C.record(C.string(),C.unknown()).optional()})};function S(Z,H){let Q=Z.safeParse(H??{});if(!Q.success)throw new T(-32602,Q.error.issues.map((B)=>`${B.path.join(".")||"params"}: ${B.message}`).join("; "));return Q.data}function l(Z){return Z instanceof TypeError||Z instanceof Error&&(Z.name==="TimeoutError"||Z.name==="AbortError"||/ECONNREFUSED|ECONNRESET|did not start/.test(Z.message))}function M0(Z){if(Buffer.byteLength(Z)<=pZ)return Z;return new TextDecoder().decode(Buffer.from(Z).subarray(0,pZ-3)).replace(/�+$/,"")+"…"}function H0(Z){return{cursor:Z.id,ts:Z.ts,stream:Z.stream,text:M0(Z.line)}}function oZ(Z,H,Q){let B=0,G=!1;if(H!==void 0){let O=Z.findIndex((j)=>j.id===H);if(O===-1)G=Z.length>0;else B=O+1}let W=Z.slice(B),Y=W.slice(-Q).map(H0),V=0,P=Y.length;while(P>0){if(V+=Buffer.byteLength(JSON.stringify(Y[P-1]))+1,V>K0)break;P--}let X=Y.slice(P);return{lines:X,truncated:G||X.length<W.length}}function I0(Z){for(let H of Z){let Q=H.replace(/^(http:\/\/[a-z0-9-]+(?:\.[a-z0-9-]+)?\.localhost):\d+(?=\/|$)/i,"$1");if(Q!==H)return Q}return}function T0(Z,H,Q,B={}){let G=Q?.status==="running"||Q?.status==="starting",W;if(!Q||Q.status==="stopped")W=Q&&(Q.readinessStatus==="failed"||Q.lastError)?"failed":"stopped";else if(Q.status==="stopping")W="stopping";else if(Q.readinessStatus==="failed")W="failed";else if(Q.status==="starting"||!Q.upstreamReady||Q.readinessStatus==="checking")W="starting";else W="running";let Y=Q?.stablePort??B.command?.port,V=!(Q?.serviceType??B.command?.serviceType)||(Q?.serviceType??B.command?.serviceType)==="http",P=V&&Y?(B.cleanUrls&&Q?I0(Q.urls):void 0)??`http://localhost:${Y}`:void 0,X=Boolean(Q?.share||Q?.shareStartup?.status==="starting"),O=Boolean(G&&Q?.configFingerprint&&B.fingerprint&&Q.configFingerprint!==B.fingerprint),j=[];if(!G&&W!=="stopping")j.push("start");if(G)j.push("stop","restart");if(W==="running"&&V&&B.cloudflared&&!X)j.push("share");if(X)j.push("unshare");if(P)j.push("open");return{id:`${Z}:${H}`,name:H,status:W,...Y?{detail:`:${Y}`}:{},...P?{url:P}:{},...O?{restartNeeded:O}:{},actions:j}}function y0(Z){return`${Z.filter((H)=>H.status==="running").length} of ${Z.length} services running`}function E0(Z,H=process.env){let Q=(G)=>{try{return m.accessSync(G,m.constants.X_OK),m.statSync(G).isFile()}catch{return!1}};if(Z.includes("/")||Z.includes("\\"))return Q(Z);let B=process.platform==="win32"?["",...(H.PATHEXT??".EXE;.CMD;.BAT").split(";")]:[""];return(H.PATH??"").split(c.delimiter).filter(Boolean).some((G)=>B.some((W)=>Q(c.join(G,Z+W))))}function S0(Z){let H=Z.coalesceMs??150,Q=Z.flushMs??50,B=Z.retryMs??q0,G=Z.warn??(()=>{}),W=new Map,Y=new Map,V,P,X=!1,O,j=0,y=!1,f,I;function A(J){if(y)return;let $=JSON.stringify({jsonrpc:"2.0",...J});if(Buffer.byteLength($)>ZZ){if(!("id"in J)){G(`dropped an oversized ${String(J.method)} notification`);return}$=JSON.stringify({jsonrpc:"2.0",id:J.id,error:{code:-32603,message:"Result exceeds 1 MiB"}})}Z.write($+`
2
2
  `)}let w=(J,$)=>A({method:J,params:$}),x=(J,$,K)=>A({id:J,error:{code:$,message:K}});function p(J,$){let K={workspaceId:J.id,...$},F=JSON.stringify(K);if(F===J.lastStatus)return;J.lastStatus=F,w("status",K)}function n(){let J=V;V=void 0,P=void 0;try{J?.close()}catch{}}function $Z(J){if(y||!W.size||V&&P===J)return;n();let $=Z.createWebSocket(`ws://127.0.0.1:${J}/api/events`);V=$,P=J,$.on("open",()=>{if(V!==$)return;if(j=0,X){X=!1;for(let K of Y.values())X0(K)}}),$.on("message",(K)=>{if(V===$)Q0(K)}),$.on("error",(K)=>{if(V===$)G(`event stream error: ${K.message}`)}),$.on("close",()=>{if(V!==$)return;V=void 0,P=void 0,b()})}function b(){if(y)return;X=!0;for(let J of W.values())p(J,{state:"degraded",message:A0});n(),DZ()}function DZ(){if(y||O||!W.size)return;let J=B[Math.min(j++,B.length-1)];O=setTimeout(async()=>{if(O=void 0,y||!W.size||V)return;let $=await Z.discover().catch(()=>{return});if(y||!W.size||V)return;if($)$Z($.apiPort);else DZ()},J)}function Q0(J){let $;try{$=JSON.parse(String(J))}catch{return}if($.type==="snapshot")for(let K of W.values())i(K);else if($.type==="service"){for(let K of W.values())if($.service.projectId===K.projectId)i(K)}else if($.type==="service:removed"){for(let K of W.values())if($.name.startsWith(`${K.projectId}:`))i(K)}else if($.type==="log"){for(let K of Y.values())if(K.serviceId===$.log.service)a(K,H0($.log))}else if($.type==="history:cleared"&&$.kind==="logs"){for(let K of Y.values())if(K.serviceId===$.service)a(K,{cursor:$.beforeId,ts:Date.now(),stream:"system",text:"Logs cleared in LocalDeck"})}}function i(J){if(J.timer||y)return;J.timer=setTimeout(()=>{J.timer=void 0,F0(J)},H)}async function F0(J){if(W.get(J.id)!==J)return;try{let $=await Z.discover();if(!$)return b();let K=await JZ($.api,J.projectId);if(W.get(J.id)!==J)return;BZ(J,K)}catch($){if(l($))b();else G(`could not refresh services: ${$ instanceof Error?$.message:String($)}`)}}function BZ(J,$){let K=JSON.stringify($);if(K!==J.lastItems)J.lastItems=K,w("services/changed",{workspaceId:J.id,items:$});p(J,{state:"ready",summary:y0($)})}async function W0(J,$){try{let K=await J.project($);return{details:K,runtime:K.services}}catch(K){if(l(K))throw K;return{runtime:(await J.services()).filter((F)=>F.projectId===$)}}}async function G0(J){if(!f||Date.now()-f.at>15000)f={ready:await J.forwarder().then(($)=>$.ready===!0,()=>!1),at:Date.now()};return f.ready}function D0(){if(!I||Date.now()-I.at>60000)I={available:Z.cloudflared?Z.cloudflared():E0(process.env.LOCALDECK_CLOUDFLARED??"cloudflared"),at:Date.now()};return I.available}async function JZ(J,$,K){let[{details:F,runtime:U},N]=await Promise.all([W0(J,$),G0(J)]),_=D0(),z=new Map(U.map((q)=>[q.name,q]));for(let q of U)K?.set(q.key,q);let D=F?.commands??[];return[...D.map((q)=>q.name),...U.map((q)=>q.name).filter((q)=>!D.some((s)=>s.name===q)).sort()].slice(0,_0).map((q)=>T0($,q,z.get(q),{command:D.find((s)=>s.name===q),fingerprint:F?.fingerprints?.[q],cleanUrls:N,cloudflared:_}))}async function KZ(){let J;try{J=await Z.connect()}catch($){throw b(),new T(-32000,`LocalDeck isn't responding: ${$ instanceof Error?$.message:String($)}`)}return $Z(J.apiPort),J}async function o(J){let $=await KZ();try{return await J($)}catch(K){if(K instanceof T)throw K;if(l(K))throw b(),new T(-32000,"LocalDeck isn't responding");throw new T(-32000,K instanceof Error?K.message:String(K))}}function v(J){let $=W.get(J);if(!$)throw new T(-32602,"Unknown workspace; call workspace/open first");return $}function YZ(J,$){if(!$.startsWith(`${J.projectId}:`))throw new T(-32602,"That service belongs to another project")}async function HZ(J){let $=W.get(J);if(!$)return;W.delete(J),clearTimeout($.timer);for(let F of Y.values())if(F.workspaceId===J)UZ(F.id);if(!W.size)n(),clearTimeout(O),O=void 0,X=!1,j=0;let K=$.tools;if($.tools=void 0,K)await K.then((F)=>F.close(),()=>{})}async function B0(J,$){await HZ(J);let K;try{K=m.realpathSync($)}catch{return{active:!1,reason:"The folder couldn't be found"}}let F=sZ.map((D)=>c.join(K,D)).find((D)=>{try{return m.statSync(D).isFile()}catch{return!1}});if(!F)return{active:!1,reason:"No .localdeck file in this folder"};let U=c.basename(F);try{rZ(F)}catch(D){let k=(D instanceof Error?D.message:String(D)).replace(new RegExp(`^${U.replace(/\./g,"\\.")}:\\s*`),"");return{active:!1,reason:`${U} couldn't be read: ${k}`}}let{projectId:N,apiPort:_}=await o(async({api:D,apiPort:k,controlToken:q})=>{return{projectId:(await D.projects()).find((C0)=>C0.directory===K)?.id??(await D.rememberProject(F,q)).id,apiPort:k}}),z={id:J,path:K,projectId:N};return W.set(J,z),$Z(_),i(z),{active:!0}}async function Y0(J,$,K){return YZ(J,$),o(async({api:F})=>{let U=new Map,N=(await JZ(F,J.projectId,U)).find((D)=>D.id===$);if(!N)throw new T(-32602,"Unknown service; use services/list");let _=U.get($),z=N.name;try{if(K==="start"||K==="restart"){if(K==="restart"&&_?.managedBy==="terminal"&&_.status!=="stopped")return{ok:!1,message:L0};let D=await F.serviceAction(J.projectId,z,K);return{ok:D.ok,...D.error?{message:D.error}:{}}}if(K==="stop"){if(!_)return{ok:!1,message:"It isn't running"};let D=await F.stop($);return{ok:D.ok,...D.ok?{}:{message:"It isn't running"}}}if(K==="share"){if(!N.actions.includes("share"))return{ok:!1,message:N.actions.includes("unshare")?"It's already shared":N.status!=="running"?"Start it before sharing":"Sharing needs cloudflared"};let D=mZ.randomBytes(12).toString("base64url");return{ok:!0,url:(await F.share($,D,!0,!1)).url,secret:D}}if(K==="unshare"){let D=await F.unshare($);return{ok:D.ok,...D.ok?{}:{message:"It isn't shared"}}}return N.url?{ok:!0,url:N.url}:{ok:!1,message:"It has no address"}}catch(D){if(l(D))throw D;return{ok:!1,message:D instanceof Error?D.message:String(D)}}})}function a(J,$){if(J.pending){if(J.pending.push($),J.pending.length>d)J.pending.shift();return}if(J.queue.push($),J.lastCursor=$.cursor,J.queue.length>d)J.queue.shift(),J.dropped++;J.timer??=setTimeout(()=>O0(J),Q)}function O0(J){if(J.timer=void 0,Y.get(J.id)!==J)return;let $=J.queue.splice(0),K=J.dropped;J.dropped=0;let F=[],U=0,N=(_)=>{if(!F.length&&!(_&&K))return;w("logs/append",{subscription:J.id,lines:F,..._&&K?{dropped:K}:{}}),F=[],U=0};for(let _ of $){let z=Buffer.byteLength(JSON.stringify(_))+1;if(U+z>K0)N(!1);F.push(_),U+=z}N(!0)}async function OZ(J,$){try{return await J.logs($,d)}catch(K){if(!l(K)&&/unknown service|not found/i.test(K instanceof Error?K.message:""))return[];throw K}}async function U0(J){let $=v(J.workspaceId);if(YZ($,J.serviceId),Y.size>=nZ)throw new T(-32000,`At most ${nZ} log subscriptions`);let K={id:mZ.randomUUID(),workspaceId:$.id,serviceId:J.serviceId,pending:[],queue:[],dropped:0};Y.set(K.id,K);try{let F=await o(({api:D})=>OZ(D,J.serviceId)),{lines:U,truncated:N}=oZ(F,J.from,J.limit),_=new Set(F.map((D)=>D.id)),z=K.pending.filter((D)=>!_.has(D.cursor));K.pending=void 0,K.lastCursor=F.at(-1)?.id??J.from;for(let D of z)a(K,D);return{subscription:K.id,lines:U,truncated:N}}catch(F){throw Y.delete(K.id),F}}async function X0(J){try{let $=await Z.discover();if(!$||Y.get(J.id)!==J)return;let K=await OZ($.api,J.serviceId);if(Y.get(J.id)!==J)return;let{lines:F}=oZ(K,J.lastCursor,d);for(let U of F)a(J,U)}catch($){G(`could not catch up logs: ${$ instanceof Error?$.message:String($)}`)}}function UZ(J){let $=Y.get(J);if(!$)return;clearTimeout($.timer),Y.delete(J)}async function XZ(J){return J.tools??=(async()=>{let $=J0({projectId:J.projectId,projectSecrets:Z.projectSecrets,connect:async()=>{let N=await KZ();return{api:N.api,secrets:[N.controlToken]}}}),[K,F]=u.createLinkedPair(),U=new WZ({name:"quarry",version:GZ});return await $.connect(F),await U.connect(K),{client:U,close:async()=>{await U.close(),await $.close()}}})(),(await J.tools).client}async function V0(J,$){switch(J){case"initialize":return S(E.initialize,$),{protocolVersion:z0,name:"LocalDeck",version:GZ};case"workspace/open":{let K=S(E.open,$);return B0(K.workspaceId,K.path)}case"workspace/close":return await HZ(S(E.workspace,$).workspaceId),{};case"services/list":{let K=v(S(E.workspace,$).workspaceId),F=await o(({api:U})=>JZ(U,K.projectId));if(W.get(K.id)===K)BZ(K,F);return{items:F}}case"services/action":{let K=S(E.action,$);return Y0(v(K.workspaceId),K.serviceId,K.action)}case"logs/subscribe":return U0(S(E.subscribe,$));case"logs/unsubscribe":return UZ(S(E.unsubscribe,$).subscription),{};case"pages/open":{let K=S(E.page,$),F=v(K.workspaceId);if(K.pageId!=="dashboard")throw new T(-32602,`Unknown page "${K.pageId}"`);let{apiPort:U}=await KZ();return{url:`http://127.0.0.1:${U}/projects/${encodeURIComponent(F.projectId)}`}}case"tools/list":{let K=v(S(E.workspace,$).workspaceId),F=(await(await XZ(K)).listTools()).tools;return{tools:cZ.flatMap((U)=>F.filter((N)=>N.name===U))}}case"tools/call":{let K=S(E.call,$),F=v(K.workspaceId);if(!cZ.includes(K.name))throw new T(-32602,`Unknown tool "${K.name}"`);let U=await XZ(F);try{return await U.callTool({name:K.name,arguments:K.arguments??{}})}catch(N){return{content:[{type:"text",text:N instanceof Error?N.message:String(N)}],isError:!0}}}case"shutdown":return{};default:throw new T(-32601,`Method not found: ${J}`)}}function N0(J){let $;try{$=JSON.parse(J)}catch{return x(null,-32700,"Parse error")}if(!$||typeof $!=="object"||Array.isArray($))return x(null,-32600,"Invalid request");let{id:K,method:F,params:U,jsonrpc:N}=$,_=K===void 0||K===null||typeof K==="string"||typeof K==="number";if(F===void 0&&(("result"in $)||("error"in $)))return;if(N!=="2.0"||typeof F!=="string"||!_)return x(_&&K!==void 0?K:null,-32600,"Invalid request");if(K===void 0)return;V0(F,U).then((z)=>{if(A({id:K,result:z}),F==="shutdown")NZ().finally(()=>Z.onShutdown?.())},(z)=>{if(z instanceof T)x(K,z.code,z.message);else G(z instanceof Error?z.message:String(z)),x(K,-32603,"Internal error")})}let VZ=Buffer.alloc(0),t=!1;function P0(J){if(y)return;let $=Buffer.concat([VZ,typeof J==="string"?Buffer.from(J):J]);for(let K=$.indexOf(10);K!==-1;K=$.indexOf(10)){let F=$.subarray(0,K);if($=$.subarray(K+1),t){t=!1;continue}if(F.length>ZZ){x(null,-32600,"Message exceeds 1 MiB");continue}let U=F.toString("utf8").trim();if(U)N0(U)}if($.length>ZZ){if(!t)x(null,-32600,"Message exceeds 1 MiB");t=!0,$=Buffer.alloc(0)}VZ=Buffer.from($)}async function NZ(){if(y)return;let J=[...W.keys()];for(let $ of J)await HZ($);y=!0,n(),clearTimeout(O);for(let $ of Y.values())clearTimeout($.timer);Y.clear()}return{receive:P0,close:NZ}}var aZ=`Usage: localdeck quarry
3
3
  Speaks the Quarry Extension Protocol (version 1) over stdio so Quarry can show and control this project's services.
4
4
  Started by Quarry; stdout is reserved for protocol messages. Connecting starts no services.`;async function r0(Z){if(Z.includes("--help")||Z.includes("-h")){console.log(aZ);return}if(Z.length)throw Error(aZ);console.log=console.info=(...G)=>console.error(...G);let H=(G)=>({api:new $0(G.apiPort,globalThis.fetch,60000),apiPort:G.apiPort,controlToken:G.controlToken}),Q=()=>{},B=S0({connect:async()=>H(await Z0()),discover:async()=>{let G=await eZ();return G?H(G):void 0},createWebSocket:(G)=>new tZ(G),write:(G)=>{process.stdout.write(G)},warn:(G)=>{process.stderr.write(`LocalDeck: ${G}
@@ -1 +1 @@
1
- import{P as F,R as H,ta as C,wa as I}from"./index-2da1tyad.js";import{spawn as q}from"node:child_process";import X from"node:fs";import N from"node:path";import{fileURLToPath as w}from"node:url";function A(z,J,G=process.platform){let B=G==="win32"?N.win32:N.posix,Q=B.normalize(z),M=B.dirname(Q),O=(K,Y)=>G==="win32"?K.toLowerCase()===Y.toLowerCase():K===Y;if(B.basename(Q)!=="localdeck"||!O(B.basename(M),"node_modules"))throw Error("--update requires a global npm installation. Source checkouts and linked development builds must be updated manually.");if(O(M,B.normalize(J)))return G==="win32"?B.dirname(M):B.dirname(B.dirname(M));if(G!=="win32"&&B.basename(B.dirname(M))==="lib")return B.dirname(B.dirname(M));throw Error("This is not the active global npm installation. Update it with the package manager and prefix used to install it.")}function D(){let z=[N.resolve(N.dirname(process.execPath),"node_modules/npm/bin/npm-cli.js"),N.resolve(N.dirname(process.execPath),"../lib/node_modules/npm/bin/npm-cli.js")];for(let G of(process.env.PATH??"").split(N.delimiter)){if(!G)continue;z.push(N.join(G,"node_modules/npm/bin/npm-cli.js"));try{let B=X.realpathSync(N.join(G,"npm"));if(N.basename(B)==="npm-cli.js")z.push(B)}catch{}}let J=z.find((G)=>X.existsSync(G));if(!J)throw Error("npm was not found. Install Node.js with npm, then run localdeck --update again.");return[process.execPath,J]}async function $(z,J=!1){return new Promise((G,B)=>{let Q=q(z[0],z.slice(1),{stdio:J?["ignore","pipe","inherit"]:"inherit",shell:!1}),M="";Q.stdout?.on("data",(O)=>{M+=O.toString()}),Q.once("error",B),Q.once("close",(O,K)=>O===0?G(M.trim()):B(Error(`Command failed (${K??`exit ${O}`}).`)))})}function E(z,J,G=process.platform){let B=G==="win32"?N.win32:N.posix;for(let Q of[z,B.dirname(z),G==="win32"?J:B.join(J,"bin")])try{X.accessSync(Q,X.constants.W_OK|X.constants.X_OK)}catch(M){let O=M.code;if(O==="EACCES"||O==="EPERM")return!1;throw M}return!0}async function L(z){let J=z.platform??process.platform,G=z.execute??$,B=[...z.npm,"install","--global","--prefix",z.prefix,"localdeck@latest","--registry=https://registry.npmjs.org/","--ignore-scripts"];if((z.writable??E)(z.packageRoot,z.prefix,J)){await G(B);return}if(J!=="darwin"&&J!=="linux")throw Error("The installation requires administrator access. Install localdeck@latest with npm in an administrator terminal, then restart LocalDeck as your normal user.");if(!(z.interactive??Boolean(process.stdin.isTTY&&process.stdout.isTTY)))throw Error("The installation requires administrator access. Run localdeck --update in an interactive terminal so npm can request permission. Do not run LocalDeck with sudo.");(z.log??console.log)(`Administrator access is required to update ${z.prefix}. Only npm will run with sudo; LocalDeck will continue as your normal user.`),await G(["/usr/bin/sudo","-H","--",...B])}async function S(z){await z.install();let J=await z.validate();return await z.stop(),await z.start(),J}async function T(){H();let z=X.realpathSync(N.resolve(N.dirname(w(import.meta.url)),"..")),J=D(),G=await $([...J,"root","--global"],!0),B=A(z,G),Q=N.join(z,"bin/localdeck.js");console.log(`Updating LocalDeck from npm in ${B}…`),console.log("After installation, the daemon will restart. Managed services and public shares will stop; start them again when ready.");let M="",O=await S({install:async()=>{try{await L({npm:J,packageRoot:z,prefix:B})}catch(K){throw Error(`npm update failed. The daemon was not restarted. ${K instanceof Error?K.message:K}`)}},validate:async()=>{let K=await $([process.execPath,Q,"--version"],!0);if(!/^\d+\.\d+\.\d+(?:[-+][\w.-]+)?$/.test(K))throw Error("The updated CLI could not be verified. The daemon was not restarted.");return M=K,K},stop:async()=>{let K=await C();if(!K)return;await new I(K.apiPort,globalThis.fetch,30000).shutdown();let Y=Date.now()+30000,W=()=>{try{return JSON.parse(X.readFileSync(F,"utf8")).pid===K.pid}catch(Z){if(Z.code==="ENOENT")return!1;throw Z}};while(W()){if(Date.now()>=Y)throw Error("Package updated, but the daemon did not stop within 30 seconds. Restart it manually.");await new Promise((Z)=>setTimeout(Z,150))}},start:async()=>{try{if(await $([process.execPath,Q,"daemon","start"]),(await C())?.version!==M)throw Error("Unexpected daemon version")}catch{throw Error("Package updated, but the daemon could not restart. Run localdeck daemon start to retry.")}}});console.log(`LocalDeck ${O} installed. The daemon has restarted.`)}export{T as updateLocalDeck,E as installationWritable,A as installationPrefix,L as installUpdate,S as applyUpdate};
1
+ import{P as F,R as H,ta as C,wa as I}from"./index-scnd2pq4.js";import{spawn as q}from"node:child_process";import X from"node:fs";import N from"node:path";import{fileURLToPath as w}from"node:url";function A(z,J,G=process.platform){let B=G==="win32"?N.win32:N.posix,Q=B.normalize(z),M=B.dirname(Q),O=(K,Y)=>G==="win32"?K.toLowerCase()===Y.toLowerCase():K===Y;if(B.basename(Q)!=="localdeck"||!O(B.basename(M),"node_modules"))throw Error("--update requires a global npm installation. Source checkouts and linked development builds must be updated manually.");if(O(M,B.normalize(J)))return G==="win32"?B.dirname(M):B.dirname(B.dirname(M));if(G!=="win32"&&B.basename(B.dirname(M))==="lib")return B.dirname(B.dirname(M));throw Error("This is not the active global npm installation. Update it with the package manager and prefix used to install it.")}function D(){let z=[N.resolve(N.dirname(process.execPath),"node_modules/npm/bin/npm-cli.js"),N.resolve(N.dirname(process.execPath),"../lib/node_modules/npm/bin/npm-cli.js")];for(let G of(process.env.PATH??"").split(N.delimiter)){if(!G)continue;z.push(N.join(G,"node_modules/npm/bin/npm-cli.js"));try{let B=X.realpathSync(N.join(G,"npm"));if(N.basename(B)==="npm-cli.js")z.push(B)}catch{}}let J=z.find((G)=>X.existsSync(G));if(!J)throw Error("npm was not found. Install Node.js with npm, then run localdeck --update again.");return[process.execPath,J]}async function $(z,J=!1){return new Promise((G,B)=>{let Q=q(z[0],z.slice(1),{stdio:J?["ignore","pipe","inherit"]:"inherit",shell:!1}),M="";Q.stdout?.on("data",(O)=>{M+=O.toString()}),Q.once("error",B),Q.once("close",(O,K)=>O===0?G(M.trim()):B(Error(`Command failed (${K??`exit ${O}`}).`)))})}function E(z,J,G=process.platform){let B=G==="win32"?N.win32:N.posix;for(let Q of[z,B.dirname(z),G==="win32"?J:B.join(J,"bin")])try{X.accessSync(Q,X.constants.W_OK|X.constants.X_OK)}catch(M){let O=M.code;if(O==="EACCES"||O==="EPERM")return!1;throw M}return!0}async function L(z){let J=z.platform??process.platform,G=z.execute??$,B=[...z.npm,"install","--global","--prefix",z.prefix,"localdeck@latest","--registry=https://registry.npmjs.org/","--ignore-scripts"];if((z.writable??E)(z.packageRoot,z.prefix,J)){await G(B);return}if(J!=="darwin"&&J!=="linux")throw Error("The installation requires administrator access. Install localdeck@latest with npm in an administrator terminal, then restart LocalDeck as your normal user.");if(!(z.interactive??Boolean(process.stdin.isTTY&&process.stdout.isTTY)))throw Error("The installation requires administrator access. Run localdeck --update in an interactive terminal so npm can request permission. Do not run LocalDeck with sudo.");(z.log??console.log)(`Administrator access is required to update ${z.prefix}. Only npm will run with sudo; LocalDeck will continue as your normal user.`),await G(["/usr/bin/sudo","-H","--",...B])}async function S(z){await z.install();let J=await z.validate();return await z.stop(),await z.start(),J}async function T(){H();let z=X.realpathSync(N.resolve(N.dirname(w(import.meta.url)),"..")),J=D(),G=await $([...J,"root","--global"],!0),B=A(z,G),Q=N.join(z,"bin/localdeck.js");console.log(`Updating LocalDeck from npm in ${B}…`),console.log("After installation, the daemon will restart. Managed services and public shares will stop; start them again when ready.");let M="",O=await S({install:async()=>{try{await L({npm:J,packageRoot:z,prefix:B})}catch(K){throw Error(`npm update failed. The daemon was not restarted. ${K instanceof Error?K.message:K}`)}},validate:async()=>{let K=await $([process.execPath,Q,"--version"],!0);if(!/^\d+\.\d+\.\d+(?:[-+][\w.-]+)?$/.test(K))throw Error("The updated CLI could not be verified. The daemon was not restarted.");return M=K,K},stop:async()=>{let K=await C();if(!K)return;await new I(K.apiPort,globalThis.fetch,30000).shutdown();let Y=Date.now()+30000,W=()=>{try{return JSON.parse(X.readFileSync(F,"utf8")).pid===K.pid}catch(Z){if(Z.code==="ENOENT")return!1;throw Z}};while(W()){if(Date.now()>=Y)throw Error("Package updated, but the daemon did not stop within 30 seconds. Restart it manually.");await new Promise((Z)=>setTimeout(Z,150))}},start:async()=>{try{if(await $([process.execPath,Q,"daemon","start"]),(await C())?.version!==M)throw Error("Unexpected daemon version")}catch{throw Error("Package updated, but the daemon could not restart. Run localdeck daemon start to retry.")}}});console.log(`LocalDeck ${O} installed. The daemon has restarted.`)}export{T as updateLocalDeck,E as installationWritable,A as installationPrefix,L as installUpdate,S as applyUpdate};
@@ -45,7 +45,7 @@ Readiness defaults to a 60-second timeout and a 400ms retry interval. A command
45
45
 
46
46
  For Docker Compose databases, set `upstream` to the host-published database port as shown above. Container listeners are not descendants of the `docker compose` client process, so LocalDeck cannot safely infer their ownership from the local process tree.
47
47
 
48
- Native database presets are `ready: "postgres"` (requires `pg_isready`) and `ready: "redis"` (requires `redis-cli`). The matching `serviceType` selects this check by default. Compose checks use tools inside the named container: `{ "type": "compose", "service": "redis", "engine": "redis" }`. Compose service names and engines are validated; the host still needs Docker. **Listening** means TCP connections are accepted; **ready** means the configured readiness contract passed. Custom HTTP/command checks also run for services with no dependents.
48
+ Native database presets are `ready: "postgres"` (requires `pg_isready`) and `ready: "redis"` (requires `redis-cli`). The matching `serviceType` selects this check by default. Compose checks use tools inside the named container: `{ "type": "compose", "service": "redis", "engine": "redis" }`. Compose service names and engines are validated; the host still needs Docker. **Listening** means TCP connections are accepted; **ready** means the configured readiness contract passed. A command check does not wait for a listener, so a background worker that never opens its port can use one (even `{ "type": "command", "run": "true" }`) to report ready. Custom HTTP/command checks also run for services with no dependents.
49
49
 
50
50
  ### Environment wiring
51
51
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "localdeck",
3
- "version": "1.7.0",
3
+ "version": "1.7.1",
4
4
  "type": "module",
5
5
  "description": "Stable ports, shareable HTTPS links and request logs for your local dev servers",
6
6
  "bin": {