localdeck 1.7.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +1 -1
- package/dashboard/assets/index-BNbydS4x.js +21 -0
- package/dashboard/index.html +1 -1
- package/dist/{index-2da1tyad.js → index-hdw8ggnb.js} +3 -3
- package/dist/{index-fmgnn6mt.js → index-xhf909hw.js} +1 -1
- package/dist/index.js +2 -2
- package/dist/{mcp-59a41rj3.js → mcp-yqgy25c4.js} +1 -1
- package/dist/quarry-31n76q0s.js +5 -0
- package/dist/{update-zhsjwnrw.js → update-c2m151t6.js} +1 -1
- package/docs/configuration.md +1 -1
- package/docs/quarry.md +11 -2
- package/package.json +1 -1
- package/dashboard/assets/index-CbmaAEDy.js +0 -21
- package/dist/quarry-23qjnaj9.js +0 -5
package/dashboard/index.html
CHANGED
|
@@ -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-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-BNbydS4x.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-DDw1Wq-H.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
@@ -124,12 +124,12 @@ LocalDeck: service name "${L}" is ambiguous; use ${_.alternatives.map((T)=>`${T}
|
|
|
124
124
|
Connection: close\r
|
|
125
125
|
Content-Length: 0\r
|
|
126
126
|
\r
|
|
127
|
-
`)}async function o7($,Z,Q,X,G){let{registry:J,store:V,shares:z,projects:Y,supervisor:K}=G,N=$.method??"GET";if(N==="OPTIONS"){Z.writeHead(204).end();return}if(X.length===1&&X[0]==="status"&&N==="GET")return x(Z,200,{ok:!0,pid:process.pid,version:G.version,startedAt:G.startedAt,services:J.list().length});if(X.length===1&&X[0]==="shutdown"&&N==="POST"){let U=new Promise((C)=>{Z.once("finish",C),Z.once("close",C)}),W=G.shutdown(U);x(Z,200,{ok:!0}),W.catch(()=>{});return}if(await k5($,Z,Q,X,G))return;if(X[0]==="projects"){if(X.length===1&&N==="GET")return x(Z,200,Y.list());if(X.length===2&&X[1]==="remember"&&N==="POST"){if(j(G),!C4($,G.controlToken))throw new I(403,"forbidden");let U=await n($);if(j(G),!U||typeof U!=="object"||Array.isArray(U))throw new I(400,"request body must be a JSON object");let W=U.file;if(typeof W!=="string")throw new I(400,"file must be a string");try{return x(Z,200,Y.remember(W))}catch(C){if(C instanceof q)throw C;throw new q("invalid","project could not be remembered")}}if(X.length>=2&&X[1]!=="remember"){let U=X[1];if(X.length===3&&X[2]==="secrets"&&N==="GET"){let W=_$(Y,U);if(!W.available)throw new q("invalid",W.error??"project configuration is invalid");let C=G.listProjectSecrets??A0,D=W.commands.flatMap((L)=>L.secrets??[]),O=new Set(C(U)),B=[...new Set([...D,...O])].sort();return x(Z,200,{secrets:B.map((L)=>({name:L,configured:O.has(L)}))})}if(X.length===4&&X[2]==="secrets"&&(N==="PUT"||N==="DELETE")){j(G);let W=_$(Y,U);if(!W.available)throw new q("invalid",W.error??"project configuration is invalid");let C=X[3];if(N==="PUT"){let D=await n($);if(!D||typeof D!=="object"||Array.isArray(D)||Object.keys(D).length!==1||typeof D.value!=="string")throw new I(400,'request body must contain only a string "value"');(G.setProjectSecret??D$)(U,C,D.value)}else(G.deleteProjectSecret??O$)(U,C);return x(Z,200,{ok:!0})}if(X.length===3&&X[2]==="nickname"&&N==="PATCH"){j(G);let W=await n($);if(j(G),!W||typeof W!=="object"||Array.isArray(W)||Object.keys(W).length!==1||typeof W.nickname!=="string")throw new I(400,'request body must contain only a string "nickname"');let C=Y.saveConfigNickname(U,W.nickname);return J.refreshProjectUrls(U),x(Z,200,{...C,services:J.list(U)})}if(X.length===3&&X[2]==="diagnostics"&&N==="GET"){let W=Y.details(U),C=J.list(U),D=C.flatMap((L)=>V.logs(L.key,100)).sort((L,_)=>L.ts-_.ts),O=(G.listProjectSecrets??A0)(U),B=Object.values((G.resolveProjectSecrets??z0)(U,O));return x(Z,200,{report:b5(W,C,D,G.version,[G.controlToken,...B])})}if(X.length===3&&X[2]==="profiles"&&N==="GET"){let W=_$(Y,U);if(!W.available)throw new q("invalid",W.error??"project configuration is invalid");return x(Z,200,O4(W))}if(X.length===4&&X[2]==="profiles"&&X[3]==="active"&&N==="PUT"){j(G);let W=await n($);if(j(G),!W||typeof W!=="object"||Array.isArray(W)||Object.keys(W).some((D)=>D!=="profiles"))throw new I(400,'request body must be { "profiles": [...] }');let C=Y.setActiveProfiles(U,W.profiles);return x(Z,200,O4(C))}if(X.length===2&&N==="GET"){let W=Y.details(U);if(!W.available)throw new q("invalid",W.error??"project configuration is invalid");return x(Z,200,{...W,services:J.list(U)})}if(X.length===2&&N==="DELETE"){j(G);let W=new Set(J.list().filter((C)=>C.status!=="stopped").map((C)=>C.key));return Y.forget(U,W),x(Z,200,{ok:!0})}if(X.length===3&&N==="POST"&&(X[2]==="start"||X[2]==="stop")){j(G),await n($),j(G);let W=_$(Y,U);if(X[2]==="start"&&!W.available)throw new q("invalid",W.error??"project configuration is invalid");let C=X[2]==="start"?await K.startAll(U):await K.stopAll(U);return x(Z,200,{ok:C.every((D)=>D.ok),results:C})}if(X.length===5&&X[2]==="services"&&X[4]==="config"&&N==="PATCH"){j(G);let W=await n($);j(G);let C=Y.updateServiceConfig(U,X[3],W);return x(Z,200,{...C,services:J.list(U)})}if(X.length===5&&X[2]==="services"&&X[4]==="dependencies"&&N==="PATCH"){j(G);let W=await n($);if(j(G),!W||typeof W!=="object"||Array.isArray(W))throw new I(400,"request body must be a JSON object");let C=Object.keys(W);if(C.length!==1||C[0]!=="after")throw new I(400,'request body may contain only "after"');let D=W.after;if(!Array.isArray(D)||!D.every((B)=>typeof B==="string"))throw new I(400,"after must be an array of service names");let O=Y.updateDependencies(U,X[3],D);return x(Z,200,{...O,services:J.list(U)})}if(X.length===5&&X[2]==="services"&&N==="POST"&&(X[4]==="start"||X[4]==="stop"||X[4]==="restart"))return z4(Z,async()=>{j(G),await n($),j(G);let W=X[3],C=_$(Y,U),D=u(U,W.toLowerCase());if(X[4]==="stop"){let O=J.get(D);if(!O||O.status==="stopped"){if(!C.available)throw new q("not_found",`Project ${U} has no active service named ${W}`);Y.resolve(U,W)}return K.stop(D)}if(!C.available)throw new q("invalid",C.error??"project configuration is invalid");return Y.resolve(U,W),X[4]==="start"?K.start(U,W):K.restart(U,W)})}}if(X[0]==="services"){if(X.length===1&&N==="GET")return x(Z,200,J.list());let U=X.length===4&&X[2]==="share"&&X[3]==="new"&&N==="POST";if(X.length<2||X.length>3&&!U)return x(Z,404,{error:"not found"});let W=X[1],C=J.resolve(W);if(C.kind==="ambiguous")return x(Z,409,{error:`service name "${W}" is ambiguous`,alternatives:C.alternatives});if(C.kind==="missing")return x(Z,404,{error:`unknown service "${W}"`});let{key:D,service:O}=C,B=X[2];if(B==="response"&&N==="GET"){let L=V.requests(D,5000).find((H)=>H.id===Q.searchParams.get("requestId"));if(!L)throw new I(404,"Recorded request is no longer available");let _=L.responseBodyId?V.responseBodies.get(L.responseBodyId,D):void 0;if(!_)throw new I(404,"Full response is no longer cached. Make a new request through the LocalDeck URL. The cache holds up to 64 MiB and resets when the daemon restarts.");return Z.setHeader("cache-control","no-store"),x(Z,200,_)}if(B==="replay"&&N==="POST"){j(G);let L=await n($);if(j(G),!L||typeof L!=="object"||Array.isArray(L)||Object.keys(L).length!==1||typeof L.requestId!=="string")throw new I(400,"Provide only a recorded requestId");let _=V.requests(D,5000).find((H)=>H.id===L.requestId);if(!_)throw new I(404,"Recorded request is no longer available");try{return x(Z,200,await p$(O,_))}catch(H){throw new I(422,H instanceof Error?H.message:"Replay failed")}}if(!B&&N==="GET")return x(Z,200,O);if((B==="logs"||B==="requests")&&N==="DELETE")return j(G),x(Z,200,await V.clearHistory(D,B));if((B==="logs"||B==="requests")&&N==="GET"){let L=V.historyBoundary(D,B);if(L)Z.setHeader("x-localdeck-history-boundary",L)}if(B==="logs"&&N==="GET")return x(Z,200,V.logs(D,V4(Q)));if(B==="requests"&&N==="GET")return x(Z,200,V.requests(D,V4(Q)));if(B==="stop"&&N==="POST")return z4(Z,async()=>{return j(G),K.stop(D)});if(B==="share-password"&&N==="POST")return j(G),Z.setHeader("cache-control","no-store"),x(Z,200,{password:z.password(D)??null});if(B==="share"){if(N==="GET")return x(Z,200,z.get(D)??null);if(N==="POST"){if(j(G),O.serviceType&&O.serviceType!=="http")throw new I(422,"Database endpoints cannot be shared over HTTP");let L=await n($);if(j(G),!L||typeof L!=="object"||Array.isArray(L))throw new I(400,"request body must be a JSON object");let{password:_,public:H}=L;if(_!==void 0&&typeof _!=="string")throw new I(400,"password must be a string");if(H!==void 0&&typeof H!=="boolean")throw new I(400,"public must be a boolean");if(H&&_)throw new I(400,"a public link cannot have a password");let T=H?void 0:_||k7(12).toString("base64url");try{return x(Z,200,await z.start(D,T,{exclusive:U}))}catch(A){if(A instanceof N0)return x(Z,503,{error:A.message});return x(Z,500,{error:"Sharing failed. Check that the service is running and try again."})}}if(N==="DELETE")return j(G),x(Z,200,{ok:await z.stop(D)})}}x(Z,404,{error:"not found"})}function _$($,Z){return $.details(Z)}function s7($,Z,Q){if(!Q){Z.writeHead(200,{"content-type":"text/html; charset=utf-8"}),Z.end("<h1>LocalDeck daemon</h1><p>Dashboard not built. Run <code>bun run build</code> in the repo. API is at <a href=/api/services>/api/services</a>.</p>");return}let X=U0.join(Q,U0.normalize($).replace(/^(\.\.[/\\])+/,""));if(!X.startsWith(Q))X=U0.join(Q,"index.html");if(!Z1.existsSync(X)||Z1.statSync(X).isDirectory())X=U0.join(Q,"index.html");let G=U0.dirname(X)===U0.join(Q,"assets")&&/-[A-Za-z0-9_-]{8,}\.[a-z0-9]+$/i.test(U0.basename(X));Z.writeHead(200,{"content-type":m7[U0.extname(X)]??"application/octet-stream","cache-control":G?"public, max-age=31536000, immutable":"no-cache","x-frame-options":"DENY","content-security-policy":"frame-ancestors 'none'","x-content-type-options":"nosniff"}),Z1.createReadStream(X).pipe(Z)}function t7($,Z){let{registry:Q,store:X}=Z,G,J=!1,V=!1,z=!1,Y=(C)=>$.readyState===Z$.default.OPEN&&$.send(JSON.stringify(C)),K=Z.trackAttachOperation??((C)=>C),N=async()=>{let C=G;if(!C)return;G=void 0;try{await Z.shares.stop(C,"terminal service disconnected")}catch(D){X.log({ts:Date.now(),service:C,stream:"system",line:`LocalDeck: share cleanup failed: ${D instanceof Error?D.message:String(D)}; stop the share before starting this service again`})}finally{await Q.unregister(C)}},U=(C)=>{Y({type:"error",message:C}),$.close()},W=()=>{J=!0,K(N()).catch(()=>{})};$.on("error",W),$.on("message",(C)=>{let D=Promise.resolve().then(async()=>{let O;try{O=r7(C)}catch(B){U(B instanceof Error?B.message:"invalid attach frame");return}try{if(O.type==="register"){if(V){U("registration has already been attempted");return}if(V=!0,Z.isShuttingDown?.()||J){Y({type:"error",message:"daemon is shutting down"}),$.close();return}let B=await Q.register(Z6(O,Z),()=>Y({type:"stop"}));if(G=B.key,Z.isShuttingDown?.()||J){await N(),Y({type:"error",message:"daemon is shutting down"}),$.close();return}z=!0,Y({type:"registered",service:B})}else if(!z||!G)U("register must be the first attach frame");else if(O.type==="log")X.log({ts:Date.now(),service:G,stream:O.stream,line:O.line});else if(O.type==="pid")Q.setPid(G,O.pid);else if(O.type==="readiness")Q.setReadiness(G,O.status,O.message);else if(O.type==="upstream"){let B=Z.verifyAttachedUpstream??((_,H,T)=>Q6(Q,_,H,T)),L=G;try{if(!await B(L,O.port,O.host)){Y({type:"error",message:"reported upstream is not owned by the attached process; report ignored, retrying detection"});return}if(!J&&G===L)Q.setUpstream(L,O.port,O.host)}catch(_){Y({type:"error",message:`upstream report ignored: ${_ instanceof Error?_.message:String(_)}; retrying detection`})}}}catch(B){Y({type:"error",message:B?.message??String(B)}),$.close()}});K(D).catch(()=>{})}),$.on("close",W)}function r7($){let Z=e7($);if(Z.length>p1)throw Error(`attach frame must not exceed ${p1} bytes`);let Q;try{Q=JSON.parse(Z.toString("utf8"))}catch{throw Error("attach frame must be valid JSON")}if(!Q||typeof Q!=="object"||Array.isArray(Q))throw Error("attach frame must be a JSON object");let X=Q;if(typeof X.type!=="string")throw Error("attach frame type must be a string");if(X.type==="register"){if(L$(X.name,"service name",41),L$(X.cwd,"cwd",l7),L$(X.command,"command",p7),H$(X.key,"service key",256),H$(X.projectId,"project ID",64),H$(X.projectName,"project name",256),H$(X.projectSlug,"project slug",256),$6(X.stablePort,"stable"),d1(X.upstreamPort,"upstream"),X.upstreamSource!==void 0&&X.upstreamSource!=="assigned"&&X.upstreamSource!=="manual")throw Error("upstreamSource must be assigned or manual");if(D4(X.pid),X.profiles!==void 0&&(!Array.isArray(X.profiles)||X.profiles.length>64||!X.profiles.every((G)=>typeof G==="string"&&/^[a-z0-9][a-z0-9_-]{0,40}$/.test(G))))throw Error("profiles must be an array of profile names");return X}if(X.type==="log"){if(X.stream!=="stdout"&&X.stream!=="stderr")throw Error("log stream must be stdout or stderr");return L$(X.line,"log line",d7),X}if(X.type==="pid")return D4(X.pid,!0),X;if(X.type==="readiness"){if(!["checking","ready","failed"].includes(X.status))throw Error("invalid readiness status");return H$(X.message,"readiness message",2000),X}if(X.type==="upstream"){if(d1(X.port,"upstream"),X.host!==void 0&&X.host!=="127.0.0.1"&&X.host!=="::1")throw Error("upstream host must be loopback");return X}throw Error("unknown attach frame type")}function e7($){if(Buffer.isBuffer($))return $;if($ instanceof ArrayBuffer)return Buffer.from($);if(Array.isArray($)&&$.every(Buffer.isBuffer))return Buffer.concat($);throw Error("attach frame must be text or binary data")}function L$($,Z,Q){if(typeof $!=="string")throw Error(`${Z} must be a string`);if($.length>Q)throw Error(`${Z} is too long`)}function H$($,Z,Q){if($!==void 0)L$($,Z,Q)}function d1($,Z){if(!Number.isInteger($)||$<1||$>65535)throw Error(`${Z} port must be an integer between 1 and 65535`)}function $6($,Z){if($!==void 0)d1($,Z)}function D4($,Z=!1){if($===void 0&&!Z)return;if(!Number.isInteger($)||$<1||$>2147483647)throw Error("pid must be a positive integer")}function Z6($,Z){let Q=$.name.toLowerCase(),X=typeof $.key==="string"&&$.key.includes(":")?$.key.slice(0,$.key.lastIndexOf(":")):void 0;if($.projectId!==void 0&&X!==void 0&&$.projectId!==X)throw Error("service key and project ID do not match");let G=$.projectId??X??"standalone";if(G==="standalone")return W4($.cwd),{key:u("standalone",Q),projectId:"standalone",projectName:"standalone",projectSlug:"standalone",name:Q,managedBy:"terminal",stablePort:$.stablePort,upstreamPort:$.upstreamPort,upstreamSource:$.upstreamSource??"assigned",cwd:$.cwd,command:$.command,pid:$.pid};let J=Z.projects.details(G,$.profiles);if(!J.available)throw new q("invalid",J.error??"project configuration is invalid");let V=Z.projects.resolve(G,Q,$.profiles);if(V.serviceType&&V.serviceType!=="http"&&($.upstreamPort!==V.upstream||$.stablePort!==void 0))throw Error("database registration must use its configured published upstream port");let z=V.cwd?U0.resolve(J.directory,V.cwd):J.directory;return W4(z),{key:u(J.id,V.name),projectId:J.id,projectName:J.name,projectSlug:J.slug,name:V.name,serviceType:V.serviceType,managedBy:"terminal",stablePort:$.stablePort??V.port,upstreamPort:$.upstreamPort,upstreamSource:$.upstreamSource??(V.upstream===void 0?"assigned":"manual"),cwd:z,command:V.run,pid:$.pid,...J.activeProfiles?.length?{profiles:J.activeProfiles}:{},configFingerprint:P0(V)}}function O4($){return{profiles:$.profiles??[],active:$.activeProfiles??[],clashes:$.profileClashes??[],...$.profileError?{error:$.profileError}:{},...$.legacyProfiles?{legacyProfiles:$.legacyProfiles}:{}}}function W4($){try{if(!Z1.statSync($).isDirectory())throw Error("not a directory")}catch{throw Error(`working directory does not exist or is not a directory: ${$}`)}}async function Q6($,Z,Q,X){let G=$.get(Z)?.pid;if(!G)return!1;let J=new Set(await C$(G));return(await B$([...J])).some((z)=>J.has(z.pid)&&z.port===Q&&(X===void 0||z.host==="*"||z.host===X))}import X6 from"node:http";import G6 from"node:net";var J6=/^[a-z0-9][a-z0-9_-]{0,40}$/i,V6=/^[a-f0-9]{16}$/,Y6=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/,K6=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/,z6="0123456789abcdefghijklmnopqrstuvwxyz-_",T4="x-",n1=63;function i1($,Z){if(!Number.isInteger($)||$<1||$>65535)throw Error(`${Z} port must be an integer between 1 and 65535`)}function N6($){if($.serviceType!==void 0&&!["http","postgres","redis","compose"].includes($.serviceType))throw Error("invalid service type");if($.serviceType&&$.serviceType!=="http"&&$.stablePort!==void 0)throw Error("database endpoints use upstream, not an HTTP proxy port");if(typeof $.name!=="string")throw Error("service name must be a string");if($.key!==void 0&&typeof $.key!=="string")throw Error("service key must be a string");if($.projectId!==void 0&&typeof $.projectId!=="string")throw Error("project ID must be a string");if($.projectName!==void 0&&typeof $.projectName!=="string")throw Error("project name must be a string");if($.projectSlug!==void 0&&typeof $.projectSlug!=="string")throw Error("project slug must be a string");if($.managedBy!==void 0&&$.managedBy!=="terminal"&&$.managedBy!=="daemon")throw Error("managedBy must be terminal or daemon");if(typeof $.cwd!=="string")throw Error("cwd must be a string");if(typeof $.command!=="string")throw Error("command must be a string");if($.upstreamSource!==void 0&&$.upstreamSource!=="assigned"&&$.upstreamSource!=="manual")throw Error("upstreamSource must be assigned or manual");if($.pid!==void 0&&(!Number.isInteger($.pid)||$.pid<1))throw Error("pid must be a positive integer")}function A4($){if($==="standalone")return"standalone";return BigInt(`0x${$}`).toString(36).padStart(13,"0")}function T$($){if(K6.test($)&&!$.startsWith(T4))return $;let Z=1n;for(let Q of $)Z=Z*38n+BigInt(z6.indexOf(Q));return`${T4}${Z.toString(36)}`}function c0($){let Z=T$($.name),Q=A4($.projectId),X=n1-Z.length-Q.length-5,G=$.projectSlug.slice(0,X);return`${Z}--${G}--p${Q}`}function c1($){let Z=`--p${A4($.projectId)}`;return`${$.projectSlug.length<=n1?$.projectSlug:`${$.projectSlug.slice(0,n1-Z.length)}${Z}`}.${T$($.name)}`}class a1{store;apiPort;nicknameForProject;entries=new Map;registrationQueue=Promise.resolve();constructor($,Z,Q=()=>{return}){this.store=$;this.apiPort=Z;this.nicknameForProject=Q}list($){return[...this.entries.values()].filter((Z)=>$===void 0||Z.info.projectId===$).map((Z)=>Z.info)}get($){return this.entries.get($)?.info}setReadiness($,Z,Q){let X=this.get($);if(!X||X.status==="stopped")return;X.readinessStatus=Z,X.readinessMessage=Q,this.store.emitEvent({type:"service",service:X})}resolve($){let Z=this.entries.get($);if(Z)return{kind:"service",key:Z.info.key,service:Z.info};let Q=$.toLowerCase(),X=this.findQualified(Q);if(X)return{kind:"service",key:X.info.key,service:X.info};return this.resolveMatches(Q,!0)}resolveHostname($){let Z=$.toLowerCase(),Q=[...this.entries.values()].find((G)=>G.info.status!=="stopped"&&c0(G.info)===Z);if(Q)return{kind:"service",key:Q.info.key,service:Q.info};let X=[...this.entries.values()].filter((G)=>G.info.status!=="stopped"&&(c1(G.info)===Z||this.nicknameHostname(G.info)===Z));if(X.length===1)return{kind:"service",key:X[0].info.key,service:X[0].info};if(X.length>1)return{kind:"ambiguous",alternatives:X.map((G)=>c0(G.info)).sort()};return this.resolveMatches(Z,!1)}findQualified($){return[...this.entries.values()].find((Z)=>Z.info.status!=="stopped"&&c0(Z.info)===$)}resolveMatches($,Z){let Q=[...this.entries.values()].filter((X)=>X.info.status!=="stopped"&&(T$(X.info.name)===$||Z&&X.info.name===$));if(Q.length===1){let X=Q[0].info;return{kind:"service",key:X.key,service:X}}if(Q.length>1)return{kind:"ambiguous",alternatives:Q.map((G)=>c0(G.info)).sort()};return{kind:"missing"}}target($,Z="local"){let Q=this.entries.get($);if(!Q||Q.info.status==="stopped"||Q.info.serviceType&&Q.info.serviceType!=="http")return;return{service:Q.info.key,upstreamPort:Q.info.upstreamPort,upstreamHost:Q.info.upstreamHost,upstreamReady:Q.info.upstreamReady,via:Z}}takenPorts(){let $=new Set([this.apiPort]);for(let Z of this.entries.values())if(Z.info.status!=="stopped")$.add(Z.info.stablePort);return $}async register($,Z){let Q,X=this.registrationQueue;this.registrationQueue=new Promise((G)=>{Q=G}),await X;try{return await this.registerNow($,Z)}finally{Q()}}async registerNow($,Z){N6($);let Q=$.name.toLowerCase();if(!J6.test(Q))throw Error(`invalid service name "${$.name}" (letters, digits, - and _ only)`);let X=$.key?.slice(0,$.key.lastIndexOf(":")),G=$.projectId??X??"standalone";if(G!=="standalone"&&!V6.test(G))throw Error("project ID must be standalone or 16 lowercase hexadecimal characters");let J=$.key??u(G,Q);if(J!==u(G,Q))throw Error(`service key "${J}" does not match project "${G}" and service "${Q}"`);let V=$.projectName??(G==="standalone"?"standalone":G),z=($.projectSlug??(G==="standalone"?"standalone":G)).toLowerCase();if(!Y6.test(z))throw Error("project slug must contain only lowercase letters, digits, and interior hyphens");let Y=$.managedBy??"terminal";if(i1($.upstreamPort,"upstream"),$.stablePort!==void 0)i1($.stablePort,"stable");let K=this.entries.get(J);if(K&&K.info.status!=="stopped")throw Error(`service "${Q}" is already running (pid ${K.info.pid??"?"})`);if(K?.info.share)throw Error(`previous share cleanup for "${Q}" is incomplete; stop the share before starting this service again`);if(($.upstreamSource??"manual")==="assigned"&&[...this.entries.values()].some((D)=>D.info.status!=="stopped"&&D.info.upstreamSource==="assigned"&&D.info.upstreamPort===$.upstreamPort))throw Error(`assigned upstream port ${$.upstreamPort} is already reserved by another LocalDeck service`);let N=$.stablePort,U=$.serviceType!==void 0&&$.serviceType!=="http";if(U)N=$.upstreamPort;else if(N!==void 0){if(this.takenPorts().has(N))throw Error(`port ${N} is already used by another LocalDeck service`);if(!await Y$(N))throw Error(`port ${N} is already in use by something outside LocalDeck`)}else N=await M5(J,this.takenPorts());this.store.resetStats(J);let W={key:J,projectId:G,projectName:V,projectSlug:z,name:Q,managedBy:Y,...$.serviceType?{serviceType:$.serviceType}:{},stablePort:N,upstreamPort:$.upstreamPort,upstreamHost:"127.0.0.1",upstreamSource:$.upstreamSource??"manual",status:"starting",pid:$.pid,cwd:$.cwd,command:$.command,...$.profiles?.length?{profiles:[...$.profiles]}:{},...$.configFingerprint?{configFingerprint:$.configFingerprint}:{},startedAt:Date.now(),upstreamReady:!1,urls:[`http://localhost:${N}`,`http://${c1({name:Q,projectSlug:z,projectId:G})}.localhost:${this.apiPort}`,`http://${c0({name:Q,projectSlug:z,projectId:G})}.localhost:${this.apiPort}`],stats:this.store.stats(J)},C={info:W,requestStop:Z,upstreamOwnershipVerified:W.upstreamSource!=="assigned"};this.entries.set(J,C);try{if(U)return W.urls=[],this.store.log({ts:Date.now(),service:J,stream:"system",line:`LocalDeck: ${Q} uses published database port ${$.upstreamPort}; HTTP proxy and sharing are unavailable`}),this.startHealthPolling(C),this.store.emitEvent({type:"service",service:W}),W;C.server=X6.createServer((O,B)=>{let L=this.target(J);if(!L){B.writeHead(503).end("LocalDeck: service stopped");return}d0(O,B,L,{responseBodies:this.store.responseBodies,onRequest:(_)=>this.store.request(_)})}),C.sockets=new Set,C.server.on("connection",(O)=>{C.sockets.add(O),O.once("close",()=>C.sockets?.delete(O))}),C.server.on("upgrade",(O,B,L)=>{let _=this.target(J);if(!_)return B.destroy();i0(O,B,L,_,{responseBodies:this.store.responseBodies,onRequest:(H)=>this.store.request(H)})}),await new Promise((O,B)=>{C.server.once("error",B),C.server.listen(N,"127.0.0.1",()=>{C.server.off("error",B),O()})}),C.server.on("error",(O)=>this.store.log({ts:Date.now(),service:J,stream:"system",line:`LocalDeck: proxy listener error: ${O.message}`})),R5(J,N),this.store.log({ts:Date.now(),service:J,stream:"system",line:`LocalDeck: ${Q} on http://localhost:${N} → waiting for the process to open a port (assigned PORT=${$.upstreamPort})`}),this.startHealthPolling(C);let D=new Set(this.refreshUrls(Q));D.add(C);for(let O of D)this.store.emitEvent({type:"service",service:O.info});return W}catch(D){if(C.info.status="stopped",C.healthTimer)clearTimeout(C.healthTimer);for(let O of C.sockets??[])O.destroy();if(C.server?.listening)await new Promise((O)=>C.server.close(()=>O()));if(this.entries.get(J)===C){if(K)this.entries.set(J,K);else this.entries.delete(J);this.refreshUrls(Q)}throw D}}startHealthPolling($){let Z=$.detectedHost?[$.detectedHost]:["127.0.0.1","::1"],Q=($.healthGeneration??0)+1;$.healthGeneration=Q;let X=0,G=()=>{if($.info.status==="stopped"||$.healthGeneration!==Q)return;if(!$.upstreamOwnershipVerified){$.healthTimer=setTimeout(G,400),$.healthTimer.unref();return}let J=$.info.upstreamReady?$.info.upstreamHost:Z[X++%Z.length],V=G6.connect({port:$.info.upstreamPort,host:J}),z=(Y)=>{if(V.destroy(),$.info.status==="stopped"||$.healthGeneration!==Q)return;if(!Y&&!$.info.upstreamReady&&X%Z.length!==0)return void($.healthTimer=setTimeout(G,100));let K=Y!==$.info.upstreamReady;if($.info.upstreamReady=Y,Y)$.info.upstreamHost=J;if(Y&&$.info.status==="starting")$.info.status="running";if(K)this.store.log({ts:Date.now(),service:$.info.key,stream:"system",line:Y?`upstream ready on ${J}:${$.info.upstreamPort}`:`upstream on ${$.info.upstreamHost}:${$.info.upstreamPort} stopped answering`}),this.store.emitEvent({type:"service",service:$.info});$.healthTimer=setTimeout(G,Y?3000:400)};V.once("connect",()=>z(!0)),V.once("error",()=>z(!1))};G()}setUpstream($,Z,Q){let X=this.entries.get($);if(!X||X.info.status==="stopped")return;if(i1(Z,"upstream"),Q!==void 0&&Q!=="127.0.0.1"&&Q!=="::1")throw Error("upstream host must be 127.0.0.1 or ::1");let G=X.info.upstreamPort!==Z||Boolean(Q&&X.info.upstreamHost!==Q);if(X.info.upstreamPort=Z,X.detectedHost=Q,Q)X.info.upstreamHost=Q;if(X.info.upstreamSource="detected",X.upstreamOwnershipVerified=!0,X.info.upstreamReady=!1,X.healthTimer)clearTimeout(X.healthTimer);if(G)this.store.log({ts:Date.now(),service:X.info.key,stream:"system",line:`detected process listening on ${Q??"localhost"}:${Z} — proxying there`});this.startHealthPolling(X),this.store.emitEvent({type:"service",service:X.info})}setPid($,Z){let Q=this.entries.get($);if(!Q)return;if(Q.info.pid!==void 0&&Q.info.pid!==Z){if(Q.info.upstreamReady=!1,Q.info.status="starting",Q.upstreamOwnershipVerified=Q.info.upstreamSource==="manual",Q.healthTimer)clearTimeout(Q.healthTimer);this.startHealthPolling(Q)}Q.info.pid=Z,this.store.emitEvent({type:"service",service:Q.info})}requestStop($){let Z=this.entries.get($);if(!Z||Z.info.status==="stopped"||!Z.requestStop)return!1;return Z.requestStop(),!0}async unregister($){let Z=this.entries.get($);if(!Z||Z.info.status==="stopped")return;if(Z.info.status="stopped",Z.info.stoppedAt=Date.now(),Z.info.upstreamReady=!1,Z.info.pid=void 0,Z.healthTimer)clearTimeout(Z.healthTimer);for(let X of Z.sockets??[])X.destroy();await new Promise((X)=>Z.server?Z.server.close(()=>X()):X()),Z.server=void 0,Z.sockets=void 0,Z.requestStop=void 0,this.store.log({ts:Date.now(),service:Z.info.key,stream:"system",line:`LocalDeck: ${Z.info.name} stopped, released port ${Z.info.stablePort}`});let Q=new Set(this.refreshUrls(Z.info.name));Q.add(Z);for(let X of Q)this.store.emitEvent({type:"service",service:X.info})}setShare($,Z){let Q=this.entries.get($);if(!Q)return;Q.info.share=Z,Q.info.shareStartup=void 0,this.store.emitEvent({type:"service",service:Q.info})}setShareStartup($,Z){let Q=this.entries.get($);if(!Q)return;Q.info.shareStartup=Z,this.store.emitEvent({type:"service",service:Q.info})}async closeAll(){for(let $ of this.entries.keys())await this.unregister($)}refreshProjectUrls($){for(let Z of new Set(this.list($).map((Q)=>Q.name)))for(let Q of this.refreshUrls(Z))this.store.emitEvent({type:"service",service:Q.info})}nicknameHostname($){let Z=this.nicknameForProject($.projectId);return Z?`${Z}.${T$($.name)}`:void 0}refreshUrls($){let Z=[...this.entries.values()].filter((X)=>X.info.name===$&&X.info.status!=="stopped"),Q=[];for(let X of this.entries.values()){if(X.info.name!==$)continue;if(X.info.serviceType&&X.info.serviceType!=="http"){X.info.urls=[];continue}let G=[`http://localhost:${X.info.stablePort}`,`http://${c1(X.info)}.localhost:${this.apiPort}`,`http://${c0(X.info)}.localhost:${this.apiPort}`],J=this.nicknameHostname(X.info);if(J)G.unshift(`http://${J}.localhost:${this.apiPort}`);else if(X.info.status!=="stopped"&&Z.length===1)G.unshift(`http://${T$(X.info.name)}.localhost:${this.apiPort}`);if(X.info.urls.length!==G.length||X.info.urls.some((V,z)=>V!==G[z]))Q.push(X);X.info.urls=G}return Q}}import f from"node:fs";import R4 from"node:fs";import U6 from"node:path";import{randomUUID as D6,createHash as q4}from"node:crypto";function n0($,Z){if($.startsWith("legacy-"))return!1;let[Q,X]=$.split("-").map((V)=>Number.parseInt(V,36)),[G,J]=Z.split("-").map((V)=>Number.parseInt(V,36));return Q>G||Q===G&&X>J}var O6=/\b(error|exception|unhandled|fatal|EADDRINUSE|ECONNREFUSED)\b/i,F4=2000,M4=50;function x4($,Z){if($.ts!==Z.ts)return $.ts-Z.ts;if($.id===Z.id)return 0;return n0($.id,Z.id)?1:n0(Z.id,$.id)?-1:$.id.localeCompare(Z.id)}function P4($,Z){let Q=$.replace(/([?&])([^=&#\s]+)=([^&#\s]*)/g,(X,G,J,V)=>{let Y=[...new URLSearchParams(`${J}=${V}`)][0];if(Y&&/password|passwd|secret|token|api[_-]?key|credential|session|signature|authorization|cookie/i.test(Y[0]))return`${G}${J}=[REDACTED]`;if(Y&&Z.some((K)=>K&&Y[1].includes(K)))return`${G}${J}=[REDACTED]`;return X});return U$(Q,Z.flatMap((X)=>[X,encodeURIComponent(X)]))}function I4($){return $.length<=300?$:`${$.slice(0,230)}… [${q4("sha256").update($).digest("hex")}]`}function W6($){if(!$||typeof $!=="object")return!1;let Z=$;return typeof Z.id==="string"&&Number.isFinite(Z.ts)&&typeof Z.service==="string"&&Z.service.includes(":")&&["lifecycle","clear"].includes(Z.kind)&&["info","error"].includes(Z.severity)&&typeof Z.title==="string"&&Z.title.length<=2000&&(Z.kind!=="lifecycle"||!!Z.transition&&typeof Z.transition.status==="string")}function C6($){if(!$||typeof $!=="object")return!1;let Z=$,Q=Z.before,X=Z.coverage;return typeof Z.id==="string"&&typeof Z.projectId==="string"&&Array.isArray(Z.services)&&Z.services.length>0&&Z.services.length<=100&&Z.services.every((G)=>typeof G==="string"&&G.startsWith(`${Z.projectId}:`))&&typeof Z.label==="string"&&Z.label.length<=100&&Number.isFinite(Z.ts)&&typeof Z.boundary==="string"&&!!Q&&[Q.from,Q.to,Q.requests,Q.requestErrors,Q.errorLines,Q.restarts].every(Number.isFinite)&&(Q.errorRate===null||Number.isFinite(Q.errorRate))&&typeof Q.truncated==="boolean"&&Array.isArray(Q.signatures)&&Q.signatures.length<=100&&Q.signatures.every((G)=>typeof G==="string"&&G.length<=300)&&Array.isArray(Q.routes)&&Q.routes.length<=100&&Q.routes.every((G)=>G&&typeof G.route==="string"&&G.route.length<=300&&[G.count,G.errors,G.avgLatencyMs].every(Number.isFinite))&&!!X&&typeof X.partial==="boolean"&&Array.isArray(X.reasons)&&X.reasons.every((G)=>typeof G==="string")}function S4($,Z,Q,X=[]){let G=new Set,J=new Map,V=0,z=0,Y=0,K=0,N=!1;for(let U of $)if(U.kind==="request"&&U.request){if(V++,U.severity==="error")z++;let W=P4(`${U.request.method} ${U.request.path}`,X),C=I4(W);if(W.length>300)N=!0;if(U.severity==="error")if(G.size<100)G.add(C);else N=!0;if(!J.has(C)&&J.size<100)J.set(C,{route:C,count:0,errors:0,total:0});let D=J.get(C);if(D)D.count++,D.errors+=Number(U.severity==="error"),D.total+=U.request.durationMs;else N=!0}else if(U.kind==="log"&&U.severity==="error"){Y++;let W=P4(U.title,X),C=I4(W);if(W.length>300)N=!0;if(G.size<100)G.add(C);else N=!0}else if(U.kind==="lifecycle"&&U.title==="Service restarted")K++;return{from:Z,to:Q,requests:V,requestErrors:z,errorRate:V?z/V:null,errorLines:Y,restarts:K,signatures:[...G],routes:[...J.values()].map(({total:U,...W})=>({...W,avgLatencyMs:Math.round(U/W.count)})),truncated:N}}class o1{store;data;persistenceFailed=!1;file;constructor($,Z){this.store=$;this.file=U6.join(Z,"activity.json"),this.data={version:1,events:[],markers:[],startedAt:Date.now()};try{if(R4.statSync(this.file).size>16777216)throw Error("Activity history too large");let Q=JSON.parse(R4.readFileSync(this.file,"utf8"));if(Q.version!==1||!Array.isArray(Q.events)||!Array.isArray(Q.markers)||!Number.isFinite(Q.startedAt))throw Error("Invalid activity history");let X=Q.events.filter(W6),G=Q.markers.filter(C6);if(X.length!==Q.events.length||G.length!==Q.markers.length)this.persistenceFailed=!0;this.data={...Q,events:X.slice(-F4),markers:G.slice(-M4)}}catch(Q){if(Q.code!=="ENOENT")this.persistenceFailed=!0}}persist($=!1){try{K0(this.file,this.data)}catch(Z){if(this.persistenceFailed=!0,$)throw Error("Could not save baseline history")}}capture($){let Z;if($.type==="service"){let Q=$.service,X={status:Q.status,readiness:Q.readinessStatus,ready:Q.upstreamReady,startedAt:Q.startedAt},G=[...this.data.events].reverse().find((V)=>V.service===Q.key&&V.kind==="lifecycle");if(G&&JSON.stringify(G.transition)===JSON.stringify(X))return;let J=!!G?.transition?.startedAt&&G.transition.startedAt!==Q.startedAt&&(Q.status==="starting"||Q.status==="running");Z={id:$.eventId,ts:Date.now(),service:Q.key,kind:"lifecycle",severity:Q.readinessStatus==="failed"?"error":"info",title:J?"Service restarted":Q.readinessStatus==="failed"?"Readiness failed":Q.status==="running"&&Q.upstreamReady?"Service ready":`Service ${Q.status}`,transition:X}}else if($.type==="service:removed")Z={id:$.eventId,ts:Date.now(),service:$.name,kind:"lifecycle",severity:"info",title:"Service removed",transition:{status:"removed"}};else if($.type==="history:cleared")Z={id:$.eventId,ts:Date.now(),service:$.service,kind:"clear",severity:"info",title:`${$.kind==="logs"?"Logs":"Requests"} cleared`};if(!Z)return;if(this.data.events.push(Z),this.data.events.length>F4)this.data.droppedBefore=this.data.events.shift().ts;this.persist()}scope($,Z){if(!$||!Z.length||Z.length>100||Z.some((Q)=>!Q.startsWith(`${$}:`)))throw Error("Select 1–100 services belonging to this project")}records($,Z){this.scope($,Z);let Q=new Set(Z),X=this.data.events.filter((G)=>Q.has(G.service));for(let G of Q){for(let J of this.store.logs(G,2000))X.push({id:J.id,ts:J.ts,service:G,kind:"log",severity:J.stream==="stderr"||O6.test(J.line)?"error":"info",title:J.line.slice(0,2000)});for(let J of this.store.requests(G,5000))X.push({id:J.id,ts:J.ts,service:G,kind:"request",severity:J.error||J.status>=400||J.status===0?"error":"info",title:`${J.method} ${J.path}`.slice(0,2000),request:{method:J.method,path:J.path,status:J.status,durationMs:J.durationMs,via:J.via}})}return X.sort(x4)}coverage($,Z,Q){let X=new Set;if(this.persistenceFailed)X.add("Lifecycle history persistence was unavailable.");if(this.data.droppedBefore!==void 0&&(Q===void 0||Q<=this.data.droppedBefore))X.add("Older lifecycle events have expired.");if(Q!==void 0&&Q<this.data.startedAt)X.add("The observation window begins before lifecycle recording started.");for(let G of $)this.store.activityCoverage(G).reasons.forEach((V)=>X.add(V));return{partial:X.size>0,reasons:[...X],...Z[0]?{retainedFrom:Z[0].ts}:{}}}timeline($,Z,Q={}){let X=Q.limit??100;if(!Number.isInteger(X)||X<1||X>200)throw Error("limit must be between 1 and 200");if(Q.filter&&!["all","incidents"].includes(Q.filter))throw Error("Unknown activity filter");if(Q.query&&Q.query.length>200)throw Error("Search must be at most 200 characters");let G=this.records($,Z),J=this.coverage(Z,G),V,z=q4("sha256").update([...new Set(Z)].sort().join(",")).digest("hex");if(Q.cursor)try{if(Q.cursor.length>4096)throw 0;if(V=JSON.parse(Buffer.from(Q.cursor,"base64url").toString()),!V||!Number.isFinite(V.ts)||typeof V.id!=="string"||V.projectId!==$||V.scope!==z)throw 0}catch{throw Error("Invalid activity cursor for this project and service selection")}let Y=Q.query?.toLowerCase(),K=G.filter((W)=>(!V||x4(W,V)<0)&&(!Q.eventId||W.id===Q.eventId)&&(Q.filter!=="incidents"||W.severity==="error"||W.kind==="lifecycle"||W.kind==="clear")&&(!Y||`${W.title} ${W.service}`.toLowerCase().includes(Y))).reverse(),N=K.slice(0,X),U=N.at(-1);return{items:N,coverage:J,...U&&K.length>X?{nextCursor:Buffer.from(JSON.stringify({ts:U.ts,id:U.id,projectId:$,scope:z})).toString("base64url")}:{}}}markers($){return this.data.markers.filter((Z)=>Z.projectId===$).slice().reverse()}mark($,Z,Q={}){let X=Q.now??Date.now(),G=this.records($,Z);if(Q.label!==void 0&&(typeof Q.label!=="string"||Q.label.length>100))throw Error("Baseline label must be at most 100 characters");let J=G.filter((Y)=>Y.ts>=X-300000&&Y.ts<=X),V={id:D6(),projectId:$,services:[...new Set(Z)],label:Q.label?.trim()||"Before my change",ts:X,boundary:this.store.activityBoundary(),before:S4(J,X-300000,X,Q.secrets),coverage:this.coverage(Z,G,X-300000),...Q.git?{git:Q.git}:{}},z=this.data.markers;this.data.markers=[...z,V].slice(-M4);try{this.persist(!0)}catch(Y){throw this.data.markers=z,Y}return V}compare($,Z,Q=Date.now(),X=[]){let G=this.data.markers.find((Y)=>Y.id===Z&&Y.projectId===$);if(!G)throw Error("Baseline not found or expired");let J=this.records($,G.services),V=S4(J.filter((Y)=>n0(Y.id,G.boundary)&&Y.ts<=Q),G.ts,Q,X),z=this.coverage(G.services,J,G.ts);return z.partial||=G.coverage.partial,z.reasons=[...new Set([...G.coverage.reasons,...z.reasons])],{marker:G,before:G.before,after:V,newlyObserved:V.signatures.filter((Y)=>!G.before.signatures.includes(Y)),notObservedAgain:G.before.signatures.filter((Y)=>!V.signatures.includes(Y)),insufficientEvidence:V.requests<5||G.before.requests<5,coverage:z}}}import{randomUUID as B6}from"node:crypto";var _6=67108864,H6=5000;class s1{capacity;entries=new Map;bytes=0;constructor($=_6){this.capacity=$}start($){let Z=B6();while(this.entries.size>=H6)this.remove(this.entries.keys().next().value);return this.entries.set(Z,{service:$,body:new l0(this.capacity),bytes:0,finished:!1,complete:!1}),{id:Z,append:(Q)=>{let X=this.entries.get(Z);if(!X||X.finished)return;if(X.bytes+Q.length>this.capacity){this.remove(Z);return}while(this.bytes+Q.length>this.capacity){let G=this.entries.keys().next().value;if(this.remove(G),G===Z)return}X.body.append(Q),X.bytes+=Q.length,this.bytes+=Q.length},finish:(Q,X)=>{let G=this.entries.get(Z);if(G)G.finished=!0,G.complete=Q,G.encoding=X}}}get($,Z){let Q=this.entries.get($);if(!Q?.finished||Q.service!==Z)return;return Q.body.snapshot(Q.complete,Q.encoding)}clear($){for(let[Z,Q]of this.entries)if(!$||Q.service===$)this.remove(Z)}remove($){let Z=this.entries.get($);if(Z)this.bytes-=Z.bytes,this.entries.delete($)}}import E4 from"node:path";import{createHash as L6}from"node:crypto";import{EventEmitter as T6}from"node:events";import{finished as A6}from"node:stream/promises";import{Writable as w4}from"node:stream";var t1=2000,r1=5000,R6=1000,F6=/\b(error|exception|unhandled|fatal|EADDRINUSE|ECONNREFUSED)\b/i;class $8{cap;maxBytes;buf;sizes;size=0;next=0;bytes=0;constructor($,Z=1/0){this.cap=$;this.maxBytes=Z;this.buf=Array($),this.sizes=Array($).fill(0)}push($,Z=0){if(this.size===this.cap)this.bytes-=this.sizes[this.next];this.buf[this.next]=$,this.sizes[this.next]=Z,this.bytes+=Z,this.next=(this.next+1)%this.cap,this.size=Math.min(this.size+1,this.cap);while(this.bytes>this.maxBytes&&this.size>1){let Q=(this.next-this.size+this.cap)%this.cap;this.bytes-=this.sizes[Q],this.buf[Q]=void 0,this.sizes[Q]=0,this.size--}}last($){let Z=Math.min(Math.max(0,$),this.size),Q=(this.next-this.size+this.cap)%this.cap,X=Math.max(0,this.size-Z),G=[];for(let J=X;J<this.size;J++)G.push(this.buf[(Q+J)%this.cap]);return G}clear(){this.buf.fill(void 0),this.sizes.fill(0),this.size=0,this.next=0,this.bytes=0}}function j4(){return{requests:0,ok:0,clientErrors:0,serverErrors:0,proxyErrors:0,avgLatencyMs:0,logLines:0,errorLines:0}}class Z8 extends T6{responseBodies=new s1;activity;buckets=new Map;logsDir;daemonStartedAt;sequence=0;closePromise;closing=!1;closeAfterMs;streamFactory;maxFileBytes;maxHistoryBytes;constructor($={}){super();if(this.logsDir=$.logsDir??R1,this.daemonStartedAt=$.daemonStartedAt??Date.now(),this.closeAfterMs=$.closeAfterMs??R6,this.streamFactory=$.streamFactory??((Z,Q)=>f.createWriteStream(Z,Q)),this.maxFileBytes=Math.max(1,$.maxFileBytes??5242880),this.maxHistoryBytes=Math.max(1,$.maxHistoryBytes??8388608),$.logsDir===void 0)y$();else f.mkdirSync(this.logsDir,{recursive:!0});this.activity=new o1(this,this.logsDir)}nextId(){return`${this.daemonStartedAt.toString(36)}-${(++this.sequence).toString(36)}`}compatibilityId($,Z,Q,X){return`legacy-${L6("sha256").update(`${$}\x00${Z}\x00${Q}\x00${X}`).digest("hex")}`}historyFile($,Z){let Q=Z==="log"?"log.jsonl":"requests.jsonl";return E4.join(this.logsDir,`${encodeURIComponent($)}.${Q}`)}legacyHistoryFile($,Z){let Q=$.replace(/[^a-z0-9_-]/gi,"_"),X=Z==="log"?"log.jsonl":"requests.jsonl";return E4.join(this.logsDir,`${Q}.${X}`)}loadHistory($,Z,Q,X,G,J=this.maxFileBytes){let V=`${this.historyFile(Q,Z)}.cleared`,z=f.existsSync(V)?f.readFileSync(V,"utf8"):void 0,Y,K;try{Y=f.openSync($,"r"),K=f.fstatSync(Y).size}catch(O){if(O.code==="ENOENT")return 0;throw O}let N=Math.min(K,Math.max(0,J)),U=K-N,W=Buffer.alloc(N);try{if(N)f.readSync(Y,W,0,N,U)}finally{f.closeSync(Y)}let C=W.toString("binary").split(`
|
|
127
|
+
`)}async function o7($,Z,Q,X,G){let{registry:J,store:V,shares:z,projects:Y,supervisor:K}=G,N=$.method??"GET";if(N==="OPTIONS"){Z.writeHead(204).end();return}if(X.length===1&&X[0]==="status"&&N==="GET")return x(Z,200,{ok:!0,pid:process.pid,version:G.version,startedAt:G.startedAt,services:J.list().length});if(X.length===1&&X[0]==="shutdown"&&N==="POST"){let U=new Promise((C)=>{Z.once("finish",C),Z.once("close",C)}),W=G.shutdown(U);x(Z,200,{ok:!0}),W.catch(()=>{});return}if(await k5($,Z,Q,X,G))return;if(X[0]==="projects"){if(X.length===1&&N==="GET")return x(Z,200,Y.list());if(X.length===2&&X[1]==="remember"&&N==="POST"){if(j(G),!C4($,G.controlToken))throw new I(403,"forbidden");let U=await n($);if(j(G),!U||typeof U!=="object"||Array.isArray(U))throw new I(400,"request body must be a JSON object");let W=U.file;if(typeof W!=="string")throw new I(400,"file must be a string");try{return x(Z,200,Y.remember(W))}catch(C){if(C instanceof q)throw C;throw new q("invalid","project could not be remembered")}}if(X.length>=2&&X[1]!=="remember"){let U=X[1];if(X.length===3&&X[2]==="secrets"&&N==="GET"){let W=_$(Y,U);if(!W.available)throw new q("invalid",W.error??"project configuration is invalid");let C=G.listProjectSecrets??A0,D=W.commands.flatMap((L)=>L.secrets??[]),O=new Set(C(U)),B=[...new Set([...D,...O])].sort();return x(Z,200,{secrets:B.map((L)=>({name:L,configured:O.has(L)}))})}if(X.length===4&&X[2]==="secrets"&&(N==="PUT"||N==="DELETE")){j(G);let W=_$(Y,U);if(!W.available)throw new q("invalid",W.error??"project configuration is invalid");let C=X[3];if(N==="PUT"){let D=await n($);if(!D||typeof D!=="object"||Array.isArray(D)||Object.keys(D).length!==1||typeof D.value!=="string")throw new I(400,'request body must contain only a string "value"');(G.setProjectSecret??D$)(U,C,D.value)}else(G.deleteProjectSecret??O$)(U,C);return x(Z,200,{ok:!0})}if(X.length===3&&X[2]==="nickname"&&N==="PATCH"){j(G);let W=await n($);if(j(G),!W||typeof W!=="object"||Array.isArray(W)||Object.keys(W).length!==1||typeof W.nickname!=="string")throw new I(400,'request body must contain only a string "nickname"');let C=Y.saveConfigNickname(U,W.nickname);return J.refreshProjectUrls(U),x(Z,200,{...C,services:J.list(U)})}if(X.length===3&&X[2]==="diagnostics"&&N==="GET"){let W=Y.details(U),C=J.list(U),D=C.flatMap((L)=>V.logs(L.key,100)).sort((L,_)=>L.ts-_.ts),O=(G.listProjectSecrets??A0)(U),B=Object.values((G.resolveProjectSecrets??z0)(U,O));return x(Z,200,{report:b5(W,C,D,G.version,[G.controlToken,...B])})}if(X.length===3&&X[2]==="profiles"&&N==="GET"){let W=_$(Y,U);if(!W.available)throw new q("invalid",W.error??"project configuration is invalid");return x(Z,200,O4(W))}if(X.length===4&&X[2]==="profiles"&&X[3]==="active"&&N==="PUT"){j(G);let W=await n($);if(j(G),!W||typeof W!=="object"||Array.isArray(W)||Object.keys(W).some((D)=>D!=="profiles"))throw new I(400,'request body must be { "profiles": [...] }');let C=Y.setActiveProfiles(U,W.profiles);return V.emitEvent({type:"profiles",projectId:U}),x(Z,200,O4(C))}if(X.length===2&&N==="GET"){let W=Y.details(U);if(!W.available)throw new q("invalid",W.error??"project configuration is invalid");return x(Z,200,{...W,services:J.list(U)})}if(X.length===2&&N==="DELETE"){j(G);let W=new Set(J.list().filter((C)=>C.status!=="stopped").map((C)=>C.key));return Y.forget(U,W),x(Z,200,{ok:!0})}if(X.length===3&&N==="POST"&&(X[2]==="start"||X[2]==="stop")){j(G),await n($),j(G);let W=_$(Y,U);if(X[2]==="start"&&!W.available)throw new q("invalid",W.error??"project configuration is invalid");let C=X[2]==="start"?await K.startAll(U):await K.stopAll(U);return x(Z,200,{ok:C.every((D)=>D.ok),results:C})}if(X.length===5&&X[2]==="services"&&X[4]==="config"&&N==="PATCH"){j(G);let W=await n($);j(G);let C=Y.updateServiceConfig(U,X[3],W);return x(Z,200,{...C,services:J.list(U)})}if(X.length===5&&X[2]==="services"&&X[4]==="dependencies"&&N==="PATCH"){j(G);let W=await n($);if(j(G),!W||typeof W!=="object"||Array.isArray(W))throw new I(400,"request body must be a JSON object");let C=Object.keys(W);if(C.length!==1||C[0]!=="after")throw new I(400,'request body may contain only "after"');let D=W.after;if(!Array.isArray(D)||!D.every((B)=>typeof B==="string"))throw new I(400,"after must be an array of service names");let O=Y.updateDependencies(U,X[3],D);return x(Z,200,{...O,services:J.list(U)})}if(X.length===5&&X[2]==="services"&&N==="POST"&&(X[4]==="start"||X[4]==="stop"||X[4]==="restart"))return z4(Z,async()=>{j(G),await n($),j(G);let W=X[3],C=_$(Y,U),D=u(U,W.toLowerCase());if(X[4]==="stop"){let O=J.get(D);if(!O||O.status==="stopped"){if(!C.available)throw new q("not_found",`Project ${U} has no active service named ${W}`);Y.resolve(U,W)}return K.stop(D)}if(!C.available)throw new q("invalid",C.error??"project configuration is invalid");return Y.resolve(U,W),X[4]==="start"?K.start(U,W):K.restart(U,W)})}}if(X[0]==="services"){if(X.length===1&&N==="GET")return x(Z,200,J.list());let U=X.length===4&&X[2]==="share"&&X[3]==="new"&&N==="POST";if(X.length<2||X.length>3&&!U)return x(Z,404,{error:"not found"});let W=X[1],C=J.resolve(W);if(C.kind==="ambiguous")return x(Z,409,{error:`service name "${W}" is ambiguous`,alternatives:C.alternatives});if(C.kind==="missing")return x(Z,404,{error:`unknown service "${W}"`});let{key:D,service:O}=C,B=X[2];if(B==="response"&&N==="GET"){let L=V.requests(D,5000).find((H)=>H.id===Q.searchParams.get("requestId"));if(!L)throw new I(404,"Recorded request is no longer available");let _=L.responseBodyId?V.responseBodies.get(L.responseBodyId,D):void 0;if(!_)throw new I(404,"Full response is no longer cached. Make a new request through the LocalDeck URL. The cache holds up to 64 MiB and resets when the daemon restarts.");return Z.setHeader("cache-control","no-store"),x(Z,200,_)}if(B==="replay"&&N==="POST"){j(G);let L=await n($);if(j(G),!L||typeof L!=="object"||Array.isArray(L)||Object.keys(L).length!==1||typeof L.requestId!=="string")throw new I(400,"Provide only a recorded requestId");let _=V.requests(D,5000).find((H)=>H.id===L.requestId);if(!_)throw new I(404,"Recorded request is no longer available");try{return x(Z,200,await p$(O,_))}catch(H){throw new I(422,H instanceof Error?H.message:"Replay failed")}}if(!B&&N==="GET")return x(Z,200,O);if((B==="logs"||B==="requests")&&N==="DELETE")return j(G),x(Z,200,await V.clearHistory(D,B));if((B==="logs"||B==="requests")&&N==="GET"){let L=V.historyBoundary(D,B);if(L)Z.setHeader("x-localdeck-history-boundary",L)}if(B==="logs"&&N==="GET")return x(Z,200,V.logs(D,V4(Q)));if(B==="requests"&&N==="GET")return x(Z,200,V.requests(D,V4(Q)));if(B==="stop"&&N==="POST")return z4(Z,async()=>{return j(G),K.stop(D)});if(B==="share-password"&&N==="POST")return j(G),Z.setHeader("cache-control","no-store"),x(Z,200,{password:z.password(D)??null});if(B==="share"){if(N==="GET")return x(Z,200,z.get(D)??null);if(N==="POST"){if(j(G),O.serviceType&&O.serviceType!=="http")throw new I(422,"Database endpoints cannot be shared over HTTP");let L=await n($);if(j(G),!L||typeof L!=="object"||Array.isArray(L))throw new I(400,"request body must be a JSON object");let{password:_,public:H}=L;if(_!==void 0&&typeof _!=="string")throw new I(400,"password must be a string");if(H!==void 0&&typeof H!=="boolean")throw new I(400,"public must be a boolean");if(H&&_)throw new I(400,"a public link cannot have a password");let T=H?void 0:_||k7(12).toString("base64url");try{return x(Z,200,await z.start(D,T,{exclusive:U}))}catch(A){if(A instanceof N0)return x(Z,503,{error:A.message});return x(Z,500,{error:"Sharing failed. Check that the service is running and try again."})}}if(N==="DELETE")return j(G),x(Z,200,{ok:await z.stop(D)})}}x(Z,404,{error:"not found"})}function _$($,Z){return $.details(Z)}function s7($,Z,Q){if(!Q){Z.writeHead(200,{"content-type":"text/html; charset=utf-8"}),Z.end("<h1>LocalDeck daemon</h1><p>Dashboard not built. Run <code>bun run build</code> in the repo. API is at <a href=/api/services>/api/services</a>.</p>");return}let X=U0.join(Q,U0.normalize($).replace(/^(\.\.[/\\])+/,""));if(!X.startsWith(Q))X=U0.join(Q,"index.html");if(!Z1.existsSync(X)||Z1.statSync(X).isDirectory())X=U0.join(Q,"index.html");let G=U0.dirname(X)===U0.join(Q,"assets")&&/-[A-Za-z0-9_-]{8,}\.[a-z0-9]+$/i.test(U0.basename(X));Z.writeHead(200,{"content-type":m7[U0.extname(X)]??"application/octet-stream","cache-control":G?"public, max-age=31536000, immutable":"no-cache","x-frame-options":"DENY","content-security-policy":"frame-ancestors 'none'","x-content-type-options":"nosniff"}),Z1.createReadStream(X).pipe(Z)}function t7($,Z){let{registry:Q,store:X}=Z,G,J=!1,V=!1,z=!1,Y=(C)=>$.readyState===Z$.default.OPEN&&$.send(JSON.stringify(C)),K=Z.trackAttachOperation??((C)=>C),N=async()=>{let C=G;if(!C)return;G=void 0;try{await Z.shares.stop(C,"terminal service disconnected")}catch(D){X.log({ts:Date.now(),service:C,stream:"system",line:`LocalDeck: share cleanup failed: ${D instanceof Error?D.message:String(D)}; stop the share before starting this service again`})}finally{await Q.unregister(C)}},U=(C)=>{Y({type:"error",message:C}),$.close()},W=()=>{J=!0,K(N()).catch(()=>{})};$.on("error",W),$.on("message",(C)=>{let D=Promise.resolve().then(async()=>{let O;try{O=r7(C)}catch(B){U(B instanceof Error?B.message:"invalid attach frame");return}try{if(O.type==="register"){if(V){U("registration has already been attempted");return}if(V=!0,Z.isShuttingDown?.()||J){Y({type:"error",message:"daemon is shutting down"}),$.close();return}let B=await Q.register(Z6(O,Z),()=>Y({type:"stop"}));if(G=B.key,Z.isShuttingDown?.()||J){await N(),Y({type:"error",message:"daemon is shutting down"}),$.close();return}z=!0,Y({type:"registered",service:B})}else if(!z||!G)U("register must be the first attach frame");else if(O.type==="log")X.log({ts:Date.now(),service:G,stream:O.stream,line:O.line});else if(O.type==="pid")Q.setPid(G,O.pid);else if(O.type==="readiness")Q.setReadiness(G,O.status,O.message);else if(O.type==="upstream"){let B=Z.verifyAttachedUpstream??((_,H,T)=>Q6(Q,_,H,T)),L=G;try{if(!await B(L,O.port,O.host)){Y({type:"error",message:"reported upstream is not owned by the attached process; report ignored, retrying detection"});return}if(!J&&G===L)Q.setUpstream(L,O.port,O.host)}catch(_){Y({type:"error",message:`upstream report ignored: ${_ instanceof Error?_.message:String(_)}; retrying detection`})}}}catch(B){Y({type:"error",message:B?.message??String(B)}),$.close()}});K(D).catch(()=>{})}),$.on("close",W)}function r7($){let Z=e7($);if(Z.length>p1)throw Error(`attach frame must not exceed ${p1} bytes`);let Q;try{Q=JSON.parse(Z.toString("utf8"))}catch{throw Error("attach frame must be valid JSON")}if(!Q||typeof Q!=="object"||Array.isArray(Q))throw Error("attach frame must be a JSON object");let X=Q;if(typeof X.type!=="string")throw Error("attach frame type must be a string");if(X.type==="register"){if(L$(X.name,"service name",41),L$(X.cwd,"cwd",l7),L$(X.command,"command",p7),H$(X.key,"service key",256),H$(X.projectId,"project ID",64),H$(X.projectName,"project name",256),H$(X.projectSlug,"project slug",256),$6(X.stablePort,"stable"),d1(X.upstreamPort,"upstream"),X.upstreamSource!==void 0&&X.upstreamSource!=="assigned"&&X.upstreamSource!=="manual")throw Error("upstreamSource must be assigned or manual");if(D4(X.pid),X.profiles!==void 0&&(!Array.isArray(X.profiles)||X.profiles.length>64||!X.profiles.every((G)=>typeof G==="string"&&/^[a-z0-9][a-z0-9_-]{0,40}$/.test(G))))throw Error("profiles must be an array of profile names");return X}if(X.type==="log"){if(X.stream!=="stdout"&&X.stream!=="stderr")throw Error("log stream must be stdout or stderr");return L$(X.line,"log line",d7),X}if(X.type==="pid")return D4(X.pid,!0),X;if(X.type==="readiness"){if(!["checking","ready","failed"].includes(X.status))throw Error("invalid readiness status");return H$(X.message,"readiness message",2000),X}if(X.type==="upstream"){if(d1(X.port,"upstream"),X.host!==void 0&&X.host!=="127.0.0.1"&&X.host!=="::1")throw Error("upstream host must be loopback");return X}throw Error("unknown attach frame type")}function e7($){if(Buffer.isBuffer($))return $;if($ instanceof ArrayBuffer)return Buffer.from($);if(Array.isArray($)&&$.every(Buffer.isBuffer))return Buffer.concat($);throw Error("attach frame must be text or binary data")}function L$($,Z,Q){if(typeof $!=="string")throw Error(`${Z} must be a string`);if($.length>Q)throw Error(`${Z} is too long`)}function H$($,Z,Q){if($!==void 0)L$($,Z,Q)}function d1($,Z){if(!Number.isInteger($)||$<1||$>65535)throw Error(`${Z} port must be an integer between 1 and 65535`)}function $6($,Z){if($!==void 0)d1($,Z)}function D4($,Z=!1){if($===void 0&&!Z)return;if(!Number.isInteger($)||$<1||$>2147483647)throw Error("pid must be a positive integer")}function Z6($,Z){let Q=$.name.toLowerCase(),X=typeof $.key==="string"&&$.key.includes(":")?$.key.slice(0,$.key.lastIndexOf(":")):void 0;if($.projectId!==void 0&&X!==void 0&&$.projectId!==X)throw Error("service key and project ID do not match");let G=$.projectId??X??"standalone";if(G==="standalone")return W4($.cwd),{key:u("standalone",Q),projectId:"standalone",projectName:"standalone",projectSlug:"standalone",name:Q,managedBy:"terminal",stablePort:$.stablePort,upstreamPort:$.upstreamPort,upstreamSource:$.upstreamSource??"assigned",cwd:$.cwd,command:$.command,pid:$.pid};let J=Z.projects.details(G,$.profiles);if(!J.available)throw new q("invalid",J.error??"project configuration is invalid");let V=Z.projects.resolve(G,Q,$.profiles);if(V.serviceType&&V.serviceType!=="http"&&($.upstreamPort!==V.upstream||$.stablePort!==void 0))throw Error("database registration must use its configured published upstream port");let z=V.cwd?U0.resolve(J.directory,V.cwd):J.directory;return W4(z),{key:u(J.id,V.name),projectId:J.id,projectName:J.name,projectSlug:J.slug,name:V.name,serviceType:V.serviceType,managedBy:"terminal",stablePort:$.stablePort??V.port,upstreamPort:$.upstreamPort,upstreamSource:$.upstreamSource??(V.upstream===void 0?"assigned":"manual"),cwd:z,command:V.run,pid:$.pid,...J.activeProfiles?.length?{profiles:J.activeProfiles}:{},configFingerprint:P0(V)}}function O4($){return{profiles:$.profiles??[],active:$.activeProfiles??[],clashes:$.profileClashes??[],...$.profileError?{error:$.profileError}:{},...$.legacyProfiles?{legacyProfiles:$.legacyProfiles}:{}}}function W4($){try{if(!Z1.statSync($).isDirectory())throw Error("not a directory")}catch{throw Error(`working directory does not exist or is not a directory: ${$}`)}}async function Q6($,Z,Q,X){let G=$.get(Z)?.pid;if(!G)return!1;let J=new Set(await C$(G));return(await B$([...J])).some((z)=>J.has(z.pid)&&z.port===Q&&(X===void 0||z.host==="*"||z.host===X))}import X6 from"node:http";import G6 from"node:net";var J6=/^[a-z0-9][a-z0-9_-]{0,40}$/i,V6=/^[a-f0-9]{16}$/,Y6=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/,K6=/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/,z6="0123456789abcdefghijklmnopqrstuvwxyz-_",T4="x-",n1=63;function i1($,Z){if(!Number.isInteger($)||$<1||$>65535)throw Error(`${Z} port must be an integer between 1 and 65535`)}function N6($){if($.serviceType!==void 0&&!["http","postgres","redis","compose"].includes($.serviceType))throw Error("invalid service type");if($.serviceType&&$.serviceType!=="http"&&$.stablePort!==void 0)throw Error("database endpoints use upstream, not an HTTP proxy port");if(typeof $.name!=="string")throw Error("service name must be a string");if($.key!==void 0&&typeof $.key!=="string")throw Error("service key must be a string");if($.projectId!==void 0&&typeof $.projectId!=="string")throw Error("project ID must be a string");if($.projectName!==void 0&&typeof $.projectName!=="string")throw Error("project name must be a string");if($.projectSlug!==void 0&&typeof $.projectSlug!=="string")throw Error("project slug must be a string");if($.managedBy!==void 0&&$.managedBy!=="terminal"&&$.managedBy!=="daemon")throw Error("managedBy must be terminal or daemon");if(typeof $.cwd!=="string")throw Error("cwd must be a string");if(typeof $.command!=="string")throw Error("command must be a string");if($.upstreamSource!==void 0&&$.upstreamSource!=="assigned"&&$.upstreamSource!=="manual")throw Error("upstreamSource must be assigned or manual");if($.pid!==void 0&&(!Number.isInteger($.pid)||$.pid<1))throw Error("pid must be a positive integer")}function A4($){if($==="standalone")return"standalone";return BigInt(`0x${$}`).toString(36).padStart(13,"0")}function T$($){if(K6.test($)&&!$.startsWith(T4))return $;let Z=1n;for(let Q of $)Z=Z*38n+BigInt(z6.indexOf(Q));return`${T4}${Z.toString(36)}`}function c0($){let Z=T$($.name),Q=A4($.projectId),X=n1-Z.length-Q.length-5,G=$.projectSlug.slice(0,X);return`${Z}--${G}--p${Q}`}function c1($){let Z=`--p${A4($.projectId)}`;return`${$.projectSlug.length<=n1?$.projectSlug:`${$.projectSlug.slice(0,n1-Z.length)}${Z}`}.${T$($.name)}`}class a1{store;apiPort;nicknameForProject;entries=new Map;registrationQueue=Promise.resolve();constructor($,Z,Q=()=>{return}){this.store=$;this.apiPort=Z;this.nicknameForProject=Q}list($){return[...this.entries.values()].filter((Z)=>$===void 0||Z.info.projectId===$).map((Z)=>Z.info)}get($){return this.entries.get($)?.info}setReadiness($,Z,Q){let X=this.get($);if(!X||X.status==="stopped")return;X.readinessStatus=Z,X.readinessMessage=Q,this.store.emitEvent({type:"service",service:X})}resolve($){let Z=this.entries.get($);if(Z)return{kind:"service",key:Z.info.key,service:Z.info};let Q=$.toLowerCase(),X=this.findQualified(Q);if(X)return{kind:"service",key:X.info.key,service:X.info};return this.resolveMatches(Q,!0)}resolveHostname($){let Z=$.toLowerCase(),Q=[...this.entries.values()].find((G)=>G.info.status!=="stopped"&&c0(G.info)===Z);if(Q)return{kind:"service",key:Q.info.key,service:Q.info};let X=[...this.entries.values()].filter((G)=>G.info.status!=="stopped"&&(c1(G.info)===Z||this.nicknameHostname(G.info)===Z));if(X.length===1)return{kind:"service",key:X[0].info.key,service:X[0].info};if(X.length>1)return{kind:"ambiguous",alternatives:X.map((G)=>c0(G.info)).sort()};return this.resolveMatches(Z,!1)}findQualified($){return[...this.entries.values()].find((Z)=>Z.info.status!=="stopped"&&c0(Z.info)===$)}resolveMatches($,Z){let Q=[...this.entries.values()].filter((X)=>X.info.status!=="stopped"&&(T$(X.info.name)===$||Z&&X.info.name===$));if(Q.length===1){let X=Q[0].info;return{kind:"service",key:X.key,service:X}}if(Q.length>1)return{kind:"ambiguous",alternatives:Q.map((G)=>c0(G.info)).sort()};return{kind:"missing"}}target($,Z="local"){let Q=this.entries.get($);if(!Q||Q.info.status==="stopped"||Q.info.serviceType&&Q.info.serviceType!=="http")return;return{service:Q.info.key,upstreamPort:Q.info.upstreamPort,upstreamHost:Q.info.upstreamHost,upstreamReady:Q.info.upstreamReady,via:Z}}takenPorts(){let $=new Set([this.apiPort]);for(let Z of this.entries.values())if(Z.info.status!=="stopped")$.add(Z.info.stablePort);return $}async register($,Z){let Q,X=this.registrationQueue;this.registrationQueue=new Promise((G)=>{Q=G}),await X;try{return await this.registerNow($,Z)}finally{Q()}}async registerNow($,Z){N6($);let Q=$.name.toLowerCase();if(!J6.test(Q))throw Error(`invalid service name "${$.name}" (letters, digits, - and _ only)`);let X=$.key?.slice(0,$.key.lastIndexOf(":")),G=$.projectId??X??"standalone";if(G!=="standalone"&&!V6.test(G))throw Error("project ID must be standalone or 16 lowercase hexadecimal characters");let J=$.key??u(G,Q);if(J!==u(G,Q))throw Error(`service key "${J}" does not match project "${G}" and service "${Q}"`);let V=$.projectName??(G==="standalone"?"standalone":G),z=($.projectSlug??(G==="standalone"?"standalone":G)).toLowerCase();if(!Y6.test(z))throw Error("project slug must contain only lowercase letters, digits, and interior hyphens");let Y=$.managedBy??"terminal";if(i1($.upstreamPort,"upstream"),$.stablePort!==void 0)i1($.stablePort,"stable");let K=this.entries.get(J);if(K&&K.info.status!=="stopped")throw Error(`service "${Q}" is already running (pid ${K.info.pid??"?"})`);if(K?.info.share)throw Error(`previous share cleanup for "${Q}" is incomplete; stop the share before starting this service again`);if(($.upstreamSource??"manual")==="assigned"&&[...this.entries.values()].some((D)=>D.info.status!=="stopped"&&D.info.upstreamSource==="assigned"&&D.info.upstreamPort===$.upstreamPort))throw Error(`assigned upstream port ${$.upstreamPort} is already reserved by another LocalDeck service`);let N=$.stablePort,U=$.serviceType!==void 0&&$.serviceType!=="http";if(U)N=$.upstreamPort;else if(N!==void 0){if(this.takenPorts().has(N))throw Error(`port ${N} is already used by another LocalDeck service`);if(!await Y$(N))throw Error(`port ${N} is already in use by something outside LocalDeck`)}else N=await M5(J,this.takenPorts());this.store.resetStats(J);let W={key:J,projectId:G,projectName:V,projectSlug:z,name:Q,managedBy:Y,...$.serviceType?{serviceType:$.serviceType}:{},stablePort:N,upstreamPort:$.upstreamPort,upstreamHost:"127.0.0.1",upstreamSource:$.upstreamSource??"manual",status:"starting",pid:$.pid,cwd:$.cwd,command:$.command,...$.profiles?.length?{profiles:[...$.profiles]}:{},...$.configFingerprint?{configFingerprint:$.configFingerprint}:{},startedAt:Date.now(),upstreamReady:!1,urls:[`http://localhost:${N}`,`http://${c1({name:Q,projectSlug:z,projectId:G})}.localhost:${this.apiPort}`,`http://${c0({name:Q,projectSlug:z,projectId:G})}.localhost:${this.apiPort}`],stats:this.store.stats(J)},C={info:W,requestStop:Z,upstreamOwnershipVerified:W.upstreamSource!=="assigned"};this.entries.set(J,C);try{if(U)return W.urls=[],this.store.log({ts:Date.now(),service:J,stream:"system",line:`LocalDeck: ${Q} uses published database port ${$.upstreamPort}; HTTP proxy and sharing are unavailable`}),this.startHealthPolling(C),this.store.emitEvent({type:"service",service:W}),W;C.server=X6.createServer((O,B)=>{let L=this.target(J);if(!L){B.writeHead(503).end("LocalDeck: service stopped");return}d0(O,B,L,{responseBodies:this.store.responseBodies,onRequest:(_)=>this.store.request(_)})}),C.sockets=new Set,C.server.on("connection",(O)=>{C.sockets.add(O),O.once("close",()=>C.sockets?.delete(O))}),C.server.on("upgrade",(O,B,L)=>{let _=this.target(J);if(!_)return B.destroy();i0(O,B,L,_,{responseBodies:this.store.responseBodies,onRequest:(H)=>this.store.request(H)})}),await new Promise((O,B)=>{C.server.once("error",B),C.server.listen(N,"127.0.0.1",()=>{C.server.off("error",B),O()})}),C.server.on("error",(O)=>this.store.log({ts:Date.now(),service:J,stream:"system",line:`LocalDeck: proxy listener error: ${O.message}`})),R5(J,N),this.store.log({ts:Date.now(),service:J,stream:"system",line:`LocalDeck: ${Q} on http://localhost:${N} → waiting for the process to open a port (assigned PORT=${$.upstreamPort})`}),this.startHealthPolling(C);let D=new Set(this.refreshUrls(Q));D.add(C);for(let O of D)this.store.emitEvent({type:"service",service:O.info});return W}catch(D){if(C.info.status="stopped",C.healthTimer)clearTimeout(C.healthTimer);for(let O of C.sockets??[])O.destroy();if(C.server?.listening)await new Promise((O)=>C.server.close(()=>O()));if(this.entries.get(J)===C){if(K)this.entries.set(J,K);else this.entries.delete(J);this.refreshUrls(Q)}throw D}}startHealthPolling($){let Z=$.detectedHost?[$.detectedHost]:["127.0.0.1","::1"],Q=($.healthGeneration??0)+1;$.healthGeneration=Q;let X=0,G=()=>{if($.info.status==="stopped"||$.healthGeneration!==Q)return;if(!$.upstreamOwnershipVerified){$.healthTimer=setTimeout(G,400),$.healthTimer.unref();return}let J=$.info.upstreamReady?$.info.upstreamHost:Z[X++%Z.length],V=G6.connect({port:$.info.upstreamPort,host:J}),z=(Y)=>{if(V.destroy(),$.info.status==="stopped"||$.healthGeneration!==Q)return;if(!Y&&!$.info.upstreamReady&&X%Z.length!==0)return void($.healthTimer=setTimeout(G,100));let K=Y!==$.info.upstreamReady;if($.info.upstreamReady=Y,Y)$.info.upstreamHost=J;if(Y&&$.info.status==="starting")$.info.status="running";if(K)this.store.log({ts:Date.now(),service:$.info.key,stream:"system",line:Y?`upstream ready on ${J}:${$.info.upstreamPort}`:`upstream on ${$.info.upstreamHost}:${$.info.upstreamPort} stopped answering`}),this.store.emitEvent({type:"service",service:$.info});$.healthTimer=setTimeout(G,Y?3000:400)};V.once("connect",()=>z(!0)),V.once("error",()=>z(!1))};G()}setUpstream($,Z,Q){let X=this.entries.get($);if(!X||X.info.status==="stopped")return;if(i1(Z,"upstream"),Q!==void 0&&Q!=="127.0.0.1"&&Q!=="::1")throw Error("upstream host must be 127.0.0.1 or ::1");let G=X.info.upstreamPort!==Z||Boolean(Q&&X.info.upstreamHost!==Q);if(X.info.upstreamPort=Z,X.detectedHost=Q,Q)X.info.upstreamHost=Q;if(X.info.upstreamSource="detected",X.upstreamOwnershipVerified=!0,X.info.upstreamReady=!1,X.healthTimer)clearTimeout(X.healthTimer);if(G)this.store.log({ts:Date.now(),service:X.info.key,stream:"system",line:`detected process listening on ${Q??"localhost"}:${Z} — proxying there`});this.startHealthPolling(X),this.store.emitEvent({type:"service",service:X.info})}setPid($,Z){let Q=this.entries.get($);if(!Q)return;if(Q.info.pid!==void 0&&Q.info.pid!==Z){if(Q.info.upstreamReady=!1,Q.info.status="starting",Q.upstreamOwnershipVerified=Q.info.upstreamSource==="manual",Q.healthTimer)clearTimeout(Q.healthTimer);this.startHealthPolling(Q)}Q.info.pid=Z,this.store.emitEvent({type:"service",service:Q.info})}requestStop($){let Z=this.entries.get($);if(!Z||Z.info.status==="stopped"||!Z.requestStop)return!1;return Z.requestStop(),!0}async unregister($){let Z=this.entries.get($);if(!Z||Z.info.status==="stopped")return;if(Z.info.status="stopped",Z.info.stoppedAt=Date.now(),Z.info.upstreamReady=!1,Z.info.pid=void 0,Z.healthTimer)clearTimeout(Z.healthTimer);for(let X of Z.sockets??[])X.destroy();await new Promise((X)=>Z.server?Z.server.close(()=>X()):X()),Z.server=void 0,Z.sockets=void 0,Z.requestStop=void 0,this.store.log({ts:Date.now(),service:Z.info.key,stream:"system",line:`LocalDeck: ${Z.info.name} stopped, released port ${Z.info.stablePort}`});let Q=new Set(this.refreshUrls(Z.info.name));Q.add(Z);for(let X of Q)this.store.emitEvent({type:"service",service:X.info})}setShare($,Z){let Q=this.entries.get($);if(!Q)return;Q.info.share=Z,Q.info.shareStartup=void 0,this.store.emitEvent({type:"service",service:Q.info})}setShareStartup($,Z){let Q=this.entries.get($);if(!Q)return;Q.info.shareStartup=Z,this.store.emitEvent({type:"service",service:Q.info})}async closeAll(){for(let $ of this.entries.keys())await this.unregister($)}refreshProjectUrls($){for(let Z of new Set(this.list($).map((Q)=>Q.name)))for(let Q of this.refreshUrls(Z))this.store.emitEvent({type:"service",service:Q.info})}nicknameHostname($){let Z=this.nicknameForProject($.projectId);return Z?`${Z}.${T$($.name)}`:void 0}refreshUrls($){let Z=[...this.entries.values()].filter((X)=>X.info.name===$&&X.info.status!=="stopped"),Q=[];for(let X of this.entries.values()){if(X.info.name!==$)continue;if(X.info.serviceType&&X.info.serviceType!=="http"){X.info.urls=[];continue}let G=[`http://localhost:${X.info.stablePort}`,`http://${c1(X.info)}.localhost:${this.apiPort}`,`http://${c0(X.info)}.localhost:${this.apiPort}`],J=this.nicknameHostname(X.info);if(J)G.unshift(`http://${J}.localhost:${this.apiPort}`);else if(X.info.status!=="stopped"&&Z.length===1)G.unshift(`http://${T$(X.info.name)}.localhost:${this.apiPort}`);if(X.info.urls.length!==G.length||X.info.urls.some((V,z)=>V!==G[z]))Q.push(X);X.info.urls=G}return Q}}import f from"node:fs";import R4 from"node:fs";import U6 from"node:path";import{randomUUID as D6,createHash as q4}from"node:crypto";function n0($,Z){if($.startsWith("legacy-"))return!1;let[Q,X]=$.split("-").map((V)=>Number.parseInt(V,36)),[G,J]=Z.split("-").map((V)=>Number.parseInt(V,36));return Q>G||Q===G&&X>J}var O6=/\b(error|exception|unhandled|fatal|EADDRINUSE|ECONNREFUSED)\b/i,F4=2000,M4=50;function x4($,Z){if($.ts!==Z.ts)return $.ts-Z.ts;if($.id===Z.id)return 0;return n0($.id,Z.id)?1:n0(Z.id,$.id)?-1:$.id.localeCompare(Z.id)}function P4($,Z){let Q=$.replace(/([?&])([^=&#\s]+)=([^&#\s]*)/g,(X,G,J,V)=>{let Y=[...new URLSearchParams(`${J}=${V}`)][0];if(Y&&/password|passwd|secret|token|api[_-]?key|credential|session|signature|authorization|cookie/i.test(Y[0]))return`${G}${J}=[REDACTED]`;if(Y&&Z.some((K)=>K&&Y[1].includes(K)))return`${G}${J}=[REDACTED]`;return X});return U$(Q,Z.flatMap((X)=>[X,encodeURIComponent(X)]))}function I4($){return $.length<=300?$:`${$.slice(0,230)}… [${q4("sha256").update($).digest("hex")}]`}function W6($){if(!$||typeof $!=="object")return!1;let Z=$;return typeof Z.id==="string"&&Number.isFinite(Z.ts)&&typeof Z.service==="string"&&Z.service.includes(":")&&["lifecycle","clear"].includes(Z.kind)&&["info","error"].includes(Z.severity)&&typeof Z.title==="string"&&Z.title.length<=2000&&(Z.kind!=="lifecycle"||!!Z.transition&&typeof Z.transition.status==="string")}function C6($){if(!$||typeof $!=="object")return!1;let Z=$,Q=Z.before,X=Z.coverage;return typeof Z.id==="string"&&typeof Z.projectId==="string"&&Array.isArray(Z.services)&&Z.services.length>0&&Z.services.length<=100&&Z.services.every((G)=>typeof G==="string"&&G.startsWith(`${Z.projectId}:`))&&typeof Z.label==="string"&&Z.label.length<=100&&Number.isFinite(Z.ts)&&typeof Z.boundary==="string"&&!!Q&&[Q.from,Q.to,Q.requests,Q.requestErrors,Q.errorLines,Q.restarts].every(Number.isFinite)&&(Q.errorRate===null||Number.isFinite(Q.errorRate))&&typeof Q.truncated==="boolean"&&Array.isArray(Q.signatures)&&Q.signatures.length<=100&&Q.signatures.every((G)=>typeof G==="string"&&G.length<=300)&&Array.isArray(Q.routes)&&Q.routes.length<=100&&Q.routes.every((G)=>G&&typeof G.route==="string"&&G.route.length<=300&&[G.count,G.errors,G.avgLatencyMs].every(Number.isFinite))&&!!X&&typeof X.partial==="boolean"&&Array.isArray(X.reasons)&&X.reasons.every((G)=>typeof G==="string")}function S4($,Z,Q,X=[]){let G=new Set,J=new Map,V=0,z=0,Y=0,K=0,N=!1;for(let U of $)if(U.kind==="request"&&U.request){if(V++,U.severity==="error")z++;let W=P4(`${U.request.method} ${U.request.path}`,X),C=I4(W);if(W.length>300)N=!0;if(U.severity==="error")if(G.size<100)G.add(C);else N=!0;if(!J.has(C)&&J.size<100)J.set(C,{route:C,count:0,errors:0,total:0});let D=J.get(C);if(D)D.count++,D.errors+=Number(U.severity==="error"),D.total+=U.request.durationMs;else N=!0}else if(U.kind==="log"&&U.severity==="error"){Y++;let W=P4(U.title,X),C=I4(W);if(W.length>300)N=!0;if(G.size<100)G.add(C);else N=!0}else if(U.kind==="lifecycle"&&U.title==="Service restarted")K++;return{from:Z,to:Q,requests:V,requestErrors:z,errorRate:V?z/V:null,errorLines:Y,restarts:K,signatures:[...G],routes:[...J.values()].map(({total:U,...W})=>({...W,avgLatencyMs:Math.round(U/W.count)})),truncated:N}}class o1{store;data;persistenceFailed=!1;file;constructor($,Z){this.store=$;this.file=U6.join(Z,"activity.json"),this.data={version:1,events:[],markers:[],startedAt:Date.now()};try{if(R4.statSync(this.file).size>16777216)throw Error("Activity history too large");let Q=JSON.parse(R4.readFileSync(this.file,"utf8"));if(Q.version!==1||!Array.isArray(Q.events)||!Array.isArray(Q.markers)||!Number.isFinite(Q.startedAt))throw Error("Invalid activity history");let X=Q.events.filter(W6),G=Q.markers.filter(C6);if(X.length!==Q.events.length||G.length!==Q.markers.length)this.persistenceFailed=!0;this.data={...Q,events:X.slice(-F4),markers:G.slice(-M4)}}catch(Q){if(Q.code!=="ENOENT")this.persistenceFailed=!0}}persist($=!1){try{K0(this.file,this.data)}catch(Z){if(this.persistenceFailed=!0,$)throw Error("Could not save baseline history")}}capture($){let Z;if($.type==="service"){let Q=$.service,X={status:Q.status,readiness:Q.readinessStatus,ready:Q.upstreamReady,startedAt:Q.startedAt},G=[...this.data.events].reverse().find((V)=>V.service===Q.key&&V.kind==="lifecycle");if(G&&JSON.stringify(G.transition)===JSON.stringify(X))return;let J=!!G?.transition?.startedAt&&G.transition.startedAt!==Q.startedAt&&(Q.status==="starting"||Q.status==="running");Z={id:$.eventId,ts:Date.now(),service:Q.key,kind:"lifecycle",severity:Q.readinessStatus==="failed"?"error":"info",title:J?"Service restarted":Q.readinessStatus==="failed"?"Readiness failed":Q.status==="running"&&Q.upstreamReady?"Service ready":`Service ${Q.status}`,transition:X}}else if($.type==="service:removed")Z={id:$.eventId,ts:Date.now(),service:$.name,kind:"lifecycle",severity:"info",title:"Service removed",transition:{status:"removed"}};else if($.type==="history:cleared")Z={id:$.eventId,ts:Date.now(),service:$.service,kind:"clear",severity:"info",title:`${$.kind==="logs"?"Logs":"Requests"} cleared`};if(!Z)return;if(this.data.events.push(Z),this.data.events.length>F4)this.data.droppedBefore=this.data.events.shift().ts;this.persist()}scope($,Z){if(!$||!Z.length||Z.length>100||Z.some((Q)=>!Q.startsWith(`${$}:`)))throw Error("Select 1–100 services belonging to this project")}records($,Z){this.scope($,Z);let Q=new Set(Z),X=this.data.events.filter((G)=>Q.has(G.service));for(let G of Q){for(let J of this.store.logs(G,2000))X.push({id:J.id,ts:J.ts,service:G,kind:"log",severity:J.stream==="stderr"||O6.test(J.line)?"error":"info",title:J.line.slice(0,2000)});for(let J of this.store.requests(G,5000))X.push({id:J.id,ts:J.ts,service:G,kind:"request",severity:J.error||J.status>=400||J.status===0?"error":"info",title:`${J.method} ${J.path}`.slice(0,2000),request:{method:J.method,path:J.path,status:J.status,durationMs:J.durationMs,via:J.via}})}return X.sort(x4)}coverage($,Z,Q){let X=new Set;if(this.persistenceFailed)X.add("Lifecycle history persistence was unavailable.");if(this.data.droppedBefore!==void 0&&(Q===void 0||Q<=this.data.droppedBefore))X.add("Older lifecycle events have expired.");if(Q!==void 0&&Q<this.data.startedAt)X.add("The observation window begins before lifecycle recording started.");for(let G of $)this.store.activityCoverage(G).reasons.forEach((V)=>X.add(V));return{partial:X.size>0,reasons:[...X],...Z[0]?{retainedFrom:Z[0].ts}:{}}}timeline($,Z,Q={}){let X=Q.limit??100;if(!Number.isInteger(X)||X<1||X>200)throw Error("limit must be between 1 and 200");if(Q.filter&&!["all","incidents"].includes(Q.filter))throw Error("Unknown activity filter");if(Q.query&&Q.query.length>200)throw Error("Search must be at most 200 characters");let G=this.records($,Z),J=this.coverage(Z,G),V,z=q4("sha256").update([...new Set(Z)].sort().join(",")).digest("hex");if(Q.cursor)try{if(Q.cursor.length>4096)throw 0;if(V=JSON.parse(Buffer.from(Q.cursor,"base64url").toString()),!V||!Number.isFinite(V.ts)||typeof V.id!=="string"||V.projectId!==$||V.scope!==z)throw 0}catch{throw Error("Invalid activity cursor for this project and service selection")}let Y=Q.query?.toLowerCase(),K=G.filter((W)=>(!V||x4(W,V)<0)&&(!Q.eventId||W.id===Q.eventId)&&(Q.filter!=="incidents"||W.severity==="error"||W.kind==="lifecycle"||W.kind==="clear")&&(!Y||`${W.title} ${W.service}`.toLowerCase().includes(Y))).reverse(),N=K.slice(0,X),U=N.at(-1);return{items:N,coverage:J,...U&&K.length>X?{nextCursor:Buffer.from(JSON.stringify({ts:U.ts,id:U.id,projectId:$,scope:z})).toString("base64url")}:{}}}markers($){return this.data.markers.filter((Z)=>Z.projectId===$).slice().reverse()}mark($,Z,Q={}){let X=Q.now??Date.now(),G=this.records($,Z);if(Q.label!==void 0&&(typeof Q.label!=="string"||Q.label.length>100))throw Error("Baseline label must be at most 100 characters");let J=G.filter((Y)=>Y.ts>=X-300000&&Y.ts<=X),V={id:D6(),projectId:$,services:[...new Set(Z)],label:Q.label?.trim()||"Before my change",ts:X,boundary:this.store.activityBoundary(),before:S4(J,X-300000,X,Q.secrets),coverage:this.coverage(Z,G,X-300000),...Q.git?{git:Q.git}:{}},z=this.data.markers;this.data.markers=[...z,V].slice(-M4);try{this.persist(!0)}catch(Y){throw this.data.markers=z,Y}return V}compare($,Z,Q=Date.now(),X=[]){let G=this.data.markers.find((Y)=>Y.id===Z&&Y.projectId===$);if(!G)throw Error("Baseline not found or expired");let J=this.records($,G.services),V=S4(J.filter((Y)=>n0(Y.id,G.boundary)&&Y.ts<=Q),G.ts,Q,X),z=this.coverage(G.services,J,G.ts);return z.partial||=G.coverage.partial,z.reasons=[...new Set([...G.coverage.reasons,...z.reasons])],{marker:G,before:G.before,after:V,newlyObserved:V.signatures.filter((Y)=>!G.before.signatures.includes(Y)),notObservedAgain:G.before.signatures.filter((Y)=>!V.signatures.includes(Y)),insufficientEvidence:V.requests<5||G.before.requests<5,coverage:z}}}import{randomUUID as B6}from"node:crypto";var _6=67108864,H6=5000;class s1{capacity;entries=new Map;bytes=0;constructor($=_6){this.capacity=$}start($){let Z=B6();while(this.entries.size>=H6)this.remove(this.entries.keys().next().value);return this.entries.set(Z,{service:$,body:new l0(this.capacity),bytes:0,finished:!1,complete:!1}),{id:Z,append:(Q)=>{let X=this.entries.get(Z);if(!X||X.finished)return;if(X.bytes+Q.length>this.capacity){this.remove(Z);return}while(this.bytes+Q.length>this.capacity){let G=this.entries.keys().next().value;if(this.remove(G),G===Z)return}X.body.append(Q),X.bytes+=Q.length,this.bytes+=Q.length},finish:(Q,X)=>{let G=this.entries.get(Z);if(G)G.finished=!0,G.complete=Q,G.encoding=X}}}get($,Z){let Q=this.entries.get($);if(!Q?.finished||Q.service!==Z)return;return Q.body.snapshot(Q.complete,Q.encoding)}clear($){for(let[Z,Q]of this.entries)if(!$||Q.service===$)this.remove(Z)}remove($){let Z=this.entries.get($);if(Z)this.bytes-=Z.bytes,this.entries.delete($)}}import E4 from"node:path";import{createHash as L6}from"node:crypto";import{EventEmitter as T6}from"node:events";import{finished as A6}from"node:stream/promises";import{Writable as w4}from"node:stream";var t1=2000,r1=5000,R6=1000,F6=/\b(error|exception|unhandled|fatal|EADDRINUSE|ECONNREFUSED)\b/i;class $8{cap;maxBytes;buf;sizes;size=0;next=0;bytes=0;constructor($,Z=1/0){this.cap=$;this.maxBytes=Z;this.buf=Array($),this.sizes=Array($).fill(0)}push($,Z=0){if(this.size===this.cap)this.bytes-=this.sizes[this.next];this.buf[this.next]=$,this.sizes[this.next]=Z,this.bytes+=Z,this.next=(this.next+1)%this.cap,this.size=Math.min(this.size+1,this.cap);while(this.bytes>this.maxBytes&&this.size>1){let Q=(this.next-this.size+this.cap)%this.cap;this.bytes-=this.sizes[Q],this.buf[Q]=void 0,this.sizes[Q]=0,this.size--}}last($){let Z=Math.min(Math.max(0,$),this.size),Q=(this.next-this.size+this.cap)%this.cap,X=Math.max(0,this.size-Z),G=[];for(let J=X;J<this.size;J++)G.push(this.buf[(Q+J)%this.cap]);return G}clear(){this.buf.fill(void 0),this.sizes.fill(0),this.size=0,this.next=0,this.bytes=0}}function j4(){return{requests:0,ok:0,clientErrors:0,serverErrors:0,proxyErrors:0,avgLatencyMs:0,logLines:0,errorLines:0}}class Z8 extends T6{responseBodies=new s1;activity;buckets=new Map;logsDir;daemonStartedAt;sequence=0;closePromise;closing=!1;closeAfterMs;streamFactory;maxFileBytes;maxHistoryBytes;constructor($={}){super();if(this.logsDir=$.logsDir??R1,this.daemonStartedAt=$.daemonStartedAt??Date.now(),this.closeAfterMs=$.closeAfterMs??R6,this.streamFactory=$.streamFactory??((Z,Q)=>f.createWriteStream(Z,Q)),this.maxFileBytes=Math.max(1,$.maxFileBytes??5242880),this.maxHistoryBytes=Math.max(1,$.maxHistoryBytes??8388608),$.logsDir===void 0)y$();else f.mkdirSync(this.logsDir,{recursive:!0});this.activity=new o1(this,this.logsDir)}nextId(){return`${this.daemonStartedAt.toString(36)}-${(++this.sequence).toString(36)}`}compatibilityId($,Z,Q,X){return`legacy-${L6("sha256").update(`${$}\x00${Z}\x00${Q}\x00${X}`).digest("hex")}`}historyFile($,Z){let Q=Z==="log"?"log.jsonl":"requests.jsonl";return E4.join(this.logsDir,`${encodeURIComponent($)}.${Q}`)}legacyHistoryFile($,Z){let Q=$.replace(/[^a-z0-9_-]/gi,"_"),X=Z==="log"?"log.jsonl":"requests.jsonl";return E4.join(this.logsDir,`${Q}.${X}`)}loadHistory($,Z,Q,X,G,J=this.maxFileBytes){let V=`${this.historyFile(Q,Z)}.cleared`,z=f.existsSync(V)?f.readFileSync(V,"utf8"):void 0,Y,K;try{Y=f.openSync($,"r"),K=f.fstatSync(Y).size}catch(O){if(O.code==="ENOENT")return 0;throw O}let N=Math.min(K,Math.max(0,J)),U=K-N,W=Buffer.alloc(N);try{if(N)f.readSync(Y,W,0,N,U)}finally{f.closeSync(Y)}let C=W.toString("binary").split(`
|
|
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.
|
|
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.8.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});projectAction=($,Z)=>this.call("POST",`/api/projects/${encodeURIComponent($)}/${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};
|
|
@@ -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-hdw8ggnb.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"
|