@codions/portta 0.4.2 → 0.4.3
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/dist/cli.js +229 -229
- package/dist/documentation.json.gz +0 -0
- package/dist/runtime/VERSION +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -95,16 +95,16 @@ _getCommandAndAncestors().forEach(a=>a.emit("afterAllHelp",o))}helpOption(t,n){r
|
|
|
95
95
|
return this._helpOption=t,this._initOptionGroup(t),this}help(t){this.outputHelp(t);let n=Number(ne.exitCode??0);n===0&&t&&typeof t!="function"&&t.error&&(n=1),this._exit(n,"commander.help","(outputHelp)")}addHelpText(t,n){let r=["beforeAll","before","after","afterAll"];if(!r.includes(t))throw new Error(`Unexpected value for position to addHelpText.
|
|
96
96
|
Expecting one of '${r.join("', '")}'`);let o=`${t}Help`;return this.on(o,s=>{let a;typeof n=="function"?a=n({error:s.error,command:s.command}):a=n,a&&s.write(`${a}
|
|
97
97
|
`)}),this}_outputHelpIfRequested(t){let n=this._getHelpOption();n&&t.find(o=>n.is(o))&&(this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)"))}};function bv(e){return e.map(t=>{if(!t.startsWith("--inspect"))return t;let n,r="127.0.0.1",o="9229",s;return(s=t.match(/^(--inspect(-brk)?)$/))!==null?n=s[1]:(s=t.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null?(n=s[1],/^\d+$/.test(s[3])?o=s[3]:r=s[3]):(s=t.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null&&(n=s[1],r=s[3],
|
|
98
|
-
o=s[4]),n&&o!=="0"?`${n}=${r}:${parseInt(o)+1}`:t})}i(bv,"incrementNodeInspectorPort");function Dd(){if(ne.env.NO_COLOR||ne.env.FORCE_COLOR==="0"||ne.env.FORCE_COLOR==="false")return!1;if(ne.env.FORCE_COLOR||ne.env.CLICOLOR_FORCE!==void 0)return!0}i(Dd,"useColor");Nd.Command=Id;Nd.useColor=Dd});var xv=I(pt=>{var{Argument:wv}=Ua(),{Command:Ld}=yv(),{CommanderError:D1,InvalidArgumentError:vv}=Es(),{Help:N1}=Ad(),{Option:Sv}=Cd();pt.program=new Ld;pt.createCommand=e=>new Ld(e);pt.createOption=(e,t)=>new Sv(e,t);pt.createArgument=(e,t)=>new wv(e,t);pt.Command=Ld;pt.Option=Sv;pt.Argument=wv;pt.Help=N1;pt.CommanderError=D1;pt.InvalidArgumentError=vv;pt.InvalidOptionArgumentError=vv});var IA=I((
|
|
99
|
-
return CA($A.statSync(e),e,t)}i(yq,"sync")});var zA=I((
|
|
100
|
-
n&c&&r===s||n&d&&s===0;return f}i(vq,"checkMode")});var BA=I((
|
|
101
|
-
t.ignoreErrors||n.code==="EACCES")return!1;throw n}}i(Sq,"sync")});var VA=I((
|
|
98
|
+
o=s[4]),n&&o!=="0"?`${n}=${r}:${parseInt(o)+1}`:t})}i(bv,"incrementNodeInspectorPort");function Dd(){if(ne.env.NO_COLOR||ne.env.FORCE_COLOR==="0"||ne.env.FORCE_COLOR==="false")return!1;if(ne.env.FORCE_COLOR||ne.env.CLICOLOR_FORCE!==void 0)return!0}i(Dd,"useColor");Nd.Command=Id;Nd.useColor=Dd});var xv=I(pt=>{var{Argument:wv}=Ua(),{Command:Ld}=yv(),{CommanderError:D1,InvalidArgumentError:vv}=Es(),{Help:N1}=Ad(),{Option:Sv}=Cd();pt.program=new Ld;pt.createCommand=e=>new Ld(e);pt.createOption=(e,t)=>new Sv(e,t);pt.createArgument=(e,t)=>new wv(e,t);pt.Command=Ld;pt.Option=Sv;pt.Argument=wv;pt.Help=N1;pt.CommanderError=D1;pt.InvalidArgumentError=vv;pt.InvalidOptionArgumentError=vv});var IA=I((que,jA)=>{jA.exports=RA;RA.sync=yq;var $A=Me("fs");function bq(e,t){var n=t.pathExt!==void 0?t.pathExt:process.env.PATHEXT;if(!n||(n=n.split(";"),n.indexOf("")!==-1))return!0;for(var r=0;r<n.length;r++){var o=n[r].toLowerCase();if(o&&e.substr(-o.length).toLowerCase()===o)return!0}return!1}i(bq,"checkPathExt");function CA(e,t,n){return!e.isSymbolicLink()&&!e.isFile()?!1:bq(t,n)}i(CA,"checkStat");function RA(e,t,n){$A.stat(e,function(r,o){n(r,r?!1:CA(o,e,t))})}i(RA,"isexe");function yq(e,t){
|
|
99
|
+
return CA($A.statSync(e),e,t)}i(yq,"sync")});var zA=I((Zue,MA)=>{MA.exports=NA;NA.sync=wq;var DA=Me("fs");function NA(e,t,n){DA.stat(e,function(r,o){n(r,r?!1:LA(o,t))})}i(NA,"isexe");function wq(e,t){return LA(DA.statSync(e),t)}i(wq,"sync");function LA(e,t){return e.isFile()&&vq(e,t)}i(LA,"checkStat");function vq(e,t){var n=e.mode,r=e.uid,o=e.gid,s=t.uid!==void 0?t.uid:process.getuid&&process.getuid(),a=t.gid!==void 0?t.gid:process.getgid&&process.getgid(),c=parseInt("100",8),u=parseInt("010",8),p=parseInt("001",8),d=c|u,f=n&p||n&u&&o===a||
|
|
100
|
+
n&c&&r===s||n&d&&s===0;return f}i(vq,"checkMode")});var BA=I((Vue,FA)=>{var Wue=Me("fs"),sl;process.platform==="win32"||global.TESTING_WINDOWS?sl=IA():sl=zA();FA.exports=hh;hh.sync=Sq;function hh(e,t,n){if(typeof t=="function"&&(n=t,t={}),!n){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(r,o){hh(e,t||{},function(s,a){s?o(s):r(a)})})}sl(e,t||{},function(r,o){r&&(r.code==="EACCES"||t&&t.ignoreErrors)&&(r=null,o=!1),n(r,o)})}i(hh,"isexe");function Sq(e,t){try{return sl.sync(e,t||{})}catch(n){if(t&&
|
|
101
|
+
t.ignoreErrors||n.code==="EACCES")return!1;throw n}}i(Sq,"sync")});var VA=I((Jue,WA)=>{var _o=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",UA=Me("path"),xq=_o?";":":",qA=BA(),HA=i(e=>Object.assign(new Error(`not found: ${e}`),{code:"ENOENT"}),"getNotFoundError"),ZA=i((e,t)=>{let n=t.colon||xq,r=e.match(/\//)||_o&&e.match(/\\/)?[""]:[..._o?[process.cwd()]:[],...(t.path||process.env.PATH||"").split(n)],o=_o?t.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",s=_o?o.split(n):[""];return _o&&e.indexOf(".")!==-1&&s[0]!==
|
|
102
102
|
""&&s.unshift(""),{pathEnv:r,pathExt:s,pathExtExe:o}},"getPathInfo"),GA=i((e,t,n)=>{typeof t=="function"&&(n=t,t={}),t||(t={});let{pathEnv:r,pathExt:o,pathExtExe:s}=ZA(e,t),a=[],c=i(p=>new Promise((d,f)=>{if(p===r.length)return t.all&&a.length?d(a):f(HA(e));let m=r[p],h=/^".*"$/.test(m)?m.slice(1,-1):m,b=UA.join(h,e),g=!h&&/^\.[\\\/]/.test(e)?e.slice(0,2)+b:b;d(u(g,p,0))}),"step"),u=i((p,d,f)=>new Promise((m,h)=>{if(f===o.length)return m(c(d+1));let b=o[f];qA(p+b,{pathExt:s},(g,y)=>{if(!g&&y)if(t.
|
|
103
103
|
all)a.push(p+b);else return m(p+b);return m(u(p,d,f+1))})}),"subStep");return n?c(0).then(p=>n(null,p),n):c(0)},"which"),kq=i((e,t)=>{t=t||{};let{pathEnv:n,pathExt:r,pathExtExe:o}=ZA(e,t),s=[];for(let a=0;a<n.length;a++){let c=n[a],u=/^".*"$/.test(c)?c.slice(1,-1):c,p=UA.join(u,e),d=!u&&/^\.[\\\/]/.test(e)?e.slice(0,2)+p:p;for(let f=0;f<r.length;f++){let m=d+r[f];try{if(qA.sync(m,{pathExt:o}))if(t.all)s.push(m);else return m}catch{}}}if(t.all&&s.length)return s;if(t.nothrow)return null;throw HA(
|
|
104
|
-
e)},"whichSync");WA.exports=GA;GA.sync=kq});var JA=I((
|
|
105
|
-
eCommand");QA.exports=Eq});var t0=I((
|
|
106
|
-
s,r));let o=[e.command].concat(e.args).join(" ");e.args=["/d","/s","/c",`"${o}"`],e.command=process.env.comspec||"cmd.exe",e.options.windowsVerbatimArguments=!0}return e}i(Mq,"parseNonShell");function zq(e,t,n){t&&!Array.isArray(t)&&(n=t,t=null),t=t?t.slice(0):[],n=Object.assign({},n);let r={command:e,args:t,options:n,file:void 0,original:{command:e,args:t}};return n.shell?r:Mq(r)}i(zq,"parse");u0.exports=zq});var m0=I((
|
|
107
|
-
null}i(d0,"verifyENOENT");function Bq(e,t){return vh&&e===1&&!t.file?Sh(t.original,"spawnSync"):null}i(Bq,"verifyENOENTSync");f0.exports={hookChildProcess:Fq,verifyENOENT:d0,verifyENOENTSync:Bq,notFoundError:Sh}});var b0=I((
|
|
104
|
+
e)},"whichSync");WA.exports=GA;GA.sync=kq});var JA=I((Xue,gh)=>{"use strict";var KA=i((e={})=>{let t=e.env||process.env;return(e.platform||process.platform)!=="win32"?"PATH":Object.keys(t).reverse().find(r=>r.toUpperCase()==="PATH")||"Path"},"pathKey");gh.exports=KA;gh.exports.default=KA});var e0=I((epe,QA)=>{"use strict";var YA=Me("path"),_q=VA(),Pq=JA();function XA(e,t){let n=e.options.env||process.env,r=process.cwd(),o=e.options.cwd!=null,s=o&&process.chdir!==void 0&&!process.chdir.disabled;if(s)try{process.chdir(e.options.cwd)}catch{}let a;try{a=_q.sync(e.command,{path:n[Pq({env:n})],pathExt:t?YA.delimiter:void 0})}catch{}finally{s&&process.chdir(r)}return a&&(a=YA.resolve(o?e.options.cwd:"",a)),a}i(XA,"resolveCommandAttempt");function Eq(e){return XA(e)||XA(e,!0)}i(Eq,"resolv\
|
|
105
|
+
eCommand");QA.exports=Eq});var t0=I((npe,yh)=>{"use strict";var bh=/([()\][%!^"`<>&|;, *?])/g;function Aq(e){return e=e.replace(bh,"^$1"),e}i(Aq,"escapeCommand");function Oq(e,t){return e=`${e}`,e=e.replace(/(?=(\\+?)?)\1"/g,'$1$1\\"'),e=e.replace(/(?=(\\+?)?)\1$/,"$1$1"),e=`"${e}"`,e=e.replace(bh,"^$1"),t&&(e=e.replace(bh,"^$1")),e}i(Oq,"escapeArgument");yh.exports.command=Aq;yh.exports.argument=Oq});var r0=I((ope,n0)=>{"use strict";n0.exports=/^#!(.*)/});var s0=I((spe,o0)=>{"use strict";var Tq=r0();o0.exports=(e="")=>{let t=e.match(Tq);if(!t)return null;let[n,r]=t[0].replace(/#! ?/,"").split(" "),o=n.split("/").pop();return o==="env"?r:r?`${o} ${r}`:o}});var a0=I((ipe,i0)=>{"use strict";var wh=Me("fs"),$q=s0();function Cq(e){let n=Buffer.alloc(150),r;try{r=wh.openSync(e,"r"),wh.readSync(r,n,0,150,0),wh.closeSync(r)}catch{}return $q(n.toString())}i(Cq,"readShebang");i0.exports=Cq});var p0=I((cpe,u0)=>{"use strict";var Rq=Me("path"),c0=e0(),l0=t0(),jq=a0(),Iq=process.platform==="win32",Dq=/\.(?:com|exe)$/i,Nq=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function Lq(e){e.file=c0(e);let t=e.file&&jq(e.file);return t?(e.args.unshift(e.file),e.command=t,c0(e)):e.file}i(Lq,"detectShebang");function Mq(e){if(!Iq)return e;let t=Lq(e),n=!Dq.test(t);if(e.options.forceShell||n){let r=Nq.test(t);e.command=Rq.normalize(e.command),e.command=l0.command(e.command),e.args=e.args.map(s=>l0.argument(
|
|
106
|
+
s,r));let o=[e.command].concat(e.args).join(" ");e.args=["/d","/s","/c",`"${o}"`],e.command=process.env.comspec||"cmd.exe",e.options.windowsVerbatimArguments=!0}return e}i(Mq,"parseNonShell");function zq(e,t,n){t&&!Array.isArray(t)&&(n=t,t=null),t=t?t.slice(0):[],n=Object.assign({},n);let r={command:e,args:t,options:n,file:void 0,original:{command:e,args:t}};return n.shell?r:Mq(r)}i(zq,"parse");u0.exports=zq});var m0=I((upe,f0)=>{"use strict";var vh=process.platform==="win32";function Sh(e,t){return Object.assign(new Error(`${t} ${e.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${t} ${e.command}`,path:e.command,spawnargs:e.args})}i(Sh,"notFoundError");function Fq(e,t){if(!vh)return;let n=e.emit;e.emit=function(r,o){if(r==="exit"){let s=d0(o,t);if(s)return n.call(e,"error",s)}return n.apply(e,arguments)}}i(Fq,"hookChildProcess");function d0(e,t){return vh&&e===1&&!t.file?Sh(t.original,"spawn"):
|
|
107
|
+
null}i(d0,"verifyENOENT");function Bq(e,t){return vh&&e===1&&!t.file?Sh(t.original,"spawnSync"):null}i(Bq,"verifyENOENTSync");f0.exports={hookChildProcess:Fq,verifyENOENT:d0,verifyENOENTSync:Bq,notFoundError:Sh}});var b0=I((dpe,Po)=>{"use strict";var h0=Me("child_process"),xh=p0(),kh=m0();function g0(e,t,n){let r=xh(e,t,n),o=h0.spawn(r.command,r.args,r.options);return kh.hookChildProcess(o,r),o}i(g0,"spawn");function Uq(e,t,n){let r=xh(e,t,n),o=h0.spawnSync(r.command,r.args,r.options);return o.error=o.error||kh.verifyENOENTSync(o.status,r),o}i(Uq,"spawnSync");Po.exports=g0;Po.exports.spawn=g0;Po.exports.sync=Uq;Po.exports._parse=xh;Po.exports._enoent=kh});var te=I(Be=>{"use strict";var Mg=Symbol.for("yaml.alias"),SC=Symbol.for("yaml.document"),ou=Symbol.for("yaml.map"),xC=Symbol.for("yaml.pair"),zg=Symbol.for("yaml.scalar"),su=Symbol.for("yaml.seq"),gn=Symbol.for("yaml.node.type"),iK=i(e=>!!e&&typeof e=="object"&&e[gn]===Mg,"isAlias"),aK=i(e=>!!e&&typeof e=="object"&&e[gn]===SC,"isDocument"),cK=i(e=>!!e&&typeof e=="object"&&e[gn]===ou,"isMap"),lK=i(e=>!!e&&typeof e=="object"&&e[gn]===xC,"isPair"),kC=i(e=>!!e&&typeof e=="object"&&e[gn]===zg,"isSca\
|
|
108
108
|
lar"),uK=i(e=>!!e&&typeof e=="object"&&e[gn]===su,"isSeq");function _C(e){if(e&&typeof e=="object")switch(e[gn]){case ou:case su:return!0}return!1}i(_C,"isCollection");function pK(e){if(e&&typeof e=="object")switch(e[gn]){case Mg:case ou:case zg:case su:return!0}return!1}i(pK,"isNode");var dK=i(e=>(kC(e)||_C(e))&&!!e.anchor,"hasAnchor");Be.ALIAS=Mg;Be.DOC=SC;Be.MAP=ou;Be.NODE_TYPE=gn;Be.PAIR=xC;Be.SCALAR=zg;Be.SEQ=su;Be.hasAnchor=dK;Be.isAlias=iK;Be.isCollection=_C;Be.isDocument=aK;Be.isMap=cK;Be.
|
|
109
109
|
isNode=pK;Be.isPair=lK;Be.isScalar=kC;Be.isSeq=uK});var Ei=I(Fg=>{"use strict";var $e=te(),tt=Symbol("break visit"),PC=Symbol("skip children"),Gt=Symbol("remove node");function iu(e,t){let n=EC(t);$e.isDocument(e)?zo(null,e.contents,n,Object.freeze([e]))===Gt&&(e.contents=null):zo(null,e,n,Object.freeze([]))}i(iu,"visit");iu.BREAK=tt;iu.SKIP=PC;iu.REMOVE=Gt;function zo(e,t,n,r){let o=AC(e,t,n,r);if($e.isNode(o)||$e.isPair(o))return OC(e,r,o),zo(e,o,n,r);if(typeof o!="symbol"){if($e.isCollection(t)){r=Object.freeze(r.concat(t));for(let s=0;s<t.items.
|
|
110
110
|
length;++s){let a=zo(s,t.items[s],n,r);if(typeof a=="number")s=a-1;else{if(a===tt)return tt;a===Gt&&(t.items.splice(s,1),s-=1)}}}else if($e.isPair(t)){r=Object.freeze(r.concat(t));let s=zo("key",t.key,n,r);if(s===tt)return tt;s===Gt&&(t.key=null);let a=zo("value",t.value,n,r);if(a===tt)return tt;a===Gt&&(t.value=null)}}return o}i(zo,"visit_");async function au(e,t){let n=EC(t);$e.isDocument(e)?await Fo(null,e.contents,n,Object.freeze([e]))===Gt&&(e.contents=null):await Fo(null,e,n,Object.freeze(
|
|
@@ -402,7 +402,7 @@ this.type==="newline"&&(yield*this.pop())}}};nI.Parser=hy});var aI=I(ta=>{"use s
|
|
|
402
402
|
Object.assign([],{empty:!0},s.streamInfo())}i(y8,"parseAllDocuments");function iI(e,t={}){let{lineCounter:n,prettyErrors:r}=sI(t),o=new oI.Parser(n?.addNewLine),s=new rI.Composer(t),a=null;for(let c of s.compose(o.parse(e),!0,e.length))if(!a)a=c;else if(a.options.logLevel!=="silent"){a.errors.push(new ea.YAMLParseError(c.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return r&&n&&(a.errors.forEach(ea.prettifyError(e,n)),a.warnings.
|
|
403
403
|
forEach(ea.prettifyError(e,n))),a}i(iI,"parseDocument");function w8(e,t,n){let r;typeof t=="function"?r=t:n===void 0&&t&&typeof t=="object"&&(n=t);let o=iI(e,n);if(!o)return null;if(o.warnings.forEach(s=>h8.warn(o.options.logLevel,s)),o.errors.length>0){if(o.options.logLevel!=="silent")throw o.errors[0];o.errors=[]}return o.toJS(Object.assign({reviver:r},n))}i(w8,"parse");function v8(e,t,n){let r=null;if(typeof t=="function"||Array.isArray(t)?r=t:n===void 0&&t&&(n=t),typeof n=="string"&&(n=n.length),
|
|
404
404
|
typeof n=="number"){let o=Math.round(n);n=o<1?void 0:o>8?{indent:8}:{indent:o}}if(e===void 0){let{keepUndefined:o}=n??t??{};if(!o)return}return g8.isDocument(e)&&!r?e.toString(n):new m8.Document(e,r,n).toString(n)}i(v8,"stringify");ta.parse=w8;ta.parseAllDocuments=y8;ta.parseDocument=iI;ta.stringify=v8});var yy=I(se=>{"use strict";var S8=ny(),x8=Gi(),k8=Nb(),by=Ki(),_8=$i(),Vn=te(),P8=qn(),E8=Pe(),A8=Zn(),O8=Gn(),T8=Yu(),$8=dy(),C8=my(),R8=gy(),tp=aI(),cI=Ei();se.Composer=S8.Composer;se.Document=x8.Document;se.Schema=k8.Schema;se.YAMLError=by.YAMLError;se.YAMLParseError=by.YAMLParseError;se.YAMLWarning=by.YAMLWarning;se.Alias=_8.Alias;se.isAlias=Vn.isAlias;se.isCollection=Vn.isCollection;se.isDocument=Vn.isDocument;se.isMap=Vn.isMap;se.isNode=Vn.isNode;se.isPair=Vn.isPair;se.isScalar=Vn.isScalar;
|
|
405
|
-
se.isSeq=Vn.isSeq;se.Pair=P8.Pair;se.Scalar=E8.Scalar;se.YAMLMap=A8.YAMLMap;se.YAMLSeq=O8.YAMLSeq;se.CST=T8;se.Lexer=$8.Lexer;se.LineCounter=C8.LineCounter;se.Parser=R8.Parser;se.parse=tp.parse;se.parseAllDocuments=tp.parseAllDocuments;se.parseDocument=tp.parseDocument;se.stringify=tp.stringify;se.visit=cI.visit;se.visitAsync=cI.visitAsync});var kv=Fa(xv(),1),{program:
|
|
405
|
+
se.isSeq=Vn.isSeq;se.Pair=P8.Pair;se.Scalar=E8.Scalar;se.YAMLMap=A8.YAMLMap;se.YAMLSeq=O8.YAMLSeq;se.CST=T8;se.Lexer=$8.Lexer;se.LineCounter=C8.LineCounter;se.Parser=R8.Parser;se.parse=tp.parse;se.parseAllDocuments=tp.parseAllDocuments;se.parseDocument=tp.parseDocument;se.stringify=tp.stringify;se.visit=cI.visit;se.visitAsync=cI.visitAsync});var kv=Fa(xv(),1),{program:qte,createCommand:Hte,createArgument:Zte,createOption:Gte,CommanderError:_v,InvalidArgumentError:Wte,InvalidOptionArgumentError:Vte,Command:Pv,Argument:Kte,Option:Jte,Help:Yte}=kv.default;import{randomBytes as oK}from"node:crypto";import{createHash as Q1}from"node:crypto";var As=["search","train","live","preview"],Md={search:!1,train:!1,live:!1,preview:!1},L1={search:["Googlebot","Bingbot","DuckDuckBot","YandexBot","Baiduspider","Applebot","Slurp"],train:["GPTBot","ClaudeBot","anthropic-ai","CCBot","Google-Extended","Bytespider","Meta-ExternalAgent","Amazonbot","cohere-ai","Diffbot"],live:["ChatGPT-User","OAI-SearchBot","Claude-User","Claude-Web","PerplexityBot","Perplexity-User"],preview:["Slackbot","facebookexternalhit","Twitterbot","WhatsApp","LinkedInBot","Di\
|
|
406
406
|
scordbot","TelegramBot"]};function zd(e){if(!e||typeof e!="object"||Array.isArray(e))throw new Error("invalid crawler policy");let t=e,n={...Md};for(let r of Object.keys(t))if(!As.includes(r))throw new Error(`unknown crawler kind: ${r}`);for(let r of As){let o=t[r];if(o!==void 0){if(typeof o!="boolean")throw new Error(`invalid crawler policy: ${r}`);n[r]=o}}return n}i(zd,"parseCrawlerPolicy");function M1(e){return As.every(t=>e[t])}i(M1,"allowsEveryCrawler");function z1(e){return As.every(t=>!e[t])}
|
|
407
407
|
i(z1,"blocksEveryCrawler");function Ev(e){return M1(e)?null:z1(e)?`User-agent: *
|
|
408
408
|
Disallow: /
|
|
@@ -428,7 +428,7 @@ function Nv(e,t){return`portta-alias-${e}-${t}`.replace(/[^a-zA-Z0-9-]/g,"-")}i(
|
|
|
428
428
|
`)}
|
|
429
429
|
`;r.push("http:"," routers:");for(let o of e){let s=Nv(o.project,o.service);r.push(` ${s}:`),r.push(` rule: ${wt(`Host(\`${o.host}\`)`)}`),r.push(` entryPoints: [${o.entryPoint}]`),t&&r.push(` middlewares: [${Os}]`),r.push(` service: ${s}`)}r.push(" services:");for(let o of e){let s=Nv(o.project,o.service);r.push(` ${s}:`," loadBalancer:"," servers:"),r.push(` - url: ${wt(`http://${o.container}:${o.port}`)}`)}return r.push(""),r.join(`
|
|
430
430
|
`)}i(tz,"renderAliases");function Ts(e,t,n,r){let o=i(a=>[t,...r?[r]:[]].some(c=>{let u=Ge(c,a.host);return u!==null&&(u.service!==a.service||u.project!==a.project)}),"conflicts"),s=n?e.filter(o):[];return tz(e.filter(a=>!s.includes(a)),n,s)}i(Ts,"renderAliasesForStore");function Wr(e){if(!e)return[];let t=e.split(`
|
|
431
|
-
`).find(n=>n.startsWith(Zd));if(!t)return[];try{let n=JSON.parse(t.slice(Zd.length));return Array.isArray(n)?n.filter(r=>{let o=r;return typeof o?.host=="string"&&typeof o?.container=="string"}):[]}catch{return[]}}i(Wr,"parseAliases");import{createHash as nz,randomBytes as rz}from"node:crypto";import{closeSync as oz,existsSync as
|
|
431
|
+
`).find(n=>n.startsWith(Zd));if(!t)return[];try{let n=JSON.parse(t.slice(Zd.length));return Array.isArray(n)?n.filter(r=>{let o=r;return typeof o?.host=="string"&&typeof o?.container=="string"}):[]}catch{return[]}}i(Wr,"parseAliases");import{createHash as nz,randomBytes as rz}from"node:crypto";import{closeSync as oz,existsSync as yne,mkdirSync as sz,openSync as iz,readFileSync as wne,renameSync as az,writeSync as cz}from"node:fs";import{dirname as lz,join as uz}from"node:path";var pz="state/panel/applied-env.json";var dz=/(SECRET|TOKEN|AUTHKEY|PASSWORD|PASSWD|CREDENTIAL|PRIVATE_?KEY|API_?KEY|ACCESS_?KEY|_KEY)/i;function fz(e){return dz.test(e)}i(fz,"isSecretKey");function mz(e){return nz("sha256").update(e).digest("hex")}i(mz,"digest");function hz(e,t=new Date){let n={},r={};for(let[o,s]of e)fz(o)?r[o]=mz(s):n[o]=s;return{version:1,appliedAt:t.toISOString(),values:n,secrets:r}}i(hz,"snapshotOf");function Ha(e,t){let n=uz(e,pz);sz(lz(n),{recursive:!0});let r=`${n}.${rz(8).toString("hex")}.tmp`,o=iz(r,"wx",420);try{cz(o,`${JSON.stringify(hz(t),null,2)}
|
|
432
432
|
`)}finally{oz(o)}az(r,n)}i(Ha,"writeApplied");var gz=/^[0-9]+\.[0-9]+\.[0-9]+(?:[-+][0-9A-Za-z.-]+)?$/;function bz(e){let t=e.trim();if(!gz.test(t))throw new Error(`invalid Portta release version '${t||"<empty>"}'`);return t}i(bz,"assertReleaseVersion");function Se(e){let t=bz(e);return{runtime:`codions-labs/portta:${t}`,apply:`codions-labs/portta-apply:${t}`,toolbox:`codions-labs/portta-toolbox:${t}`}}i(Se,"porttaImages");var $s="portta-apply",yz="apply";function Lv(e,t,n){return["create","--name",$s,"--label","portta.managed=true","--label",`portta.component=${yz}`,"--label",`portta.apply.spec=${t}`,"--label","traefik.enable=false","--restart","no","--network","none","--user","0:0","--security-opt","no-new-privileges:true","--workdir",e,"--env",`PORTTA_ROOT=${e}`,"--env","HOME=/tmp","--volume","/var/run/docker.sock:/var/run/docker.sock","--volume",`${e}:${e}`,Se(n).apply,"node",`${e}/bin/portta`,"up"]}i(Lv,"appl\
|
|
433
433
|
yCreateArguments");function Mv(e,t){return`${Se(t).apply}|${e}|${t}`}i(Mv,"applySpec");function zv(e){return(e.PORTTA_WEB_EXPOSE??"local")==="public"?"the panel is exposed publicly: apply on the host instead":(e.PORTTA_PROFILE??"local")==="remote-public"?"the remote-public profile applies on the host only":null}i(zv,"applyRefusal");var Fv=["auth.login","auth.logout","auth.login_failed","user.created","user.deleted","user.role_changed","user.banned","user.unbanned","user.password_set","user.password_changed","user.ownership_transferred","user.two_factor_enabled","user.two_factor_disabled","user.sessions_revoked","project_access.granted","project_access.revoked","token.created","token.revoked","project.created","project.updated","project.tagged","project_file.read","project.deleted","environment.started","environment.stopped",
|
|
434
434
|
"environment.restarted","environment.rebuilt","environment.destroyed","environment.forgotten","service.restarted","container.operated","container.destroyed","access.bridge_opened","access.bridge_closed","protection.created","protection.rotated","protection.opened","protection.removed","share.created","share.revoked","gateway.applied","settings.changed","crawlers.changed","settings.discarded","database.migrated","container.console_opened","container.console_closed"];function We(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}i(We,"slug");function Vr(e,t){return(t?`${We(e)}-${We(t)}`:We(e)).slice(0,52).replace(/-$/,"")||"project"}i(Vr,"composeNamespace");function Za(e){return["main","master","develop","development"].includes(e)?null:We(e)}i(Za,"branchSuffix");var wz=63,vz="--";function Sz(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,16777619)>>>0;return t.toString(36).padStart(6,"0").slice(-6)}i(Sz,"shortHash");function xz(e,t=wz){if(e.length<=t)return e;let n=Sz(e),r=t-n.length-1;return`${e.slice(0,r).replace(/-+$/,"")}-${n}`}i(xz,"fitLabel");function Cs(e){let t=We(e.project),n=We(e.service),r=e.context?We(e.context):"",o=n?`${t}-${n}`:t;return xz(r?`${o}${vz}${r}`:o)}i(Cs,"hostLabel");var Ga=["local","auto","custom"];function Gd(e){return Ga.includes(e)}i(Gd,"isDomainMode");var Wd=["sslip.io","nip.io"];function Vd(e){return Wd.includes(e)}i(Vd,"isAutoDomainProvider");var kz=/^(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}$/;function _z(e){return kz.test(e)}i(_z,"isIpv4");function Wa(e,t="sslip.io"){return _z(e)?`${e.replace(/\./g,"-")}.${t}`:null}i(Wa,"autoDomainFor");function Bv(e){let t=Gd(e.mode)?e.mode:"local",n=e.configured?.trim()||null;if(t==="custom")return n?{mode:t,domain:n,problem:null}:{mode:t,domain:"localhost",problem:"domain mode is custom and no domain is set"};if(t==="auto"){let r=e.provider&&Vd(e.provider)?e.provider:"sslip.io",o=e.publicIp?.trim()||null;if(!o)return{mode:t,domain:"localhost",problem:"domain mode is auto and no public address has been detected"};let s=Wa(o,r);return s?{mode:t,domain:s,problem:null}:{mode:t,domain:"localhost",
|
|
@@ -483,7 +483,7 @@ return null;let{Volumes:r,Containers:o}=n,s=new Map,a=i(c=>{let u=s.get(c)??{com
|
|
|
483
483
|
r?100:c.startsWith(r)?90:c.includes(r)?80:d?60:u.includes(r)?40:20,h=m<80?d?.id??null:null,b=p.indexOf(r),g=m>=40?s.description:p.slice(Math.max(0,b-60),Math.max(0,b-60)+220);return[{order:a,score:m,hit:{slug:s.slug,title:s.title,description:s.description,audience:s.audience,section:s.section,category:s.category,url:`${s.url}${h?`#${h}`:""}`,anchor:h,excerpt:g}}]}).sort((s,a)=>a.score-s.score||s.order-a.order).slice(0,Math.min(50,Math.max(1,n.limit??10))).map(({hit:s})=>s)}i(PS,"searchDocumentat\
|
|
484
484
|
ion");function ES(e,t,n){let r=e.pages.find(c=>c.slug===(e.aliases[t]??t));if(!r||!n)return r;let o=r.headings.findIndex(c=>c.id===n),s=r.headings[o];if(!s)return;let a=r.headings.slice(o+1).find(c=>c.level<=s.level);return{...r,url:`${r.url}#${n}`,markdown:r.markdown.split(`
|
|
485
485
|
`).slice(s.line,a?.line).join(`
|
|
486
|
-
`),headings:r.headings.filter(c=>c.line>=s.line&&(!a||c.line<a.line))}}i(ES,"getDocumentationPage");function AS(e,t="all"){return{identity:e.identity,groups:e.groups.filter(n=>t==="all"||n.audience===t),pages:e.pages.filter(n=>t==="all"||n.audience===t).map(({markdown:n,text:r,headings:o,...s})=>s)}}i(AS,"documentationNavigation");import{randomBytes as eF}from"node:crypto";import{accessSync as
|
|
486
|
+
`),headings:r.headings.filter(c=>c.line>=s.line&&(!a||c.line<a.line))}}i(ES,"getDocumentationPage");function AS(e,t="all"){return{identity:e.identity,groups:e.groups.filter(n=>t==="all"||n.audience===t),pages:e.pages.filter(n=>t==="all"||n.audience===t).map(({markdown:n,text:r,headings:o,...s})=>s)}}i(AS,"documentationNavigation");import{randomBytes as eF}from"node:crypto";import{accessSync as vre,chmodSync as of,constants as Sre,copyFileSync as OS,existsSync as js,mkdirSync as TS,readFileSync as $S,rmdirSync as tF,unlinkSync as nF,writeFileSync as rF}from"node:fs";import{dirname as Qa,join as Is}from"node:path";var oF=/^[A-Za-z_][A-Za-z0-9_]*$/,Pn=/^([ \t]*(?:export[ \t]+)?([A-Za-z_][A-Za-z0-9_]*)[ \t]*=[ \t]*)(.*)$/;function CS(e){let t=e[0]==='"'||e[0]==="'"?e[0]:"";if(t){let r=1;for(;r<e.length;r++){if(e[r]==="\\"&&(e[r+1]===t||t==='"'&&e[r+1]==="\\")){r++;continue}if(e[r]===t)break}if(r===e.length||!/^[ \t]*(?:#.*)?$/.test(e.slice(r+1)))throw new Error("invalid quoted .env value");return{value:t==="'"?e.slice(1,r).replace(/\\'/g,"'"):e.slice(1,r).replace(/\\(["\\$nrt])/g,(s,a)=>({n:`
|
|
487
487
|
`,r:"\r",t:" "})[a]??a).replace(/\$\$/g,"$"),suffix:e.slice(r+1),quote:t}}let n=/^(.*?)([ \t]+#.*|[ \t]*)$/.exec(e);return{value:n[1],suffix:n[2],quote:""}}i(CS,"parts");function me(e){let t=new Map;for(let n of e.split(/\r?\n/)){let r=Pn.exec(n);if(!r)continue;let o=r[2];if(t.has(o))throw new Error(`duplicate .env key: ${o}`);t.set(o,CS(r[3]).value)}return t}i(me,"parseEnv");function sf(e,t=""){return e.includes("\\")||t==='"'?`"${e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\$/g,()=>"$\
|
|
488
488
|
$")}"`:t==="'"||/[$\s#'"\\]/.test(e)?`'${e.replace(/'/g,"\\'")}'`:e}i(sf,"encode");function Xa(e,t,n,r=""){if(!oF.test(t))throw new Error(`refusing to write invalid .env key: ${t}`);if(/[\n\r]/.test(n))throw new Error(`refusing to write a multi-line value for ${t}`);let o=me(e);if(o.get(t)===n&&o.has(t))return e;let s=e.includes(`\r
|
|
489
489
|
`)?`\r
|
|
@@ -518,7 +518,7 @@ oundaries.","docs/product/guides/firewall.md"))}if(t.platform==="darwin")r.push(
|
|
|
518
518
|
ct/concepts/security.md"));else if(e.fail2ban.state==="absent")r.push(on("security.fail2ban","info","Fail2ban","not installed",n?"Rate-limiting repeated SSH authentication failures is recommended on publicly exposed servers.":"This is optional on an isolated local machine.","docs/product/concepts/security.md"));else{let o=e.fail2ban.active===!0&&e.fail2ban.sshdJail===!0;r.push(on("security.fail2ban",o?"pass":n?"warn":"info","Fail2ban",`unit ${e.fail2ban.active?"active":"inactive or unknown"}; ss\
|
|
519
519
|
hd jail ${e.fail2ban.sshdJail?"present":"absent or unknown"}`,"The sshd jail limits repeated authentication attempts without changing the SSH server policy.","docs/product/concepts/security.md"))}return r}i(GS,"securityVerdicts");function eo(e,t,n="http"){return e.flatMap(r=>{if(!zt(r.labels)||ec(r.labels))return[];let o=Object.entries(r.labels),s=r.labels["com.docker.compose.project"]||null,a=r.labels["com.docker.compose.service"]||null,c=nc(r.labels),u=c.hosts[0];if(!c.usesDefaultRule&&!u)return[];let p=u||(s?`${We(s)}-${We(a||r.name)}.${t}`:`${We(r.name)}.${t}`),d=o.find(([f])=>/^traefik\.http\.services\..*\.loadbalancer\.server\.port$/.test(f))?.[1]||"auto";return[{project:s,service:a,container:r.name,hostname:p,url:`${n}\
|
|
520
520
|
://${p}`,port:d,state:r.state}]}).sort((r,o)=>r.hostname.localeCompare(o.hostname))}i(eo,"routesFor");function Ns(e,t,n="http"){let r=eo(e,t,n),o=new Map;for(let s of e){let a=s.labels["com.docker.compose.project"];if(!a)continue;let c=o.get(a)??[];c.push(s),o.set(a,c)}return[...o.entries()].map(([s,a])=>({name:s,state:a.some(c=>c.state==="running")?"running":"stopped",services:a.sort((c,u)=>(c.labels["com.docker.compose.service"]||c.name).localeCompare(u.labels["com.docker.compose.service"]||u.
|
|
521
|
-
name)),urls:r.filter(c=>c.project===s)})).sort((s,a)=>s.name.localeCompare(a.name))}i(Ns,"projectsFor");import{scrypt as xF,randomBytes as kF,randomInt as
|
|
521
|
+
name)),urls:r.filter(c=>c.project===s)})).sort((s,a)=>s.name.localeCompare(a.name))}i(Ns,"projectsFor");import{scrypt as xF,randomBytes as kF,randomInt as Wre,timingSafeEqual as Vre}from"node:crypto";var _F="$portta$scrypt$",WS=65536,VS=8,KS=1,PF=32,EF=96*1024*1024;function AF(e,t,n,r){return new Promise((o,s)=>{xF(e,t,n,r,(a,c)=>{a?s(a):o(c)})})}i(AF,"scryptPassword");async function JS(e){let t=kF(16),n=await AF(e,t,PF,{N:WS,r:VS,p:KS,maxmem:EF});return`${_F}${WS}$${VS}$${KS}$${t.toString("base64url")}$${n.toString("base64url")}`}i(JS,"hashPassword");var Z={};vd(Z,{BIGINT_FORMAT_RANGES:()=>cc,CONSTANT_CATCH:()=>ax,Class:()=>ff,NUMBER_FORMAT_RANGES:()=>Ms,aborted:()=>st,allowsEval:()=>wf,assert:()=>RF,assertEqual:()=>OF,assertIs:()=>$F,assertNever:()=>CF,assertNotEqual:()=>TF,assignProp:()=>Xe,attachSchema:()=>zs,base64ToUint8Array:()=>sx,base64urlToUint8Array:()=>YF,cached:()=>oo,captureStackTrace:()=>ic,cleanEnum:()=>JF,cleanRegex:()=>Ls,clone:()=>ft,cloneDef:()=>DF,codePointLength:()=>Fs,constantCatch:()=>cx,createTransparentProxy:()=>BF,defineLazy:()=>gf,
|
|
522
522
|
defineLazyInternal:()=>Q,derived:()=>tB,esc:()=>bf,escapeRegex:()=>cn,explicitlyAborted:()=>xf,extend:()=>HF,finalizeIssue:()=>_t,floatSafeRemainder:()=>hf,getElementAtPath:()=>NF,getEnumValues:()=>no,getLengthableOrigin:()=>Bs,getParsedType:()=>FF,getSizableOrigin:()=>ox,hexToUint8Array:()=>QF,hide:()=>pc,installLazyProp:()=>sB,isObject:()=>lr,isPlainObject:()=>$n,issue:()=>io,joinValues:()=>sc,jsonStringifyReplacer:()=>ro,members:()=>_f,merge:()=>GF,mergeDefs:()=>an,normalizeParams:()=>B,nullish:()=>mf,
|
|
523
523
|
numKeys:()=>zF,objectClone:()=>jF,omit:()=>qF,optionalKeys:()=>Sf,own:()=>Tn,parsedType:()=>kf,partial:()=>WF,pick:()=>UF,prefixIssues:()=>kt,primitiveTypes:()=>nx,promiseAllObject:()=>LF,propertyKeyTypes:()=>vf,randomString:()=>MF,rawShape:()=>so,required:()=>VF,safeExtend:()=>ZF,shallowClone:()=>tx,sizeCaps:()=>uc,slugify:()=>yf,stringifyPrimitive:()=>ac,toZod:()=>XS,uint8ArrayToBase64:()=>ix,uint8ArrayToBase64url:()=>XF,uint8ArrayToHex:()=>eB,unwrapMessage:()=>to});function OF(e){return e}i(OF,"assertEqual");function TF(e){return e}i(TF,"assertNotEqual");function XS(){return e=>e}i(XS,"toZod");function $F(e){}i($F,"assertIs");function CF(e){throw new Error("Unexpected value in exhaustive check")}i(CF,"assertNever");function RF(e){}i(RF,"assert");function no(e){let t=Object.values(e).filter(r=>typeof r=="number");return Object.entries(e).filter(([r,o])=>t.indexOf(+r)===-1).map(([r,o])=>o)}i(no,"getEnumValues");function sc(e,t="|"){return e.map(n=>ac(n)).join(
|
|
524
524
|
t)}i(sc,"joinValues");function ro(e,t){return typeof t=="bigint"?t.toString():t}i(ro,"jsonStringifyReplacer");var df=class{static{i(this,"Cached")}constructor(t){this._getter=t,this._value=void 0}get value(){let t=this._getter;return t!==void 0&&(this._value=t(),this._getter=void 0),this._value}};function oo(e){return new df(e)}i(oo,"cached");function mf(e){return e==null}i(mf,"nullish");function Ls(e){let t=e.startsWith("^")?1:0,n=e.endsWith("$")?e.length-1:e.length;return e.slice(t,n)}i(Ls,"cl\
|
|
@@ -550,7 +550,7 @@ get(){return this==null?n:Tn(this,t,n.bind(this))},set(r){Tn(this,t,r)}})}i(nB,"
|
|
|
550
550
|
enumerable:r,value:s})}})}i(sB,"installLazyProp");var ax="~constantCatch";function cx(e){let t=i(()=>e,"fn");return t[ax]=!0,t}i(cx,"constantCatch");var lx,Ef=Object.freeze({status:"aborted"}),Pf={value:void 0,enumerable:!1},ux="captureStackTrace"in Error?Error:null;function iB(e){let t=ux;if(t){let n=t.stackTraceLimit;if(typeof n=="number"){try{t.stackTraceLimit=0}catch{return ux=null,new e}try{return new e}finally{t.stackTraceLimit=n}}}return new e}i(iB,"newError");function k(e,t,n,r){let o={};function s(m){this.def=m,this.constr=f,this.traits=new Set}i(s,"Internals"),s.prototype=o;let a=n,c=a&&new WeakSet;function u(m,h){if(m._zod){if(m._zod.
|
|
551
551
|
traits.has(e))return}else{Pf.value=new s(h);try{Object.defineProperty(m,"_zod",Pf)}finally{Pf.value=void 0}}if(m._zod.traits.add(e),t(m,h),c){let g=Object.getPrototypeOf(m),y=m._zod.constr.prototype,w=g;for(;w&&w!==y;)w=Object.getPrototypeOf(w);let P=w??g;c.has(P)||(c.add(P),_f(P,a))}let b=f.prototype;for(let g in b)Object.prototype.hasOwnProperty.call(b,g)&&(g in m||(m[g]=b[g].bind(m)))}i(u,"init");let p=r?.Parent??Object;class d extends p{static{i(this,"Definition")}}Object.defineProperty(d,"n\
|
|
552
552
|
ame",{value:e});function f(m){let h=r?.Parent?iB(d):this;u(h,m);let b=h._zod.deferred;if(b){for(let y of b)y();h._zod.deferred=void 0}let g=globalThis.__zod_globalConfig?.postProcessor;return g&&g(h),h}return i(f,"_"),Object.defineProperty(f,"init",{value:u}),Object.defineProperty(f,Symbol.hasInstance,{value:i(m=>r?.Parent&&m instanceof r.Parent?!0:m?._zod?.traits?.has(e),"value")}),Object.defineProperty(f,"name",{value:e}),f}i(k,"$constructor");var Pt=class extends Error{static{i(this,"$ZodAsyncError")}constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}},ao=class extends Error{static{i(this,"$ZodEncodeError")}constructor(t){super(`Encountered unidirectional transform during encode: ${t}`),this.name="ZodEncodeError"}};(lx=globalThis).__zod_globalConfig??(lx.__zod_globalConfig={});var Je=globalThis.__zod_globalConfig;function Qe(e){return e&&Object.assign(Je,e),Je}i(Qe,"config");function aB(){let e=this._zod;return e.message??(e.message=JSON.stringify(e.def,ro,2)),e.message}i(aB,"_getMessage");function cB(e){this._zod.message=e}i(cB,"_setMessage");var lB={get:aB,set:cB,enumerable:!0,configurable:!0},Of={value:void 0,enumerable:!1},px=new WeakSet([Object.prototype,Error.prototype]),dx=i((e,t)=>{e.name="$ZodError",Of.value=t,Object.defineProperty(e,"issues",Of),Of.value=void 0,Object.defineProperty(e,"message",lB);let n=Object.getPrototypeOf(e);px.has(n)||(px.add(n),Object.
|
|
553
|
-
defineProperty(n,"toString",{configurable:!0,enumerable:!1,get(){let r=i(()=>this.message,"value");return Object.defineProperty(this,"toString",{value:r,configurable:!0,writable:!0}),r},set(r){Object.defineProperty(this,"toString",{value:r,configurable:!0,writable:!0})}}))},"initializer"),fx=k("$ZodError",dx),
|
|
553
|
+
defineProperty(n,"toString",{configurable:!0,enumerable:!1,get(){let r=i(()=>this.message,"value");return Object.defineProperty(this,"toString",{value:r,configurable:!0,writable:!0}),r},set(r){Object.defineProperty(this,"toString",{value:r,configurable:!0,writable:!0})}}))},"initializer"),fx=k("$ZodError",dx),ioe=k("$ZodError",dx,void 0,{Parent:Error});function uB(e,t,n){return Object.prototype.hasOwnProperty.call(e,t)||(t==="__proto__"?Object.defineProperty(e,t,{value:n(),writable:!0,enumerable:!0,
|
|
554
554
|
configurable:!0}):e[t]=n()),e[t]}i(uB,"node");function Tf(e,t=n=>n.message){let n={},r=[];for(let o of e.issues)o.path.length>0?uB(n,o.path[0],()=>[]).push(t(o)):r.push(t(o));return{formErrors:r,fieldErrors:n}}i(Tf,"flattenError");function $f(e,t=n=>n.message){let n={_errors:[]},r=i((o,s=[])=>{for(let a of o.issues)if(a.code==="invalid_union"&&a.errors.length)a.errors.map(c=>r({issues:c},[...s,...a.path]));else if(a.code==="invalid_key")r({issues:a.issues},[...s,...a.path]);else if(a.code==="inv\
|
|
555
555
|
alid_element")r({issues:a.issues},[...s,...a.path]);else{let c=[...s,...a.path];if(c.length===0)n._errors.push(t(a));else{let u=n,p=0;for(;p<c.length;){let d=c[p],f=p===c.length-1;if(d==="_errors"){f&&u._errors.push(t(a)),p++;continue}Object.prototype.hasOwnProperty.call(u,d)||Object.defineProperty(u,d,{value:{_errors:[]},enumerable:!0,writable:!0,configurable:!0});let m=u[d];f&&m._errors.push(t(a)),u=m,p++}}}},"processError");return r(e),n}i($f,"formatError");function dc(e,t){return{callee:t?.callee??e,Err:t?.Err}}i(dc,"finalizeParams");var fc=i(e=>{let t=i((n,r,o,s)=>{let a=o?{...o,async:!1}:{async:!1},c=n._zod.run({value:r,issues:[]},a);if(c instanceof Promise)throw new Pt;if(c.issues.length){let u=new(s?.Err??e)(c.issues.map(p=>_t(p,a,Qe())));throw ic(u,s?.callee??t),u}return c.value},"fn");return t},"_parse");var mc=i(e=>{let t=i(async(n,r,o,s)=>{let a=o?{...o,async:!0}:{async:!0},c=n._zod.run({value:r,issues:[]},a);if(c instanceof Promise&&(c=await c),c.issues.length){let u=new(s?.Err??e)(c.issues.map(p=>_t(p,a,Qe())));throw ic(u,s?.callee??t),u}return c.value},"fn");return t},"_parseAsync");var hc=i(e=>(t,n,r)=>{let o=r?{...r,async:!1}:{async:!1},s=t._zod.run({value:n,issues:[]},o);if(s instanceof Promise)throw new Pt;return s.issues.length?mx(e,s.issues,o):{success:!0,data:s.value}},"_safeParse");function mx(e,t,n){let r;return{success:!1,get error(){return r||(r=new e(t.map(o=>_t(o,n,Qe()))),t=void 0,n=void 0),r},set error(o){r=o,t=void 0,n=void 0}}}i(mx,"failure");var gc=i(e=>async(t,n,r)=>{let o=r?{...r,async:!0}:{async:!0},s=t._zod.run({value:n,issues:[]},o);return s instanceof Promise&&(s=await s),s.issues.length?mx(e,s.issues,o):{success:!0,data:s.value}},"_safeParseAsync");var pB=Symbol.for("zod.compile.invalid"),dB=Symbol.for("zod.compile.fallback"),Cf=i(((e,t,n)=>{let r=e._zod.bag.validator;if(r!==void 0){if(r(t)!==pB)return!0;if(r.definite===!0&&n===void 0)return!1}return fB(e,t,n)}),"validate");function fB(e,t,n){let r=n?{...n,async:!1,abortEarly:!0}:{async:!1,abortEarly:!0},o=e._zod.bag.fallbackRun,s;if(o?(r[dB]=!0,s=o({value:t,issues:[]},r)):s=e._zod.run({value:t,issues:[]},r),s instanceof Promise)throw new Pt;return s.issues.length===0}i(fB,"validateFallbac\
|
|
556
556
|
k");var Rf=i(async(e,t,n)=>{let r=n?{...n,async:!0,abortEarly:!0}:{async:!0,abortEarly:!0},o=e._zod.run({value:t,issues:[]},r);return o instanceof Promise&&(o=await o),o.issues.length===0},"validateAsync"),hx=i(e=>{let t=fc(e),n=i((r,o,s,a)=>{let c=s?{...s,direction:"backward"}:{direction:"backward"};return t(r,o,c,dc(n,a))},"fn");return n},"_encode");var gx=i(e=>{let t=fc(e),n=i((r,o,s,a)=>t(r,o,s,dc(n,a)),"fn");return n},"_decode");var bx=i(e=>{let t=mc(e),n=i(async(r,o,s,a)=>{let c=s?{...s,direction:"backward"}:{direction:"backward"};return await t(r,o,c,dc(n,a))},"fn");return n},"_encodeAsync");var yx=i(e=>{let t=mc(e),n=i(async(r,o,s,a)=>await t(r,o,s,dc(n,a)),"fn");return n},"_decodeAsync");var wx=i(e=>(t,n,r)=>{let o=r?{...r,direction:"backward"}:{direction:"backward"};return hc(e)(t,n,o)},"_safeEncode");var vx=i(e=>(t,n,r)=>hc(e)(t,n,r),"_safeDecode");var Sx=i(e=>async(t,n,r)=>{let o=r?{...r,direction:"backward"}:{direction:"backward"};return gc(e)(t,n,o)},"_safeEncodeAsync");var xx=i(e=>async(t,n,r)=>gc(e)(t,n,r),"_safeDecodeAsync");var kx=/^[cC][0-9a-z]{6,}$/,_x=/^[0-9a-z]+$/,Px=/^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$/,Ex=/^[0-9a-vA-V]{20}$/,Ax=/^[A-Za-z0-9]{27}$/,Ox=/^[a-zA-Z0-9_-]{21}$/;function Tx(e){return new RegExp(`^[a-zA-Z0-9_-]{${e}}$`)}i(Tx,"nanoidOfLength");var $x=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/;var Cx=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,If=i(e=>e?new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,"uuid");var Rx=/^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;var mB="^(?=[\\s\\S]*[\\p{Extended_Pictographic}\\p{Regional_Indicator}\\u20E3])[\\p{Extended_Pictographic}\\p{Emoji_Component}]+$";function jx(){return new RegExp(mB,"u")}i(jx,"emoji");var Ix=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,Dx=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;var Nx=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,Lx=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,
|
|
@@ -773,9 +773,9 @@ t.push(` - hostname: ${jn(n.hostname)}`,` service: ${jn(n.service)}`)}return
|
|
|
773
773
|
s=="string"?o.s:"";if(!s||!a||!c)throw new In("the token is missing the account, tunnel or secret field");if(!Qm.test(a))throw new In("the tunnel id inside the token is not a UUID");return{AccountTag:s,TunnelID:a,TunnelSecret:c}}i(YE,"parseTunnelToken");function XE(e){return`${JSON.stringify(e)}
|
|
774
774
|
`}i(XE,"renderTunnelCredentials");var l2=/(Unauthorized|failed to authenticate|invalid tunnel secret|token is invalid|401)/i,u2=/(Couldn't start tunnel|validation failed|error parsing YAML|unable to parse config)/i,p2=/Registered tunnel connection/i;function QE(e){return!e.tokenConfigured||!e.zoneConfigured?{state:"not-configured",detail:e.tokenConfigured?"no domain has been set":"no tunnel token has been set",hint:"Settings -> Cloudflare Tunnel"}:e.enabled?l2.test(e.logTail)?{state:"auth-error",detail:"Cloudflare rejected the t\
|
|
775
775
|
unnel token",hint:"the tunnel may have been deleted, or the token belongs to another account. Replace the token."}:u2.test(e.logTail)?{state:"config-error",detail:"the connector refused its configuration",hint:"portta tunnel status --logs"}:e.containerState!=="running"?{state:"disconnected",detail:e.containerState?`the connector container is ${e.containerState}`:"the connector container does not exist",hint:"portta up"}:p2.test(e.logTail)?{state:"connected",detail:"holding registered connections\
|
|
776
|
-
to the Cloudflare edge",hint:null}:e.containerHealth==="starting"||!e.logTail?{state:"starting",detail:"the connector is establishing its connections",hint:null}:{state:"disconnected",detail:"the connector is running but has registered no connection",hint:"check outbound network access; the connector dials Cloudflare on 7844/udp and 443/tcp"}:{state:"configured",detail:"set up, and not enabled",hint:"enable it to start the connector"}}i(QE,"tunnelStatusFrom");import{stderr as d2,stdin as eA}from"node:process";import{createInterface as f2}from"node:readline/promises";var Fe={success:0,failure:1,usage:2,precondition:3,refused:4},_e=class extends Error{static{i(this,"CliError")}exitCode;hint;constructor(t,n=Fe.failure,r){super(t),this.name="CliError",this.exitCode=n,this.hint=r}},L=class extends _e{static{i(this,"PreconditionError")}constructor(t,n){super(t,Fe.precondition,n)}},U=class extends _e{static{i(this,"RefusedError")}constructor(t,n){super(t,Fe.refused,n)}},C=class extends _e{static{i(this,"UsageError")}constructor(t,n){super(t,Fe.usage,n)}};async function et(e,t){if(t)return;if(!eA.isTTY)throw new U(`${e}; confirmation is unavailable without a TTY`,"pass --yes to confirm non-interactively");let n=f2({input:eA,output:d2});try{let r=await n.question(`${e} [y/N] `);if(!/^y(es)?$/i.test(r.trim()))throw new U("operation cancelled")}finally{n.close()}}i(et,"confirm");import{existsSync as pr,readFileSync as nA}from"node:fs";import{dirname as h2,join as Et,resolve as vo}from"node:path";var tA={name:"@codions/portta",version:"0.4.
|
|
776
|
+
to the Cloudflare edge",hint:null}:e.containerHealth==="starting"||!e.logTail?{state:"starting",detail:"the connector is establishing its connections",hint:null}:{state:"disconnected",detail:"the connector is running but has registered no connection",hint:"check outbound network access; the connector dials Cloudflare on 7844/udp and 443/tcp"}:{state:"configured",detail:"set up, and not enabled",hint:"enable it to start the connector"}}i(QE,"tunnelStatusFrom");import{stderr as d2,stdin as eA}from"node:process";import{createInterface as f2}from"node:readline/promises";var Fe={success:0,failure:1,usage:2,precondition:3,refused:4},_e=class extends Error{static{i(this,"CliError")}exitCode;hint;constructor(t,n=Fe.failure,r){super(t),this.name="CliError",this.exitCode=n,this.hint=r}},L=class extends _e{static{i(this,"PreconditionError")}constructor(t,n){super(t,Fe.precondition,n)}},U=class extends _e{static{i(this,"RefusedError")}constructor(t,n){super(t,Fe.refused,n)}},C=class extends _e{static{i(this,"UsageError")}constructor(t,n){super(t,Fe.usage,n)}};async function et(e,t){if(t)return;if(!eA.isTTY)throw new U(`${e}; confirmation is unavailable without a TTY`,"pass --yes to confirm non-interactively");let n=f2({input:eA,output:d2});try{let r=await n.question(`${e} [y/N] `);if(!/^y(es)?$/i.test(r.trim()))throw new U("operation cancelled")}finally{n.close()}}i(et,"confirm");import{existsSync as pr,readFileSync as nA}from"node:fs";import{dirname as h2,join as Et,resolve as vo}from"node:path";var tA={name:"@codions/portta",version:"0.4.3",description:"Machine-first CLI for a shared Docker development gateway",keywords:["docker","docker-compose","traefik","development","gateway","devcontainer","reverse-proxy"],license:"MIT",type:"module",bin:{portta:"dist/cli.js"},files:["dist"],publishConfig:{access:"public",registry:"https://registry.npmjs.org/"},scripts:{build:"node --import tsx scripts/build.mjs",typecheck:"tsc -p tsconfig.json --noEmit",test:"vitest run",prepack:"npm run build",prepublishOnly:"\
|
|
777
777
|
npm run typecheck && npm test"},engines:{node:">=24"},repository:{type:"git",url:"git+https://github.com/codions-labs/portta.git",directory:"packages/cli"},homepage:"https://github.com/codions-labs/portta#readme",bugs:"https://github.com/codions-labs/portta/issues",dependencies:{"@clack/prompts":"^1.1.0",commander:"14.0.2",execa:"9.6.1",systeminformation:"^5.33.8",yaml:"^2.8.2",zod:"4.6.7"},devDependencies:{"@types/node":"24.13.3",esbuild:"0.28.2","portta-contracts":"0.1.0","portta-core":"0.1.0",
|
|
778
|
-
typescript:"7.0.2",vitest:"5.0.5",tsx:"4.23.15"}};var ur=tA.version,Gc="2026-11-
|
|
778
|
+
typescript:"7.0.2",vitest:"5.0.5",tsx:"4.23.15"}};var ur=tA.version,Gc="2026-11-03T05:02:26Z";function ai(){return`portta ${ur}${Gc?` (built ${Gc})`:""}`}i(ai,"cliVersionLine");var g2="0.0.0-local";function nh(e){return pr(Et(e,"docker","compose","compose.yaml"))?pr(Et(e,"VERSION"))||pr(Et(e,"packages","cli","package.json")):!1}i(nh,"isGatewayRoot");function rh(e){let t=Et(e,"VERSION");if(pr(t))return nA(t,"utf8").trim();let n=Et(e,"packages","cli","package.json");if(pr(n))return g2;throw new L(`missing generated VERSION in ${e}`,"reinstall the @codions/portta npm package")}i(rh,"versionForRoot");function b2(){let e=process.env.HOME;return[process.env.PORTTA_HOME,e?Et(
|
|
779
779
|
e,"portta"):void 0,"/opt/portta",e?Et(e,".portta"):void 0,"/var/lib/portta"].filter(t=>!!t)}i(b2,"wellKnownRoots");function oh(e=process.cwd()){let t=process.env.PORTTA_ROOT;if(t&&nh(vo(t)))return vo(t);let n=vo(e);for(;;){if(nh(n))return n;let r=h2(n);if(r===n)break;n=r}for(let r of b2())if(nh(vo(r)))return vo(r);return null}i(oh,"findGatewayRoot");function O(e={}){let t=e.root?vo(e.root):oh();if(!t){if(e.required===!1){let c={...process.env,PORTTA_PROFILE:e.profile??process.env.PORTTA_PROFILE},
|
|
780
780
|
u=nr(c);return{root:process.cwd(),env:c,config:u,composeFiles:[],version:ur}}throw new L("no Portta installation found","run `portta setup`, set PORTTA_HOME, or run this inside the gateway directory")}let n=pr(Et(t,".env"))?me(nA(Et(t,".env"),"utf8")):new Map,r=Xr(n,process.env);for(let[c,u]of Object.entries(e.overrides??{}))r[c]=u;e.profile&&(r.PORTTA_PROFILE=e.profile),r.PORTTA_ROOT=t,Zv(r);let o=nr(r);r.PORTTA_DOMAIN=o.domain,r.PORTTA_BIND_ADDRESS=o.bindAddress;let s=qv(o);for(let c of s)if(!pr(
|
|
781
781
|
Et(t,c)))throw new L(`missing compose file: ${c}`);let a=rh(t);return r.PORTTA_VERSION=a,{root:t,env:r,config:o,composeFiles:s,version:a}}i(O,"gatewayContext");function we(e){return["--project-directory",e.root,...e.composeFiles.flatMap(t=>["-f",Et(e.root,t)])]}i(we,"composeArguments");import{spawn as q4}from"node:child_process";import{closeSync as H4,openSync as Z4}from"node:fs";function xe(e){if(typeof e!="object"||e===null)return!1;let t=Object.getPrototypeOf(e);return(t===null||t===Object.prototype||Object.getPrototypeOf(t)===null)&&!(Symbol.toStringTag in e)&&!(Symbol.iterator in e)}i(xe,"isPlainObject");import{fileURLToPath as y2}from"node:url";var So=i((e,t)=>{let n=ih(w2(e));if(typeof n!="string")throw new TypeError(`${t} must be a string or a file URL: ${n}.`);return n},"safeNormalizeFileUrl"),w2=i(e=>sh(e)?e.toString():e,"normalizeDenoExecPath"),sh=i(e=>typeof e!="string"&&e&&Object.getPrototypeOf(e)===String.prototype,"isDenoExecPath"),ih=i(e=>e instanceof URL?y2(e):e,"normalizeFileUrl");var Wc=i((e,t=[],n={})=>{let r=So(e,"First argument"),[o,s]=xe(t)?[[],t]:[t,n];if(!Array.isArray(o))throw new TypeError(`Second argument must be either an array of arguments or an options object: ${o}`);if(o.some(u=>typeof u=="object"&&u!==null))throw new TypeError(`Second argument must be an array of strings: ${o}`);let a=o.map(String),c=a.find(u=>u.includes("\0"));if(c!==void 0)throw new TypeError(`Arguments cannot contain null bytes ("\\0"): ${c}`);if(!xe(s))throw new TypeError(`Last argument\
|
|
@@ -803,14 +803,14 @@ musicNote:"\u266A",musicNoteBeamed:"\u266B",arrowUp:"\u2191",arrowDown:"\u2193",
|
|
|
803
803
|
\u2547",lineUpBoldDownBoldLeftRightBold:"\u254A",lineUpBoldDownBoldLeftBoldRight:"\u2549",lineUpBoldDownLeftRight:"\u2540",lineUpDownBoldLeftRight:"\u2541",lineUpDownLeftBoldRight:"\u253D",lineUpDownLeftRightBold:"\u253E",lineUpBoldDownBoldLeftRight:"\u2542",lineUpDownLeftBoldRightBold:"\u253F",lineUpBoldDownLeftBoldRight:"\u2543",lineUpBoldDownLeftRightBold:"\u2544",lineUpDownBoldLeftBoldRight:"\u2545",lineUpDownBoldLeftRightBold:"\u2546",lineUpDoubleDownDoubleLeftDoubleRightDouble:"\u256C",lineUpDoubleDownDoubleLeftRight:"\
|
|
804
804
|
\u256B",lineUpDownLeftDoubleRightDouble:"\u256A",lineCross:"\u2573",lineBackslash:"\u2572",lineSlash:"\u2571"},wA={tick:"\u2714",info:"\u2139",warning:"\u26A0",cross:"\u2718",squareSmall:"\u25FB",squareSmallFilled:"\u25FC",circle:"\u25EF",circleFilled:"\u25C9",circleDotted:"\u25CC",circleDouble:"\u25CE",circleCircle:"\u24DE",circleCross:"\u24E7",circlePipe:"\u24BE",radioOn:"\u25C9",radioOff:"\u25EF",checkboxOn:"\u2612",checkboxOff:"\u2610",checkboxCircleOn:"\u24E7",checkboxCircleOff:"\u24BE",pointer:"\
|
|
805
805
|
\u276F",triangleUpOutline:"\u25B3",triangleLeft:"\u25C0",triangleRight:"\u25B6",lozenge:"\u25C6",lozengeOutline:"\u25C7",hamburger:"\u2630",smiley:"\u32E1",mustache:"\u0DF4",star:"\u2605",play:"\u25B6",nodejs:"\u2B22",oneSeventh:"\u2150",oneNinth:"\u2151",oneTenth:"\u2152"},Y2={tick:"\u221A",info:"i",warning:"\u203C",cross:"\xD7",squareSmall:"\u25A1",squareSmallFilled:"\u25A0",circle:"( )",circleFilled:"(*)",circleDotted:"( )",circleDouble:"( )",circleCircle:"(\u25CB)",circleCross:"(\xD7)",circlePipe:"\
|
|
806
|
-
(\u2502)",radioOn:"(*)",radioOff:"( )",checkboxOn:"[\xD7]",checkboxOff:"[ ]",checkboxCircleOn:"(\xD7)",checkboxCircleOff:"( )",pointer:">",triangleUpOutline:"\u2206",triangleLeft:"\u25C4",triangleRight:"\u25BA",lozenge:"\u2666",lozengeOutline:"\u25CA",hamburger:"\u2261",smiley:"\u263A",mustache:"\u250C\u2500\u2510",star:"\u2736",play:"\u25BA",nodejs:"\u2666",oneSeventh:"1/7",oneNinth:"1/9",oneTenth:"1/10"},X2={...yA,...wA},Q2={...yA,...Y2},eq=fh(),tq=eq?X2:Q2,Qc=tq,
|
|
807
|
-
|
|
808
|
-
5;5",59),
|
|
806
|
+
(\u2502)",radioOn:"(*)",radioOff:"( )",checkboxOn:"[\xD7]",checkboxOff:"[ ]",checkboxCircleOn:"(\xD7)",checkboxCircleOff:"( )",pointer:">",triangleUpOutline:"\u2206",triangleLeft:"\u25C4",triangleRight:"\u25BA",lozenge:"\u2666",lozengeOutline:"\u25CA",hamburger:"\u2261",smiley:"\u263A",mustache:"\u250C\u2500\u2510",star:"\u2736",play:"\u25BA",nodejs:"\u2666",oneSeventh:"1/7",oneNinth:"1/9",oneTenth:"1/10"},X2={...yA,...wA},Q2={...yA,...Y2},eq=fh(),tq=eq?X2:Q2,Qc=tq,ole=Object.entries(wA);import nq from"node:tty";var rq=nq?.WriteStream?.prototype?.hasColors?.()??!1,z=i((e,t)=>{if(!rq)return o=>o;let n=`\x1B[${e}m`,r=`\x1B[${t}m`;return o=>{let s=o+"",a=s.indexOf(r);if(a===-1)return n+s+r;let c=n,u=0,d=(t===22?r:"")+n;for(;a!==-1;)c+=s.slice(u,a)+d,u=a+r.length,a=s.indexOf(r,u);return c+=s.slice(u)+r,c}},"format"),cle=z(0,0),vA=z(1,22),lle=z(2,22),ule=z(3,23),ple=z(4,24),dle=z("4:2",24),fle=z("4:3",24),mle=z("4:4",24),hle=z("4:5",24),gle=z(53,55),ble=z(7,27),yle=z(8,28),wle=z(9,29),vle=z(30,39),Sle=z(31,39),
|
|
807
|
+
xle=z(32,39),kle=z(33,39),_le=z(34,39),Ple=z(35,39),Ele=z(36,39),Ale=z(37,39),el=z(90,39),Ole=z(40,49),Tle=z(41,49),$le=z(42,49),Cle=z(43,49),Rle=z(44,49),jle=z(45,49),Ile=z(46,49),Dle=z(47,49),Nle=z(100,49),SA=z(91,39),Lle=z(92,39),xA=z(93,39),Mle=z(94,39),zle=z(95,39),Fle=z(96,39),Ble=z(97,39),Ule=z(101,49),qle=z(102,49),Hle=z(103,49),Zle=z(104,49),Gle=z(105,49),Wle=z(106,49),Vle=z(107,49),Kle=z("58;5;0",59),Jle=z("58;5;1",59),Yle=z("58;5;2",59),Xle=z("58;5;3",59),Qle=z("58;5;4",59),eue=z("58;\
|
|
808
|
+
5;5",59),tue=z("58;5;6",59),nue=z("58;5;7",59),rue=z("58;5;8",59),oue=z("58;5;9",59),sue=z("58;5;10",59),iue=z("58;5;11",59),aue=z("58;5;12",59),cue=z("58;5;13",59),lue=z("58;5;14",59),uue=z("58;5;15",59);var PA=i(({type:e,message:t,timestamp:n,piped:r,commandId:o,result:{failed:s=!1}={},options:{reject:a=!0}})=>{let c=oq(n),u=sq[e]({failed:s,reject:a,piped:r}),p=iq[e]({reject:a});return`${el(`[${c}]`)} ${el(`[${o}]`)} ${p(u)} ${p(t)}`},"defaultVerboseFunction"),oq=i(e=>`${tl(e.getHours(),2)}:${tl(e.getMinutes(),2)}:${tl(e.getSeconds(),2)}.${tl(e.getMilliseconds(),3)}`,"serializeTimestamp"),tl=i((e,t)=>String(e).padStart(t,"0"),"padField"),kA=i(({failed:e,reject:t})=>e?t?Qc.cross:Qc.warning:Qc.tick,
|
|
809
809
|
"getFinalIcon"),sq={command:i(({piped:e})=>e?"|":"$","command"),output:i(()=>" ","output"),ipc:i(()=>"*","ipc"),error:kA,duration:kA},_A=i(e=>e,"identity"),iq={command:i(()=>vA,"command"),output:i(()=>_A,"output"),ipc:i(()=>_A,"ipc"),error:i(({reject:e})=>e?SA:xA,"error"),duration:i(()=>el,"duration")};var EA=i((e,t,n)=>{let r=mA(t,n);return e.map(({verboseLine:o,verboseObject:s})=>aq(o,s,r)).filter(o=>o!==void 0).map(o=>cq(o)).join("")},"applyVerboseOnLines"),aq=i((e,t,n)=>{if(n===void 0)return e;let r=n(e,t);if(typeof r=="string")return r},"applyVerboseFunction"),cq=i(e=>e.endsWith(`
|
|
810
810
|
`)?e:`${e}
|
|
811
811
|
`,"appendNewline");var Ft=i(({type:e,verboseMessage:t,fdNumber:n,verboseInfo:r,result:o})=>{let s=uq({type:e,result:o,verboseInfo:r}),a=pq(t,s),c=EA(a,r,n);c!==""&&console.warn(c.slice(0,-1))},"verboseLog"),uq=i(({type:e,result:t,verboseInfo:{escapedCommand:n,commandId:r,rawOptions:{piped:o=!1,...s}}})=>({type:e,escapedCommand:n,commandId:`${r}`,timestamp:new Date,piped:o,result:t,options:s}),"getVerboseObject"),pq=i((e,t)=>e.split(`
|
|
812
812
|
`).map(n=>dq({...t,message:n})),"getPrintedLines"),dq=i(e=>({verboseLine:PA(e),verboseObject:e}),"getPrintedLine"),nl=i(e=>{let t=typeof e=="string"?e:lq(e);return li(t).replaceAll(" "," ".repeat(fq))},"serializeVerboseMessage"),fq=2;var AA=i((e,t)=>{xo(t)&&Ft({type:"command",verboseMessage:e,verboseInfo:t})},"logCommand");var OA=i((e,t,n)=>{gq(e);let r=mq(e);return{verbose:e,escapedCommand:t,commandId:r,rawOptions:n}},"getVerboseInfo"),mq=i(e=>xo({verbose:e})?hq++:void 0,"getCommandId"),hq=0n,gq=i(e=>{for(let t of e){if(t===!1)throw new TypeError(`The "verbose: false" option was renamed to "verbose: 'none'".`);if(t===!0)throw new TypeError(`The "verbose: true" option was renamed to "verbose: 'short'".`);if(!Xc.includes(t)&&!Yc(t)){let n=Xc.map(r=>`'${r}'`).join(", ");throw new TypeError(`The "verbose" option must\
|
|
813
|
-
not be ${t}. Allowed values are: ${n} or a function.`)}}},"validateVerbose");import{hrtime as TA}from"node:process";var rl=i(()=>TA.bigint(),"getStartTime"),mh=i(e=>Number(TA.bigint()-e)/1e6,"getDurationMs");var ol=i((e,t,n)=>{let r=rl(),{command:o,escapedCommand:s}=hA(e,t),a=lh(n,"verbose"),c=OA(a,s,{...n});return AA(s,c),{command:o,escapedCommand:s,startTime:r,verboseInfo:c}},"handleCommand");var AO=Fa(b0(),1);import QH from"node:path";import EO from"node:process";import cl from"node:process";import dr from"node:path";function il(e={}){let{env:t=process.env,platform:n=process.platform}=e;return n!=="win32"?"PATH":Object.keys(t).reverse().find(r=>r.toUpperCase()==="PATH")||"Path"}i(il,"pathKey");import{promisify as qq}from"node:util";import{execFile as Hq,execFileSync as
|
|
813
|
+
not be ${t}. Allowed values are: ${n} or a function.`)}}},"validateVerbose");import{hrtime as TA}from"node:process";var rl=i(()=>TA.bigint(),"getStartTime"),mh=i(e=>Number(TA.bigint()-e)/1e6,"getDurationMs");var ol=i((e,t,n)=>{let r=rl(),{command:o,escapedCommand:s}=hA(e,t),a=lh(n,"verbose"),c=OA(a,s,{...n});return AA(s,c),{command:o,escapedCommand:s,startTime:r,verboseInfo:c}},"handleCommand");var AO=Fa(b0(),1);import QH from"node:path";import EO from"node:process";import cl from"node:process";import dr from"node:path";function il(e={}){let{env:t=process.env,platform:n=process.platform}=e;return n!=="win32"?"PATH":Object.keys(t).reverse().find(r=>r.toUpperCase()==="PATH")||"Path"}i(il,"pathKey");import{promisify as qq}from"node:util";import{execFile as Hq,execFileSync as ype}from"node:child_process";import y0 from"node:path";import{fileURLToPath as Zq}from"node:url";var Spe=qq(Hq);function al(e){return e instanceof URL?Zq(e):e}i(al,"toPath");function w0(e){return{*[Symbol.iterator](){let t=y0.resolve(al(e)),n;for(;n!==t;)yield t,n=t,t=y0.resolve(t,"..")}}}i(w0,"traversePathUp");var xpe=10*1024*1024;var Gq=i(({cwd:e=cl.cwd(),path:t=cl.env[il()],preferLocal:n=!0,execPath:r=cl.execPath,addExecPath:o=!0}={})=>{let s=dr.resolve(al(e)),a=[],c=t.split(dr.delimiter);return n&&Wq(a,c,s),o&&Vq(a,c,r,s),t===""||t===dr.delimiter?`${a.join(dr.delimiter)}${t}`:[...a,t].join(dr.delimiter)},"npmRunPath"),Wq=i((e,t,n)=>{for(let r of w0(n)){let o=dr.join(r,"node_modules/.bin");t.includes(o)||e.push(o)}},"applyPreferLocal"),Vq=i((e,t,n,r)=>{let o=dr.resolve(r,al(n),"..");t.includes(o)||e.push(o)},"applyExecP\
|
|
814
814
|
ath"),v0=i(({env:e=cl.env,...t}={})=>{e={...e};let n=il({env:e});return t.path=e[n],e[n]=Gq(t),e},"npmRunPathEnv");import{setTimeout as lH}from"node:timers/promises";var S0=i((e,t,n)=>{let r=n?pi:ui,o=e instanceof Ot?{}:{cause:e};return new r(t,o)},"getFinalError"),Ot=class extends Error{static{i(this,"DiscardedError")}},x0=i((e,t)=>{Object.defineProperty(e.prototype,"name",{value:t,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,_0,{value:!0,writable:!1,enumerable:!1,configurable:!1})},"setErrorName"),k0=i(e=>ll(e)&&_0 in e,"isExecaError"),_0=Symbol("isExecaError"),ll=i(e=>Object.prototype.toString.call(e)==="[object Error]","i\
|
|
815
815
|
sErrorInstance"),ui=class extends Error{static{i(this,"ExecaError")}};x0(ui,ui.name);var pi=class extends Error{static{i(this,"ExecaSyncError")}};x0(pi,pi.name);import{constants as di}from"node:os";import{constants as Xq}from"node:os";var P0=i(()=>{let e=_h-E0+1;return Array.from({length:e},Kq)},"getRealtimeSignals"),Kq=i((e,t)=>({name:`SIGRT${t+1}`,number:E0+t,action:"terminate",description:"Application-specific signal (realtime)",standard:"posix"}),"getRealtimeSignal"),E0=34,_h=64;import{constants as Jq}from"node:os";var A0=[{name:"SIGHUP",number:1,action:"terminate",description:"Terminal closed",standard:"posix"},{name:"SIGINT",number:2,action:"terminate",description:"User interruption with CTRL-C",standard:"ansi"},{name:"SIGQUIT",number:3,action:"core",description:"User interruption with CTRL-\\",standard:"posix"},{name:"SIGILL",number:4,action:"core",description:"Invalid machine instruction",standard:"ansi"},{name:"SIGTRAP",number:5,action:"core",description:"Debugger breakpoint",standard:"posix"},{name:"\
|
|
816
816
|
SIGABRT",number:6,action:"core",description:"Aborted",standard:"ansi"},{name:"SIGIOT",number:6,action:"core",description:"Aborted",standard:"bsd"},{name:"SIGBUS",number:7,action:"core",description:"Bus error due to misaligned, non-existing address or paging error",standard:"bsd"},{name:"SIGEMT",number:7,action:"terminate",description:"Command should be emulated but is not implemented",standard:"other"},{name:"SIGFPE",number:8,action:"core",description:"Floating point arithmetic error",standard:"\
|
|
@@ -820,7 +820,7 @@ sed or unpaused",standard:"other"},{name:"SIGCONT",number:18,action:"unpause",de
|
|
|
820
820
|
User interruption with CTRL-BREAK",standard:"other"},{name:"SIGTTOU",number:22,action:"pause",description:"Background process cannot write to terminal output",standard:"posix"},{name:"SIGURG",number:23,action:"ignore",description:"Socket received out-of-band data",standard:"bsd"},{name:"SIGXCPU",number:24,action:"core",description:"Process timed out",standard:"bsd"},{name:"SIGXFSZ",number:25,action:"core",description:"File too big",standard:"bsd"},{name:"SIGVTALRM",number:26,action:"terminate",description:"\
|
|
821
821
|
Timeout or timer",standard:"bsd"},{name:"SIGPROF",number:27,action:"terminate",description:"Timeout or timer",standard:"bsd"},{name:"SIGWINCH",number:28,action:"ignore",description:"Terminal window size changed",standard:"bsd"},{name:"SIGIO",number:29,action:"terminate",description:"I/O is available",standard:"other"},{name:"SIGPOLL",number:29,action:"terminate",description:"Watched event",standard:"other"},{name:"SIGINFO",number:29,action:"ignore",description:"Request for process information",standard:"\
|
|
822
822
|
other"},{name:"SIGPWR",number:30,action:"terminate",description:"Device running out of power",standard:"systemv"},{name:"SIGSYS",number:31,action:"core",description:"Invalid system call",standard:"other"},{name:"SIGUNUSED",number:31,action:"terminate",description:"Invalid system call",standard:"other"}];var Ph=i(()=>{let e=P0();return[...A0,...e].map(Yq)},"getSignals"),Yq=i(({name:e,number:t,description:n,action:r,forced:o=!1,standard:s})=>{let{signals:{[e]:a}}=Jq,c=a!==void 0;return{name:e,number:c?a:t,description:n,supported:c,action:r,forced:o,standard:s}},"normalizeSignal");var Qq=i(()=>{let e=Ph();return Object.fromEntries(e.map(eH))},"getSignalsByName"),eH=i(({name:e,number:t,description:n,supported:r,action:o,forced:s,standard:a})=>[e,{name:e,number:t,description:n,supported:r,action:o,forced:s,standard:a}],"getSignalByName"),O0=Qq(),tH=i(()=>{let e=Ph(),t=_h+1,n=Array.from({length:t},(r,o)=>nH(o,e));return Object.assign({},...n)},"getSignalsByNumber"),nH=i((e,t)=>{let n=rH(e,t);if(n===void 0)return{};let{name:r,description:o,supported:s,action:a,forced:c,standard:u}=n;
|
|
823
|
-
return{[e]:{name:r,number:e,description:o,supported:s,action:a,forced:c,standard:u}}},"getSignalByNumber"),rH=i((e,t)=>{let n=t.find(({name:r})=>Xq.signals[r]===e);return n!==void 0?n:t.find(r=>r.number===e)},"findSignalByNumber"),
|
|
823
|
+
return{[e]:{name:r,number:e,description:o,supported:s,action:a,forced:c,standard:u}}},"getSignalByNumber"),rH=i((e,t)=>{let n=t.find(({name:r})=>Xq.signals[r]===e);return n!==void 0?n:t.find(r=>r.number===e)},"findSignalByNumber"),Zpe=tH();var $0=i(e=>{let t="option `killSignal`";if(e===0)throw new TypeError(`Invalid ${t}: 0 cannot be used.`);return R0(e,t)},"normalizeKillSignal"),C0=i(e=>e===0?e:R0(e,"`subprocess.kill()`'s argument"),"normalizeSignalArgument"),R0=i((e,t)=>{if(Number.isInteger(e))return oH(e,t);if(typeof e=="string")return iH(e,t);throw new TypeError(`Invalid ${t} ${String(e)}: it must be a string or an integer.
|
|
824
824
|
${Eh()}`)},"normalizeSignal"),oH=i((e,t)=>{if(T0.has(e))return T0.get(e);throw new TypeError(`Invalid ${t} ${e}: this signal integer does not exist.
|
|
825
825
|
${Eh()}`)},"normalizeSignalInteger"),sH=i(()=>new Map(Object.entries(di.signals).reverse().map(([e,t])=>[t,e])),"getSignalsIntegerToName"),T0=sH(),iH=i((e,t)=>{if(e in di.signals)return e;throw e.toUpperCase()in di.signals?new TypeError(`Invalid ${t} '${e}': please rename it to '${e.toUpperCase()}'.`):new TypeError(`Invalid ${t} '${e}': this signal name does not exist.
|
|
826
826
|
${Eh()}`)},"normalizeSignalName"),Eh=i(()=>`Available signal names: ${aH()}.
|
|
@@ -954,7 +954,7 @@ CV(fg,dg,{value:this,writable:!1,enumerable:!1,configurable:!1})}on(t,n){this.li
|
|
|
954
954
|
return e.unload()}}),"signalExitWrap"),hg=class extends Vl{static{i(this,"SignalExitFallback")}onExit(){return()=>{}}load(){}unload(){}},gg=class extends Vl{static{i(this,"SignalExit")}#t=bg.platform==="win32"?"SIGINT":"SIGHUP";#n=new mg;#e;#r;#s;#o={};#i=!1;constructor(t){super(),this.#e=t,this.#o={};for(let n of yr)this.#o[n]=()=>{let r=this.#e.listeners(n),{count:o}=this.#n,s=t;if(typeof s.__signal_exit_emitter__=="object"&&typeof s.__signal_exit_emitter__.count=="number"&&(o+=s.__signal_exit_emitter__.
|
|
955
955
|
count),r.length===o){this.unload();let a=this.#n.emit("exit",null,n),c=n==="SIGHUP"?this.#t:n;a||t.kill(t.pid,c)}};this.#s=t.reallyExit,this.#r=t.emit}onExit(t,n){if(!Wl(this.#e))return()=>{};this.#i===!1&&this.load();let r=n?.alwaysLast?"afterExit":"exit";return this.#n.on(r,t),()=>{this.#n.removeListener(r,t),this.#n.listeners.exit.length===0&&this.#n.listeners.afterExit.length===0&&this.unload()}}load(){if(!this.#i){this.#i=!0,this.#n.count+=1;for(let t of yr)try{let n=this.#o[t];n&&this.#e.on(
|
|
956
956
|
t,n)}catch{}this.#e.emit=(t,...n)=>this.#c(t,...n),this.#e.reallyExit=t=>this.#a(t)}}unload(){this.#i&&(this.#i=!1,yr.forEach(t=>{let n=this.#o[t];if(!n)throw new Error("Listener not defined for signal: "+t);try{this.#e.removeListener(t,n)}catch{}}),this.#e.emit=this.#r,this.#e.reallyExit=this.#s,this.#n.count-=1)}#a(t){return Wl(this.#e)?(this.#e.exitCode=t||0,this.#n.emit("exit",this.#e.exitCode,null),this.#s.call(this.#e,this.#e.exitCode)):0}#c(t,...n){let r=this.#r;if(t==="exit"&&Wl(this.#e)){
|
|
957
|
-
typeof n[0]=="number"&&(this.#e.exitCode=n[0]);let o=r.call(this.#e,t,...n);return this.#n.emit("exit",this.#e.exitCode,null),o}else return r.call(this.#e,t,...n)}},bg=globalThis.process,{onExit:w$,load:
|
|
957
|
+
typeof n[0]=="number"&&(this.#e.exitCode=n[0]);let o=r.call(this.#e,t,...n);return this.#n.emit("exit",this.#e.exitCode,null),o}else return r.call(this.#e,t,...n)}},bg=globalThis.process,{onExit:w$,load:Kye,unload:Jye}=RV(Wl(bg)?new gg(bg):new hg);var v$=i((e,{cleanup:t,detached:n},{signal:r})=>{if(!t||n)return;let o=w$(()=>{e.kill()});jV(r,()=>{o()})},"cleanupOnExit");var x$=i(({source:e,sourcePromise:t,boundOptions:n,createNested:r},...o)=>{let s=rl(),{destination:a,destinationStream:c,destinationError:u,from:p,unpipeSignal:d}=IV(n,r,o),{sourceStream:f,sourceError:m}=NV(e,p),{options:h,fileDescriptors:b}=Ut.get(e);return{sourcePromise:t,sourceStream:f,sourceOptions:h,sourceError:m,destination:a,destinationStream:c,destinationError:u,unpipeSignal:d,fileDescriptors:b,startTime:s}},"normalizePipeArguments"),IV=i((e,t,n)=>{try{let{destination:r,pipeOptions:{from:o,
|
|
958
958
|
to:s,unpipeSignal:a}={}}=DV(e,t,...n),c=ml(r,s);return{destination:r,destinationStream:c,from:o,unpipeSignal:a}}catch(r){return{destinationError:r}}},"getDestinationStream"),DV=i((e,t,n,...r)=>{if(Array.isArray(n))return{destination:t(S$,e)(n,...r),pipeOptions:e};if(typeof n=="string"||n instanceof URL||sh(n)){if(Object.keys(e).length>0)throw new TypeError('Please use .pipe("file", ..., options) or .pipe(execa("file", ..., options)) instead of .pipe(options)("file", ...).');let[o,s,a]=Wc(n,...r);
|
|
959
959
|
return{destination:t(S$)(o,s,a),pipeOptions:a}}if(Ut.has(n)){if(Object.keys(e).length>0)throw new TypeError("Please use .pipe(options)`command` or .pipe($(options)`command`) instead of .pipe(options)($`command`).");return{destination:n,pipeOptions:r[0]}}throw new TypeError(`The first argument must be a template string, an options object, or an Execa subprocess: ${n}`)},"getDestination"),S$=i(({options:e})=>({options:{...e,stdin:"pipe",piped:!0}}),"mapDestinationArguments"),NV=i((e,t)=>{try{return{
|
|
960
960
|
sourceStream:Oo(e,t)}}catch(n){return{sourceError:n}}},"getSourceStream");var _$=i(({sourceStream:e,sourceError:t,destinationStream:n,destinationError:r,fileDescriptors:o,sourceOptions:s,startTime:a})=>{let c=LV({sourceStream:e,sourceError:t,destinationStream:n,destinationError:r});if(c!==void 0)throw yg({error:c,fileDescriptors:o,sourceOptions:s,startTime:a})},"handlePipeArgumentsError"),LV=i(({sourceStream:e,sourceError:t,destinationStream:n,destinationError:r})=>{if(t!==void 0&&r!==void 0)return r;if(r!==void 0)return pg(e),r;if(t!==void 0)return ug(n),t},"getPipeA\
|
|
@@ -984,7 +984,7 @@ context:f,onInternalError:m,controller:p});return{subprocess:u,promise:h}},"spaw
|
|
|
984
984
|
signal:h,stdio:w,all:P,ipcOutput:y,context:u,options:t,command:a,escapedCommand:c,startTime:n});return Ro(x,r,t)},"handlePromise"),I4=i(({errorInfo:e,exitCode:t,signal:n,stdio:r,all:o,ipcOutput:s,context:a,options:c,command:u,escapedCommand:p,startTime:d})=>"error"in e?bi({error:e.error,command:u,escapedCommand:p,timedOut:a.terminationReason==="timeout",isCanceled:a.terminationReason==="cancel"||a.terminationReason==="gracefulCancel",isGracefullyCanceled:a.terminationReason==="gracefulCancel",isMaxBuffer:e.
|
|
985
985
|
error instanceof qt,isForcefullyTerminated:a.isForcefullyTerminated,exitCode:t,signal:n,stdio:r,all:o,ipcOutput:s,options:c,startTime:d,isSync:!1}):Dl({command:u,escapedCommand:p,stdio:r,all:o,ipcOutput:s,options:c,startTime:d}),"getAsyncResult");var tu=i((e,t)=>{let n=Object.fromEntries(Object.entries(t).map(([r,o])=>[r,D4(r,e[r],o)]));return{...e,...n}},"mergeOptions"),D4=i((e,t,n)=>N4.has(e)&&xe(t)&&xe(n)?{...t,...n}:n,"mergeOption"),N4=new Set(["env",...ph]);var Mn=i((e,t,n,r)=>{let o=i((a,c,u)=>Mn(a,c,n,u),"createNested"),s=i((...a)=>L4({mapArguments:e,deepOptions:n,boundOptions:t,setBoundExeca:r,createNested:o},...a),"boundExeca");return r!==void 0&&r(s,o,t),s},"createExeca"),L4=i(({mapArguments:e,deepOptions:t={},boundOptions:n={},setBoundExeca:r,createNested:o},s,...a)=>{if(xe(s))return o(e,tu(n,s),r);let{file:c,commandArguments:u,options:p,isSync:d}=M4({mapArguments:e,firstArgument:s,nextArguments:a,deepOptions:t,boundOptions:n});return d?JT(c,
|
|
986
986
|
u,p):X$(c,u,p,o)},"callBoundExeca"),M4=i(({mapArguments:e,firstArgument:t,nextArguments:n,deepOptions:r,boundOptions:o})=>{let s=uA(t)?pA(t,n):[t,...n],[a,c,u]=Wc(...s),p=tu(tu(r,o),u),{file:d=a,commandArguments:f=c,options:m=p,isSync:h=!1}=e({file:a,commandArguments:c,options:p});return{file:d,commandArguments:f,options:m,isSync:h}},"parseArguments");var Q$=i(({file:e,commandArguments:t})=>tC(e,t),"mapCommandAsync"),eC=i(({file:e,commandArguments:t})=>({...tC(e,t),isSync:!0}),"mapCommandSync"),tC=i((e,t)=>{if(t.length>0)throw new TypeError(`The command and its arguments must be passed as a single string: ${e} ${t}.`);let[n,...r]=z4(e);return{file:n,commandArguments:r}},"parseCommand"),z4=i(e=>{if(typeof e!="string")throw new TypeError(`The command must be a string: ${String(e)}.`);let t=e.trim();if(t==="")return[];let n=[];for(let r of t.split(
|
|
987
|
-
F4)){let o=n.at(-1);o&&o.endsWith("\\")?n[n.length-1]=`${o.slice(0,-1)} ${r}`:n.push(r)}return n},"parseCommandString"),F4=/ +/g;var nC=i((e,t,n)=>{e.sync=t(B4,n),e.s=e.sync},"setScriptSync"),rC=i(({options:e})=>oC(e),"mapScriptAsync"),B4=i(({options:e})=>({...oC(e),isSync:!0}),"mapScriptSync"),oC=i(e=>({options:{...U4(e),...e}}),"getScriptOptions"),U4=i(({input:e,inputFile:t,stdio:n})=>e===void 0&&t===void 0&&n===void 0?{stdin:"inherit"}:{},"getScriptStdinOption"),sC={preferLocal:!0};var iC=Mn(()=>({})),
|
|
987
|
+
F4)){let o=n.at(-1);o&&o.endsWith("\\")?n[n.length-1]=`${o.slice(0,-1)} ${r}`:n.push(r)}return n},"parseCommandString"),F4=/ +/g;var nC=i((e,t,n)=>{e.sync=t(B4,n),e.s=e.sync},"setScriptSync"),rC=i(({options:e})=>oC(e),"mapScriptAsync"),B4=i(({options:e})=>({...oC(e),isSync:!0}),"mapScriptSync"),oC=i(e=>({options:{...U4(e),...e}}),"getScriptOptions"),U4=i(({input:e,inputFile:t,stdio:n})=>e===void 0&&t===void 0&&n===void 0?{stdin:"inherit"}:{},"getScriptStdinOption"),sC={preferLocal:!0};var iC=Mn(()=>({})),mxe=Mn(()=>({isSync:!0})),hxe=Mn(Q$),gxe=Mn(eC),bxe=Mn(bO),yxe=Mn(rC,{},sC,nC),{sendMessage:wxe,getOneMessage:vxe,getEachMessage:Sxe,getCancelSignal:xxe}=r$();var _i={};function aC(e){_i=e}i(aC,"setProcessReporter");function G4(e){return e==="inherit"?"inherit":_i.quiet?"pipe":_i.verbose?"stream":e}i(G4,"effectiveStdio");function W4(e){return e!=="stream"?{stdio:e}:{stdin:"pipe",stdout:_i.json?"pipe":["pipe","inherit"],stderr:["pipe","inherit"]}}i(W4,"outputTargets");var V4=1e4,K4=3e4,J4=18e4;function Y4(e){let t=Math.round((Date.now()-e)/1e3);return t<60?`${t}s`:`${Math.floor(t/60)}m${String(t%60).padStart(2,"0")}s`}i(Y4,"elapsed");function X4(e,t,n=88){
|
|
988
988
|
let r=[];for(let s=0;s<t.length;s+=1){let a=t[s]??"";if(a==="-f"||a==="--file"){s+=1;continue}r.push(a)}let o=[e,...r].join(" ");return o.length<=n?o:`${o.slice(0,n-1)}\u2026`}i(X4,"describeCommand");function Q4(e,t){if(_i.quiet)return()=>{};let n=Date.now(),r=X4(e,t),o=!1,s=i(()=>{process.stderr.write(`wait still running: ${r} (${Y4(n)})
|
|
989
989
|
`),!o&&Date.now()-n>=J4&&(o=!0,process.stderr.write(` -> a first build of the panel image takes several minutes; Ctrl-C is safe, and --verbose shows its output
|
|
990
990
|
`))},"announce"),a,c=setTimeout(()=>{s(),a=setInterval(s,K4),a.unref?.()},V4);return c.unref?.(),()=>{clearTimeout(c),a&&clearInterval(a)}}i(Q4,"startHeartbeat");async function _(e,t=[],n={}){let r=G4(n.stdio??"pipe"),o={cwd:n.cwd,env:n.env,input:n.input,reject:n.reject??!0,shell:!1,timeout:n.timeout,...W4(r)},s=r==="pipe"?Q4(e,t):()=>{};try{let a=await iC(e,[...t],o),c=a.failed&&a.exitCode===void 0&&!a.signal&&!a.timedOut;return{stdout:typeof a.stdout=="string"?a.stdout:"",stderr:typeof a.stderr==
|
|
@@ -1167,7 +1167,7 @@ savedAt??null};if(r.json)return r.data(p);r.line(`${o}: ${p.user} (${p.role}, vi
|
|
|
1167
1167
|
al for ${o}`)}i(aD,"authLogout");async function cD(e,t){let n=new T(da(t)),r=ua(),o=Object.entries(r.panels).map(([s,a])=>({url:s,user:a.user,role:a.role,savedAt:a.savedAt}));if(n.json)return n.data({panels:o});if(o.length===0){n.line("no saved credentials");return}for(let s of o)n.line(`${s.url} ${s.user} ${s.role}`)}i(cD,"authWhoami");async function lD(e,t){let{client:n,output:r}=de(t),o=await n.request("GET",`/auth/tokens${e.all?"?all=true":""}`);if(r.json)return r.data(o);if(o.tokens.length===
|
|
1168
1168
|
0)return r.line("no tokens");for(let s of o.tokens)r.line([s.id,s.enabled?"active":"revoked",s.actorKind,s.name,s.user].join(" "))}i(lD,"authTokenList");async function uD(e,t){if(!e.name)throw new C("--name is required");let{client:n,output:r}=de(t),o=await n.request("POST","/auth/tokens",{name:e.name,actorKind:e.human?"human":"agent",...e.scopes?{scopes:e.scopes.split(",").map(s=>s.trim()).filter(Boolean)}:{},...e.expiresInDays?{expiresInDays:Number(e.expiresInDays)}:{}});if(r.json)return r.data(
|
|
1169
1169
|
o);r.line(`token: ${o.token}`),r.warning("this is the only time the token is shown"),r.hint("save it with `portta auth login --token \u2026`, or set PORTTA_TOKEN for one command")}i(uD,"authTokenCreate");async function pD(e,t,n){let{client:r,output:o}=de(n);await r.request("DELETE",`/auth/tokens/${encodeURIComponent(e)}`),o.progress(`revoked ${e}`)}i(pD,"authTokenRevoke");import{join as dD}from"node:path";function Ny(e){return e.optsWithGlobals()}i(Ny,"globals");function $5(e,t){let n=Se(t);return[{image:n.runtime,args:["build","--build-arg",`PORTTA_VERSION=${t}`,"--target","runtime","-f","apps/web/Dockerfile","-t",n.runtime,"."]},{image:n.apply,args:["build","--build-arg",`PORTTA_VERSION=${t}`,"-t",n.apply,dD(e,"docker","images","apply")]},{image:n.toolbox,args:["build","--build-arg",`PORTTA_VERSION=${t}`,"-t",n.toolbox,dD(e,"docker","images","toolbox")]}]}i($5,"localReleaseBuilds");async function fD(e){
|
|
1170
|
-
let t=O({profile:Ny(e).profile}),n=new T(Ny(e));await Ct();let r=$5(t.root,t.version);n.step(`local release ${t.version}`);for(let o of r)n.progress(`building ${o.image}`),await _("docker",o.args,{cwd:t.root,stdio:"inherit"});if(Ny(e).json)n.data({version:t.version,images:r.map(({image:o})=>o)});else for(let{image:o}of r)n.progress(`ready ${o}`)}i(fD,"buildCommand");import{copyFileSync as
|
|
1170
|
+
let t=O({profile:Ny(e).profile}),n=new T(Ny(e));await Ct();let r=$5(t.root,t.version);n.step(`local release ${t.version}`);for(let o of r)n.progress(`building ${o.image}`),await _("docker",o.args,{cwd:t.root,stdio:"inherit"});if(Ny(e).json)n.data({version:t.version,images:r.map(({image:o})=>o)});else for(let{image:o}of r)n.progress(`ready ${o}`)}i(fD,"buildCommand");import{copyFileSync as V7,existsSync as Aa,mkdirSync as K7,rmSync as J7,statSync as Y7}from"node:fs";import{basename as X7,dirname as Q7,join as eX}from"node:path";import{existsSync as B7,mkdirSync as $N,readFileSync as U7}from"node:fs";import{join as Ir}from"node:path";import{chmodSync as C5,existsSync as R5,mkdirSync as j5}from"node:fs";import{join as I5}from"node:path";var Ly=[{path:"config/traefik/dynamic",mode:493},{path:"config/tls",mode:493},{path:"state/auth",mode:448},{path:"state/ssh",mode:448},{path:"state/runner",mode:448},{path:"state/cloudflared",mode:448},{path:"state/traefik/acme",mode:448},{path:"state/access",mode:493},{path:"state/tailscale",mode:493},{path:"state/git",mode:493},{path:"state/metrics",mode:493},{path:"state/environment",mode:493},{path:"state/logs",mode:493}];function rs(e){for(let{path:t,mode:n}of Ly){let r=I5(e,t),o=!R5(r);j5(
|
|
1171
1171
|
r,{recursive:!0}),(o||n===448)&&C5(r,n)}}i(rs,"ensureInstallationDirectories");import{join as D5}from"node:path";async function Op(e){if(e.env.PORTTA_LOCAL_RELEASE!=="true")return;let t=[];for(let n of Object.values(Se(e.version)))(await _("docker",["image","inspect",n],{reject:!1})).exitCode!==0&&t.push(n);if(t.length>0)throw new L(`local release ${e.version} is incomplete: missing ${t.join(", ")}`,"run just build")}i(Op,"requireLocalRelease");function Tp(e){let t=Se(e.version).runtime;je(D5(e.root,".env"),{PORTTA_AUTH_IMAGE:t,PORTTA_WEB_IMAGE:t,PORTTA_WEB_BUILD:"false",PORTTA_WEB_DEV:"false"})}i(Tp,"sele\
|
|
1172
1172
|
ctLocalRelease");import{homedir as Z5}from"node:os";import{accessSync as N5,constants as L5,globSync as M5,statSync as hD}from"node:fs";import{homedir as z5}from"node:os";import{join as yn}from"node:path";function F5(e){let[t,n]=e.split(".").map(Number);return t===100&&n!==void 0&&n>=64&&n<=127}i(F5,"isTailscaleRange");function gD(e){let t=e.split(".").map(Number);if(t.length!==4||t.some(o=>!Number.isInteger(o)||o<0||o>255))return!1;let[n,r]=t;return n===10||n===127||n===172&&r>=16&&r<=31||n===192&&r===168||n===169&&r===254?!0:F5(e)}i(gD,"isPrivateAddress");function mD(e){try{return N5(e,L5.X_OK),hD(e).isFile()}catch{return!1}}i(mD,"executable");async function fa(e){let t=await _("which",[e],{reject:!1}),
|
|
1173
1173
|
n=t.stdout.trim().split(`
|
|
@@ -1256,191 +1256,191 @@ Nothing in this project was modified. See docs/product/guides/adopting-projects.
|
|
|
1256
1256
|
some(d=>d.labels["com.docker.compose.project"]===c))throw new U(`Compose project ${c} is already running`,"pass --no-check only when sharing it is intentional");let u=new T(as(t));u.json?u.data({namespace:c,base:Vr(s),suffix:a}):u.data(c)}i(pN,"namespaceCommand");var m7="this project's containers are gone; start them with the runner (PORTTA_RUNNER=true) or docker compose up in the working directory";async function Up(e,t,n){let r=(await J()).filter(m=>m.labels["com.docker.compose.project"]===e);
|
|
1257
1257
|
if(r.length===0)throw new C(`no project '${e}' is running`,m7);let o=r.find(m=>m.labels["portta.managed"]==="true");if(o)throw new U(`refusing to ${t} ${o.name}: it is a Portta component`,"gateway components are restarted with portta restart");let s=r.map(m=>({service:m.labels["com.docker.compose.service"]??m.name,name:m.name,dependsOn:UE(m.labels[BE]),id:m.id,state:m.state})),a=Ym(s,"stop"),c=Ym(s,"start"),u=t==="restart"?[...a.map(m=>({...m,verb:"stop"})),...c.map(m=>({...m,verb:"start"}))]:(t===
|
|
1258
1258
|
"stop"?a:c).map(m=>({...m,verb:t})),p=new T(as(n)),d=new Map(s.map(m=>[m.id,m.state])),f=0;for(let m of u){let h=d.get(m.id)??m.state;if(m.verb==="start"&&h==="running"||m.verb==="stop"&&h!=="running"&&h!=="restarting"){p.progress(`skip ${m.service} already ${m.verb==="start"?"running":"stopped"}`);continue}let g=await _("docker",[m.verb,m.id],{reject:!1});if(g.failed){f+=1,p.warning(`${m.verb} ${m.service}: ${g.stderr.trim()||g.stdout.trim()||"failed"}`);continue}d.set(m.id,m.verb==="start"?
|
|
1259
|
-
"running":"exited"),p.progress(`ok ${m.verb} ${m.service}`)}if(f>0)throw new U(`${f} service(s) failed to ${t}`,"the rest of the project was still acted on")}i(Up,"projectAction");var v7=["compose.yaml","compose.yml","docker-compose.yaml","docker-compose.yml"],S7=new Set(["node_modules","lost+found","vendor","dist","build"]),x7=8,k7=5*6e4,_7=["/etc","/proc","/sys","/dev","/boot","/
|
|
1260
|
-
test(e)}i(
|
|
1261
|
-
p=w7(e,r).split(/[\\/]/).join("/");if(u?.isFile()&&DE(p)){t.push({path:p,composeFile:a,modifiedAt:Math.floor(u.mtimeMs/1e3)});return}}for(let c of s.sort()){if(c.startsWith(".")||S7.has(c))continue;let u=dN(lt(r,c),{throwIfNoEntry:!1});u?.isDirectory()&&!u.isSymbolicLink()&&n(lt(r,c),o+1)}},"walk");return n(e,0),t}i(
|
|
1259
|
+
"running":"exited"),p.progress(`ok ${m.verb} ${m.service}`)}if(f>0)throw new U(`${f} service(s) failed to ${t}`,"the rest of the project was still acted on")}i(Up,"projectAction");var v7=["compose.yaml","compose.yml","docker-compose.yaml","docker-compose.yml"],S7=new Set(["node_modules","lost+found","vendor","dist","build"]),x7=8,k7=5*6e4,_7=["/etc","/proc","/sys","/dev","/boot","/var/lib/docker","/var/run","/run"],P7=/^\/(?:root|home|Users|home\/[^/]+|Users\/[^/]+)\/*$/;function E7(e){let t=e.split("/").filter(Boolean);return t.length<2||t.some(n=>n.startsWith("."))||P7.test(e)?!1:!_7.some(n=>e===n||e.startsWith(`${n}/`))}i(E7,"isWalkableHome");function A7(e){return/(oci:\/\/|git\+[a-z]+:\/\/|git@[\w.-]+:|\b(?:file|path|extends):\s*['"]?https?:\/\/|^\s*-\s*['"]?https?:\/\/)/im.
|
|
1260
|
+
test(e)}i(A7,"reachesOut");function O7(e){return lt(e,"state/discovery")}i(O7,"discoveryDir");function T7(e){try{let n=(hN(lt(e,".env"))?me(bN(lt(e,".env"),"utf8")):new Map).get("PORTTA_PROJECTS_HOME")?.trim(),r=n&&n!==""?n:qc(mN(),process.getuid?.()===0),o=Hc(r,e,mN());return E7(o)?o:null}catch{return null}}i(T7,"projectsHomeOf");function $7(e){let t=[],n=i((r,o)=>{if(t.length>=200||o>3)return;let s;try{s=gN(r)}catch{return}let a=v7.find(c=>s.includes(c));if(a&&o>0){let c=lt(r,a),u=dN(c,{throwIfNoEntry:!1}),
|
|
1261
|
+
p=w7(e,r).split(/[\\/]/).join("/");if(u?.isFile()&&DE(p)){t.push({path:p,composeFile:a,modifiedAt:Math.floor(u.mtimeMs/1e3)});return}}for(let c of s.sort()){if(c.startsWith(".")||S7.has(c))continue;let u=dN(lt(r,c),{throwIfNoEntry:!1});u?.isDirectory()&&!u.isSymbolicLink()&&n(lt(r,c),o+1)}},"walk");return n(e,0),t}i($7,"findComposeFolders");var ka=new Map;async function C7(e,t,n){let r="";try{r=bN(lt(e,t.path,t.composeFile),"utf8")}catch{return null}if(A7(r))return null;let o=await ow(lt(e,t.path)).
|
|
1262
1262
|
catch(()=>null);return o?{version:1,path:t.path,composeFile:o.compose_file,project:o.project,domain:o.domain,adopted:o.gateway_overlay!==null,services:o.services.map(s=>({name:s.name,image:s.image,kind:s.kind,port:s.kind==="http"?s.container_ports[0]??s.expose[0]??null:null,publishedPorts:s.published_ports.map(a=>({host:String(a.host),container:String(a.container)})),containerName:s.container_name})),findings:{publishedHostPorts:o.findings.published_host_ports,fixedContainerNames:o.findings.fixed_container_names,
|
|
1263
|
-
publishedDatastores:o.findings.published_datastores,implicitNamespace:o.findings.implicit_namespace,containerNameCollisions:o.findings.container_name_collisions.map(s=>({service:s.service,containerName:s.container_name,usedBy:s.used_by})),namespaceInUse:o.findings.namespace_in_use?{project:o.findings.namespace_in_use.project,workingDirs:o.findings.namespace_in_use.working_dirs}:null},collectedAt:Math.floor(n/1e3)}:null}i(
|
|
1264
|
-
if(!n||!hN(n)||!y7(n).isDirectory()){fN(r,{recursive:!0,force:!0});return}let o
|
|
1263
|
+
publishedDatastores:o.findings.published_datastores,implicitNamespace:o.findings.implicit_namespace,containerNameCollisions:o.findings.container_name_collisions.map(s=>({service:s.service,containerName:s.container_name,usedBy:s.used_by})),namespaceInUse:o.findings.namespace_in_use?{project:o.findings.namespace_in_use.project,workingDirs:o.findings.namespace_in_use.working_dirs}:null},collectedAt:Math.floor(n/1e3)}:null}i(C7,"planFolder");async function yN(e,t=Date.now()){try{let n=T7(e),r=O7(e);
|
|
1264
|
+
if(!n||!hN(n)||!y7(n).isDirectory()){fN(r,{recursive:!0,force:!0});return}let o=$7(n);b7(lt(r,"plans"),{recursive:!0,mode:493});let s=x7;for(let p of o){let d=ka.get(p.path);(!d||d.modifiedAt!==p.modifiedAt||t-d.at>=k7)&&s>0&&(s-=1,ka.set(p.path,{at:t,modifiedAt:p.modifiedAt,plan:await C7(n,p,t)}))}let a=new Set,c=o.map(p=>{let d=ka.get(p.path)?.plan??null;return d&&(a.add(bo(p.path)),Ve(lt(r,"plans",bo(p.path)),`${JSON.stringify(d)}
|
|
1265
1265
|
`)),{path:p.path,composeFile:p.composeFile,services:d?d.services.length:null,modifiedAt:p.modifiedAt,adopted:d?.adopted??!1,planned:d!==null}});for(let p of gN(lt(r,"plans")))!a.has(p)&&!p.startsWith(".")&&fN(lt(r,"plans",p),{force:!0});for(let p of[...ka.keys()])o.some(d=>d.path===p)||ka.delete(p);let u={version:1,home:n,collectedAt:Math.floor(t/1e3),folders:c};Ve(lt(r,"folders.json"),`${JSON.stringify(u)}
|
|
1266
|
-
`)}catch{}}i(yN,"publishDiscovery");import{existsSync as wN,readFileSync as vN,unlinkSync as
|
|
1267
|
-
!
|
|
1268
|
-
`)}i(kN,"writePid");function
|
|
1269
|
-
t,"SIGTERM"),!0}catch{return!1}}i(_N,"stopCollector");function
|
|
1270
|
-
all([ha(),ya(e,void 0,Cr(e,t))]);va(e,p),wa(e,d)}catch(p){ga(e,`environment collect failed: ${p instanceof Error?p.message:String(p)}`)}}let c=Date.now()-a,u=Math.max(0,5e3-c);if(!o)break;await
|
|
1271
|
-
async function qp(e,t){try{let n=O({profile:e}),{pid:r,started:o}=aw(n.root,n.config.profile);o&&t.progress(`host metrics collector started (pid ${r})`)}catch(n){t.warning(`Host metrics collector could not start: ${n instanceof Error?n.message:String(n)}`)}}i(qp,"ensureMetricsCollector");function _a(e,t){try{let n=O({profile:e,required:!1});_N(n.root)&&t.progress("host metrics collector stopped")}catch{}}i(_a,"stopMetricsCollector");async function AN(e){let t=cs(e).profile,n=O({profile:t}),r=await
|
|
1266
|
+
`)}catch{}}i(yN,"publishDiscovery");import{existsSync as wN,readFileSync as vN,unlinkSync as I7}from"node:fs";function SN(e){let t=Cp(e);if(!wN(t))return null;let n=Number(vN(t,"utf8").trim());return Number.isInteger(n)&&n>0?n:null}i(SN,"readCollectorPid");function xN(e){try{return process.kill(e,0),!0}catch{return!1}}i(xN,"pidAlive");function D7(e){try{return vN(`/proc/${e}/cmdline`,"utf8").replace(/\0/g," ")}catch{return""}}i(D7,"commandLine");function N7(e){let t=D7(e);return t===""?!0:t.includes("host")&&t.includes("watch")}i(N7,"pidIsCollector");function sw(e){let t=SN(e);return t===null?null:!xN(t)||
|
|
1267
|
+
!N7(t)?(iw(e),null):t}i(sw,"collectorRunning");function iw(e){let t=Cp(e);wN(t)&&I7(t)}i(iw,"clearPid");function kN(e,t){Ve(Cp(e),`${t}
|
|
1268
|
+
`)}i(kN,"writePid");function L7(){let e=process.argv[1];return{file:process.execPath,args:e?[e]:[]}}i(L7,"cliInvocation");function aw(e,t){let n=sw(e);if(n!==null)return{pid:n,started:!1};let{file:r,args:o}=L7(),s=t?["--profile",t]:[],a=cC(r,[...o,...s,"host","watch","--loop"],{cwd:e,env:{...process.env,PORTTA_ROOT:e}});return a===void 0?{pid:null,started:!1}:(kN(e,a),{pid:a,started:!0})}i(aw,"startCollector");function _N(e){let t=SN(e);if(iw(e),t===null||!xN(t))return!1;try{return process.kill(
|
|
1269
|
+
t,"SIGTERM"),!0}catch{return!1}}i(_N,"stopCollector");function M7(e){return new Promise(t=>setTimeout(t,e))}i(M7,"sleep");async function PN(e,t){kN(e,process.pid),ga(e,`collector started pid=${process.pid}`);let n=0,r=0,o=!0,s=i(()=>{o=!1},"halt");for(process.on("SIGTERM",s),process.on("SIGINT",s);o;){let a=Date.now();try{let p=await zp(e,a);jp(e,p),(a-n>=15e3||n===0)&&(CD(e,p),n=a)}catch(p){ga(e,`collect failed: ${p instanceof Error?p.message:String(p)}`)}if(a-r>=Gv||r===0){r=a;try{let[p,d]=await Promise.
|
|
1270
|
+
all([ha(),ya(e,void 0,Cr(e,t))]);va(e,p),wa(e,d)}catch(p){ga(e,`environment collect failed: ${p instanceof Error?p.message:String(p)}`)}}let c=Date.now()-a,u=Math.max(0,5e3-c);if(!o)break;await M7(u)}iw(e),ga(e,"collector stopped")}i(PN,"runCollectorLoop");function cs(e){return e.optsWithGlobals()}i(cs,"globals");async function F7(e,t){let n=await zp(e),r=jp(e,n);await yN(e);let[o,s]=await Promise.all([ha(),ya(e,void 0,Cr(e,t))]);return va(e,o),wa(e,s),r}i(F7,"collectHostResources");async function EN(e){let t=cs(e).profile,n=O({profile:t}),[r,o]=await Promise.all([ha(),ya(n.root,void 0,Cr(n.root,t))]),s=va(n.root,r),a=wa(n.root,o),c=new T(cs(e));c.json?c.data({file:s,securityFile:a,...r}):c.progress(`wrote ${s} and ${a}`)}i(EN,"environmentReport");
|
|
1271
|
+
async function qp(e,t){try{let n=O({profile:e}),{pid:r,started:o}=aw(n.root,n.config.profile);o&&t.progress(`host metrics collector started (pid ${r})`)}catch(n){t.warning(`Host metrics collector could not start: ${n instanceof Error?n.message:String(n)}`)}}i(qp,"ensureMetricsCollector");function _a(e,t){try{let n=O({profile:e,required:!1});_N(n.root)&&t.progress("host metrics collector stopped")}catch{}}i(_a,"stopMetricsCollector");async function AN(e){let t=cs(e).profile,n=O({profile:t}),r=await F7(
|
|
1272
1272
|
n.root,t),o=new T(cs(e));if(o.json){o.data({file:r,collected:!0});return}o.progress(`wrote ${r}`)}i(AN,"hostCollect");async function ON(e){let t=cs(e),n=O({profile:t.profile});if(t.loop){await PN(n.root,t.profile);return}let r=new T(t),{pid:o,started:s}=aw(n.root,n.config.profile);if(r.json){r.data({pid:o,started:s,file:os(n.root)});return}r.progress(s?`host metrics collector started (pid ${o})`:`host metrics collector already running (pid ${o})`)}i(ON,"hostWatch");async function TN(e){let t=cs(
|
|
1273
|
-
e),n=O({profile:t.profile}),r=sw(n.root),o=Ip(n.root),s=Math.floor(Date.now()/1e3),a=o?Math.max(0,s-o.collectedAt):null,c=a!==null&&a>30,u={running:r!==null,pid:r,collectedAt:o?.collectedAt??null,ageSeconds:a,stale:c,file:os(n.root)},p=new T(t);if(p.json){p.data(u);return}r===null?p.line("collector: stopped"):p.line(`collector: running (pid ${r})`),a===null?p.line("last collect: never"):p.line(`last collect: ${a}s ago${c?" (stale)":""}`)}i(TN,"hostStatus");function He(e){return e.optsWithGlobals()}i(He,"globals");function CN(e,t){let n=Ir(e,".env");je(n,t)}i(CN,"setValues");function Pa(e,t){let n=Ir(e,"state/auth/protections.json"),r=Ze(n);Zr(n,r);let o=Ir(e,"config/traefik/dynamic");$N(o,{recursive:!0}),St(Ir(o,"portta-auth.yaml"),Gr(r));let s=Ir(o,"portta-aliases.yaml");if(
|
|
1273
|
+
e),n=O({profile:t.profile}),r=sw(n.root),o=Ip(n.root),s=Math.floor(Date.now()/1e3),a=o?Math.max(0,s-o.collectedAt):null,c=a!==null&&a>30,u={running:r!==null,pid:r,collectedAt:o?.collectedAt??null,ageSeconds:a,stale:c,file:os(n.root)},p=new T(t);if(p.json){p.data(u);return}r===null?p.line("collector: stopped"):p.line(`collector: running (pid ${r})`),a===null?p.line("last collect: never"):p.line(`last collect: ${a}s ago${c?" (stale)":""}`)}i(TN,"hostStatus");function He(e){return e.optsWithGlobals()}i(He,"globals");function CN(e,t){let n=Ir(e,".env");je(n,t)}i(CN,"setValues");function Pa(e,t){let n=Ir(e,"state/auth/protections.json"),r=Ze(n);Zr(n,r);let o=Ir(e,"config/traefik/dynamic");$N(o,{recursive:!0}),St(Ir(o,"portta-auth.yaml"),Gr(r));let s=Ir(o,"portta-aliases.yaml");if(B7(s)){let a=t==="remote-public";St(s,Ts(Wr(U7(s,"utf8")),r,a))}}i(Pa,"syncForwardAuth");var Hp={PORTTA_WEB:"true"};async function cw(e,t,n={},r="inherit"){let o=O({profile:He(
|
|
1274
1274
|
e).profile,overrides:Hp});return _("docker",["compose",...we(o),...t],{cwd:o.root,env:{...o.env,...n},stdio:r})}i(cw,"webCompose");function lw(e,t){xt(Ir(O({profile:He(t).profile}).root,".env")),e.localRelease&&Tp(O({profile:He(t).profile}));let n=O({profile:He(t).profile}),r=e.expose??n.config.webExpose;if(!kn(r))throw new C(`--expose must be one of: ${Kr.join(", ")}`);if(r==="vpn"&&n.config.profile==="remote-public")throw new U("the panel must not be routed on the tailnet hostname while Traefi\
|
|
1275
1275
|
k binds every interface","portta web up --expose domain routes it on the gateway's own domain, behind the same login page");if(r==="domain"){let p=n.env.PORTTA_PANEL_ADVERTISED_HOST??"";if(!p||p==="localhost"||/^[0-9.]+$/.test(p))throw new U(`panel access 'domain' needs a hostname to route on, and this host advertises ${p||"nothing"}`,"portta config set panel.host portta.example.com");if(!n.config.tlsEnabled)throw new U("a panel routed on the domain would carry its session cookie in clear text",
|
|
1276
1276
|
"enable TLS first: portta config set tls.enabled true")}let o=n.env.PORTTA_AUTH_MODE==="required";if(!rn(r)&&!o)throw new U(`panel access '${r}' answers whoever finds the address, and the panel would answer them as the local operator`,"portta config set panel.auth required");rn(r)&&!o&&r!=="local"&&new T(He(t)).warning(`anybody who reaches the panel over the ${r==="tailscale"?"tailnet":"VPN"} is the local operator`);let s=e.writable?!1:e.readOnly??(r==="vpn"?!0:n.config.webReadOnly),a={PORTTA_WEB:"\
|
|
1277
|
-
true",PORTTA_WEB_EXPOSE:r,PORTTA_WEB_READ_ONLY:String(s),PORTTA_WEB_DEV:String(e.dev??n.config.webDev)};e.port&&(a.PORTTA_WEB_PORT=String(Number(e.port))),(!n.env.PORTTA_PANEL_URL||e.expose||e.port)&&(a.PORTTA_PANEL_URL=
|
|
1277
|
+
true",PORTTA_WEB_EXPOSE:r,PORTTA_WEB_READ_ONLY:String(s),PORTTA_WEB_DEV:String(e.dev??n.config.webDev)};e.port&&(a.PORTTA_WEB_PORT=String(Number(e.port))),(!n.env.PORTTA_PANEL_URL||e.expose||e.port)&&(a.PORTTA_PANEL_URL=G7(n,r,e.port?String(Number(e.port)):String(n.config.webPort))),CN(n.root,a),rs(n.root),Pa(n.root,n.config.profile);let c=O({profile:He(t).profile,overrides:a}),u=new T(He(t));return{context:c,values:a,output:u}}i(lw,"prepareWebUp");async function Ea(e,t){let n=lw(e,t),{context:r,
|
|
1278
1278
|
output:o}=n;e.localRelease&&(r.env.PORTTA_LOCAL_RELEASE="true"),o.step("panel"),e.dev||await Op(r),await Zt(r.config.network),o.progress("pulling alpine/socat:1.8.1.3"),await _("docker",["pull","alpine/socat:1.8.1.3"],{reject:!1,stdio:"stream"}),$N(Ir(r.root,"state","panel"),{recursive:!0});let s=["portta-auth","web","web-socket-proxy"],a=r.config.webDev||r.config.webBuild?["--build"]:[];if(o.progress(a.length>0?`starting ${s.join(", ")}, building the panel image`:`starting ${s.join(", ")}`),(await _(
|
|
1279
1279
|
"docker",["compose",...we(r),"up","-d",...a,"--remove-orphans","--wait","--wait-timeout","180",...s],{cwd:r.root,env:r.env,stdio:"inherit",reject:!1})).exitCode!==0)throw new L("the panel did not report healthy within 180s","portta web logs shows what it is doing; portta doctor checks the rest");await uw(n,t)}i(Ea,"webUp");async function uw(e,t,n=!0,r){let{context:o,values:s,output:a}=e;n&&await qp(o.config.profile,a);let c=O({profile:He(t).profile,overrides:s});try{let d=await pw(c,r);d.applied.
|
|
1280
1280
|
length>0?a.progress(`applied ${d.applied.join(", ")}`):a.detail(`panel schema is current (${d.migrations.length} migrations)`)}catch(d){a.warning(`pending panel migrations were not applied: ${d instanceof Error?d.message:String(d)}`),a.hint(d instanceof _e&&d.hint?d.hint:"portta db migrate")}let u=dw(c);(await RN(Zp(c)))?.setupRequired&&(a.progress(`this panel has no owner yet: open ${u}/setup to create it`),a.hint("portta auth bootstrap --email you@example.com creates it from this host instea\
|
|
1281
|
-
d")),a.data(u)}i(uw,"finishWebUp");function Zp(e){let t=e.env.PORTTA_WEB_BIND_ADDRESS??"127.0.0.1";return`http://${t==="0.0.0.0"||t==="::"||t==="[::]"?"127.0.0.1":t}:${e.config.webPort}`}i(Zp,"panelLoopbackApiUrl");var
|
|
1282
|
-
"run portta web up")}i(
|
|
1281
|
+
d")),a.data(u)}i(uw,"finishWebUp");function Zp(e){let t=e.env.PORTTA_WEB_BIND_ADDRESS??"127.0.0.1";return`http://${t==="0.0.0.0"||t==="::"||t==="[::]"?"127.0.0.1":t}:${e.config.webPort}`}i(Zp,"panelLoopbackApiUrl");var q7=12e4,H7=500;async function Z7(e,t=q7){let n=`${Zp(e)}/api/health`,r=Date.now()+t;for(;Date.now()<r;){try{let o=await fetch(n,{signal:AbortSignal.timeout(3e3)});if(o.ok||o.status===401)return}catch{}await new Promise(o=>setTimeout(o,H7))}throw new L("the panel is not reachable",
|
|
1282
|
+
"run portta web up")}i(Z7,"waitForPanelLoopback");async function pw(e,t){await Z7(e);let n=`${Zp(e)}/api/database/migrate`,r;try{r=await fetch(n,{method:"POST",headers:{"content-type":"application/json",...t?{authorization:`Bearer ${t}`}:{}},body:"{}",signal:AbortSignal.timeout(6e4)})}catch{throw new L("the panel is not reachable","run portta web up")}let o=await r.json().catch(()=>({}));if(!r.ok)throw new L(o.error??`the panel refused to migrate (HTTP ${r.status})`,o.hint??"run portta db status");
|
|
1283
1283
|
return{applied:o.applied??[],migrations:o.migrations??[]}}i(pw,"requestPanelMigrate");function dw(e){return e.config.webExpose==="vpn"?`${e.config.tlsEnabled?"https":"http"}://${e.env.PORTTA_WEB_HOST??"portta-web"}.${e.config.domain}`:e.config.webExpose==="domain"?`${e.config.tlsEnabled?"https":"http"}://${e.env.PORTTA_PANEL_ADVERTISED_HOST??e.config.domain}`:e.config.webExpose==="public"?`http://${(e.env.PORTTA_PANEL_ADVERTISED_HOST||null)??"<this-host>"}:${e.config.webPort}`:`http://${e.env.PORTTA_WEB_BIND_ADDRESS??
|
|
1284
|
-
"127.0.0.1"}:${e.config.webPort}`}i(dw,"webUrl");function
|
|
1285
|
-
27.0.0.1":o}:${n}`}i(
|
|
1284
|
+
"127.0.0.1"}:${e.config.webPort}`}i(dw,"webUrl");function G7(e,t,n){let r=e.config.tlsEnabled?"https":"http";if(t==="domain")return`${r}://${e.env.PORTTA_PANEL_ADVERTISED_HOST??e.config.domain}`;if(t==="vpn")return`${r}://${e.env.PORTTA_WEB_HOST??"portta-web"}.${e.config.domain}`;if(t==="public"){let a=e.env.PORTTA_PANEL_ADVERTISED_HOST||null;return a?`http://${a}:${n}`:`http://127.0.0.1:${n}`}let o=e.env.PORTTA_WEB_BIND_ADDRESS??"127.0.0.1";return`http://${o==="0.0.0.0"||o==="::"||o==="[::]"?"1\
|
|
1285
|
+
27.0.0.1":o}:${n}`}i(G7,"panelUrlFor");async function RN(e){try{let t=await fetch(`${e}/api/auth/status`,{signal:AbortSignal.timeout(5e3)});if(!t.ok)return null;let n=await t.json();return typeof n.mode!="string"?null:{mode:n.mode,setupRequired:n.setupRequired===!0}}catch{return null}}i(RN,"panelSetupState");var W7=["web","web-socket-proxy"];async function fw(e){let t=O({profile:He(e).profile,overrides:{...Hp,PORTTA_WEB_DEV:"true"}}),n={...t.env,PORTTA_WEB:"true",PORTTA_WEB_DEV:"true"},r=W7;await _(
|
|
1286
1286
|
"docker",["compose",...we({...t,env:n}),"stop",...r],{cwd:t.root,env:n,reject:!1}),await _("docker",["compose",...we({...t,env:n}),"rm","-f",...r],{cwd:t.root,env:n,reject:!1});let o=new T(He(e));_a(He(e).profile,o),o.progress("panel stopped; gateway and projects were not touched")}i(fw,"webDown");async function jN(e){await fw(e);let t=O({profile:He(e).profile,overrides:Hp});CN(t.root,{PORTTA_WEB:"false"})}i(jN,"webDisable");async function IN(e){await cw(e,["restart","web","web-socket-proxy"])}i(
|
|
1287
1287
|
IN,"webRestart");async function DN(e,t){let n=e??"web";if(!["web","web-socket-proxy","portta-auth"].includes(n))throw new C(`unknown panel service: ${n}`);let r=He(t);if(r.json){let o=await cw(t,["logs","--no-color","--no-log-prefix","--tail","100",n],{},"pipe");new T(r).data({lines:o.stdout.split(`
|
|
1288
1288
|
`).filter(Boolean)})}else await cw(t,["logs","--follow","--tail","100",n])}i(DN,"webLogs");async function NN(e){let t=O({profile:He(e).profile}),n=Se(t.version).runtime;await _("docker",["build","--build-arg",`PORTTA_VERSION=${t.version}`,"--target","runtime","-f","apps/web/Dockerfile","-t",n,"."],{cwd:t.root,stdio:"inherit"})}i(NN,"webBuild");async function LN(e){let t=He(e),n=O({profile:t.profile,overrides:Hp}),r=await J(),o=r.find(p=>p.labels["portta.component"]==="web"),s=r.find(p=>p.labels["\
|
|
1289
1289
|
portta.component"]==="web-socket-proxy"),a=o?.state==="running"?await RN(Zp(n)):null,c={enabled:n.config.webEnabled,devMode:re(n.env.PORTTA_WEB_DEV),readOnly:n.config.webReadOnly,expose:n.config.webExpose,authMode:n.config.authMode,setupRequired:a?a.setupRequired:null,url:dw(n),panel:{state:o?.state??"absent"},socketProxy:{state:s?.state??"absent"}},u=new T(t);if(u.json)u.data(c);else for(let[p,d]of Object.entries(c))u.line(`${p}: ${typeof d=="object"?JSON.stringify(d):String(d)}`)}i(LN,"webStat\
|
|
1290
|
-
us");async function MN(e){let t=O({profile:He(e).profile}),n=dw(t);new T(He(e)).data(n);let r=process.platform==="darwin"?"open":"xportta-open";await _(r,[n],{reject:!1})}i(MN,"webOpen");function Yt(e){return e.optsWithGlobals()}i(Yt,"globals");async function
|
|
1290
|
+
us");async function MN(e){let t=O({profile:He(e).profile}),n=dw(t);new T(He(e)).data(n);let r=process.platform==="darwin"?"open":"xportta-open";await _(r,[n],{reject:!1})}i(MN,"webOpen");function Yt(e){return e.optsWithGlobals()}i(Yt,"globals");async function tX(e){let t=O({profile:Yt(e).profile}),n=Se(t.version).toolbox;return(await _("docker",["image","inspect",n],{reject:!1})).exitCode===0||await _("docker",["build","-q","--build-arg",`PORTTA_VERSION=${t.version}`,"-t",n,eX(t.root,"docker","images","toolbox")],{stdio:"inherit"}),n}i(tX,"ensureToolbox");async function nX(e){let t=await _("docker",["inspect",e,"--format","{{ range .Config.Env }}{{ println . }}{{ end }}"]);return Object.
|
|
1291
1291
|
fromEntries(t.stdout.split(`
|
|
1292
|
-
`).map(n=>[n.slice(0,n.indexOf("=")),n.slice(n.indexOf("=")+1)]).filter(([n])=>n))}i(
|
|
1293
|
-
`no running container for ${t.project}/${t.service}`);let c=a.networks.find(b=>![o.config.network,o.config.accessNetwork,o.config.controlNetwork].includes(b));if(!c)throw new L(`${t.project}/${t.service} has no private network`);let u=Number(t.port??
|
|
1294
|
-
(d.PGPASSWORD=p.POSTGRES_PASSWORD,f.push("-e","PGPASSWORD")),e==="mysql"&&p.MYSQL_PASSWORD&&(d.MYSQL_PWD=p.MYSQL_PASSWORD,f.push("-e","MYSQL_PWD"));let h=await
|
|
1292
|
+
`).map(n=>[n.slice(0,n.indexOf("=")),n.slice(n.indexOf("=")+1)]).filter(([n])=>n))}i(nX,"containerEnvironment");function rX(e){return/postgres|postgis|timescale/i.test(e)?5432:/mysql|mariadb|percona/i.test(e)?3306:/redis|valkey|keydb/i.test(e)?6379:null}i(rX,"defaultPort");async function Gp(e,t,n,r){n[0]==="--"&&(n=n.slice(1));let o=O({profile:Yt(r).profile}),a=(await J(!1)).find(b=>b.labels["com.docker.compose.project"]===t.project&&b.labels["com.docker.compose.service"]===t.service);if(!a)throw new C(
|
|
1293
|
+
`no running container for ${t.project}/${t.service}`);let c=a.networks.find(b=>![o.config.network,o.config.accessNetwork,o.config.controlNetwork].includes(b));if(!c)throw new L(`${t.project}/${t.service} has no private network`);let u=Number(t.port??rX(a.image));if(!u)throw new C("cannot determine the service port","pass --port");let p=await nX(a.id),d={...process.env},f=[],m=["run","--rm","-i",...process.stdin.isTTY&&process.stdout.isTTY?["-t"]:[],"--network",c];e==="psql"&&p.POSTGRES_PASSWORD&&
|
|
1294
|
+
(d.PGPASSWORD=p.POSTGRES_PASSWORD,f.push("-e","PGPASSWORD")),e==="mysql"&&p.MYSQL_PASSWORD&&(d.MYSQL_PWD=p.MYSQL_PASSWORD,f.push("-e","MYSQL_PWD"));let h=await tX(r);m.push(...f,h,e),e==="psql"&&m.push("-h",t.service,"-p",String(u),...t.user??p.POSTGRES_USER?["-U",t.user??p.POSTGRES_USER]:[],...t.database??p.POSTGRES_DB?["-d",t.database??p.POSTGRES_DB]:[]),e==="mysql"&&m.push("-h",t.service,"-P",String(u),...t.user??p.MYSQL_USER?["-u",t.user??p.MYSQL_USER]:[],...t.database??p.MYSQL_DATABASE?[t.database??
|
|
1295
1295
|
p.MYSQL_DATABASE]:[]),e==="redis-cli"&&m.push("-h",t.service,"-p",String(u)),m.push(...n),await _("docker",m,{env:d,stdio:"inherit"})}i(Gp,"clientExec");async function zN(e,t){await Pi({project:e.project,service:e.service??"postgres",port:e.port,localPort:e.localPort},t)}i(zN,"dbOpen");async function FN(e,t){await Pi({project:e.project,service:e.service??"redis",port:e.port,localPort:e.localPort},t)}i(FN,"redisOpen");async function mw(e,t){await ru(void 0,{project:e.project},t)}i(mw,"clientClose");
|
|
1296
1296
|
async function BN(e,t){let n=e.service??"postgres",r=(await J()).find(c=>c.labels["portta.component"]==="access-bridge"&&c.labels["portta.access.project"]===e.project&&c.labels["portta.access.service"]===n);if(!r)throw new C(`no bridge is open for ${e.project}/${n}`);let o=r.ports.find(c=>c.publicPort!==null);if(!o?.publicPort)throw new L("bridge has no host port");let s=r.labels["portta.access.kind"],a=s==="postgres"?`postgresql://<user>@127.0.0.1:${o.publicPort}/<database>`:s==="mysql"?`mysql:\
|
|
1297
1297
|
//<user>@127.0.0.1:${o.publicPort}/<database>`:s==="redis"?`redis://127.0.0.1:${o.publicPort}`:`127.0.0.1:${o.publicPort}`;new T(Yt(t)).data(a)}i(BN,"dbUrl");function Wp(e){let t=O({profile:Yt(e).profile});return{path:Mt(t.root),root:t.root}}i(Wp,"panelDatabase");async function UN(e){let t=await pw(O({profile:Yt(e).profile})),n=new T(Yt(e));n.json?n.data(t):t.applied.length===0?n.line(`no pending migrations (${t.migrations.length} applied)`):n.line(`applied ${t.applied.join(", ")}`)}i(UN,"dbMigr\
|
|
1298
|
-
ate");function qN(e){let{path:t}=Wp(e),n=rr(t).filter(a=>Aa(a)),r=n.reduce((a,c)=>a+
|
|
1298
|
+
ate");function qN(e){let{path:t}=Wp(e),n=rr(t).filter(a=>Aa(a)),r=n.reduce((a,c)=>a+Y7(c).size,0),o={state:Aa(t)?"ready":"absent",path:t,files:n.map(a=>X7(a)),bytes:r},s=new T(Yt(e));if(s.json?s.data(o):s.line(`Panel database: ${o.state}
|
|
1299
1299
|
File: ${t}
|
|
1300
1300
|
Size: ${r} bytes across ${n.length} file(s)`),o.state!=="ready")throw new L("the panel database does not exist yet","run portta web up; the panel creates it on first boot")}i(qN,"dbStatus");async function HN(){let e=await _("sh",["-c","command -v sqlite3"],{reject:!1}),t=e.stdout.trim();if(e.exitCode!==0||!t)throw new L("sqlite3 is not installed on this host","install it (macOS ships it; apt install sqlite3, apk add sqlite) and try again");return t}i(HN,"sqlite3");async function ZN(e){if(!process.
|
|
1301
1301
|
stdin.isTTY||!process.stdout.isTTY)throw new L("db shell needs an interactive terminal");let{path:t}=Wp(e);if(!Aa(t))throw new L(`no panel database at ${t}`,"run portta web up");await _(await HN(),[t],{stdio:"inherit"})}i(ZN,"dbShell");async function GN(e,t){let{path:n}=Wp(t);if(!Aa(n))throw new L(`no panel database at ${n}`,"run portta web up");let r=e??`portta-${new Date().toISOString().replaceAll(/[:.]/g,"-")}.db`;await _(await HN(),[n,`.backup '${r.replaceAll("'","''")}'`],{stdio:"inherit"}),
|
|
1302
|
-
new T(Yt(t)).progress(`panel database written to ${r}`)}i(GN,"dbDump");async function WN(e,t){if(!Aa(e))throw new C(`backup not found: ${e}`);let{path:n}=Wp(t);if((await J()).some(o=>o.labels["portta.component"]==="web"&&o.state==="running"))throw new L("the panel is running, and replacing its database under it would corrupt what it has open","portta web down then run this again, then portta web up");await et(`replace ${n} with ${e}? The current panel data is discarded.`,Yt(t).yes===!0),
|
|
1303
|
-
n),{recursive:!0});for(let o of rr(n))
|
|
1302
|
+
new T(Yt(t)).progress(`panel database written to ${r}`)}i(GN,"dbDump");async function WN(e,t){if(!Aa(e))throw new C(`backup not found: ${e}`);let{path:n}=Wp(t);if((await J()).some(o=>o.labels["portta.component"]==="web"&&o.state==="running"))throw new L("the panel is running, and replacing its database under it would corrupt what it has open","portta web down then run this again, then portta web up");await et(`replace ${n} with ${e}? The current panel data is discarded.`,Yt(t).yes===!0),K7(Q7(
|
|
1303
|
+
n),{recursive:!0});for(let o of rr(n))J7(o,{force:!0});V7(e,n),new T(Yt(t)).progress(`panel database restored from ${e}`)}i(WN,"dbRestore");import{join as VN}from"node:path";function Oa(e){return e.optsWithGlobals()}i(Oa,"globals");var hw={"panel.access":{key:"PORTTA_WEB_EXPOSE",description:"how the panel is reached",allowed:Kr},"panel.port":{key:"PORTTA_WEB_PORT",description:"host port the panel answers on"},"panel.auth":{key:"PORTTA_AUTH_MODE",description:"whether the panel asks who you are",allowed:["disabled","required"]},"panel.host":{key:"PORTTA_PANEL_ADVERTISED_HOST",description:"hostname the panel answers on, and the address a human types"},"panel.readOnly":{
|
|
1304
1304
|
key:"PORTTA_WEB_READ_ONLY",description:"refuse every mutating panel endpoint",allowed:["true","false"]},"panel.image":{key:"PORTTA_WEB_IMAGE",description:"published panel image"},"gateway.profile":{key:"PORTTA_PROFILE",description:"local, remote-private or remote-public",allowed:["local","remote-private","remote-public"]},"domain.mode":{key:"PORTTA_DOMAIN_MODE",description:"how project hostnames get their base domain",allowed:Ga},"domain.provider":{key:"PORTTA_AUTO_DOMAIN_PROVIDER",description:"\
|
|
1305
1305
|
wildcard DNS service used by the auto mode",allowed:Wd},"domain.publicIp":{key:"PORTTA_PUBLIC_IP",description:"address the auto mode builds a hostname from"},"gateway.domain":{key:"PORTTA_DOMAIN",description:"base domain, when the mode is custom"},"gateway.bindAddress":{key:"PORTTA_BIND_ADDRESS",description:"interface Traefik publishes 80/443 on"},"public.domain":{key:"PUBLIC_DOMAIN",description:"public wildcard namespace"},"public.enabled":{key:"PUBLIC_ENABLED",description:"whether HTTP service\
|
|
1306
1306
|
s may be published",allowed:["true","false"]},"private.domain":{key:"PRIVATE_DOMAIN",description:"wildcard namespace served over the VPN"},"tls.enabled":{key:"TLS_ENABLED",description:"serve HTTPS",allowed:["true","false"]},"tls.mode":{key:"TLS_MODE",description:"local certificate authority or ACME",allowed:["local","acme"]},"acme.email":{key:"ACME_EMAIL",description:"contact address for the ACME account"},"acme.challenge":{key:"ACME_CHALLENGE",description:"one wildcard over DNS-01, or one per h\
|
|
1307
1307
|
ostname over HTTP-01",allowed:["dns","http"]},"acme.caServer":{key:"ACME_CA_SERVER",description:"ACME directory URL; point at staging while testing"},"dashboard.enabled":{key:"PORTTA_DASHBOARD",description:"Traefik's own dashboard, on loopback",allowed:["true","false"]},"tcp.enabled":{key:"PORTTA_TCP",description:"route datastores by hostname",allowed:["true","false"]},"tailscale.enabled":{key:"TAILSCALE_ENABLED",description:"run the Tailscale sidecar",allowed:["true","false"]}},gw=new Set(["POR\
|
|
1308
|
-
TTA_AUTH_SECRET","TS_AUTHKEY","CF_DNS_API_TOKEN"]);function KN(e){let t=hw[e];if(!t)throw new C(`unknown setting: ${e}`,`portta config list shows the ${Object.keys(hw).length} settings this understands`);return t}i(KN,"setting");function
|
|
1309
|
-
t);if(o.json){o.data({root:n.root,settings:r});return}for(let s of r)o.line(`${s.setting.padEnd(22)} ${String(s.value).padEnd(24)} ${s.description}`)}i(JN,"configList");async function YN(e,t){let n=Oa(t),r=O({profile:n.profile}),o=KN(e);if(gw.has(o.key))throw new U(`${e} is a secret and is never printed`,"portta doctor reports whether it is set");let s=r.env[o.key]??"",a=new T(n);a.json?a.data({setting:e,variable:o.key,value:s}):a.line(s)}i(YN,"configGet");async function
|
|
1310
|
-
profile:t,overrides:n});r.progress("recreating gateway components"),await _("docker",["compose",...we(o),"up","-d","--remove-orphans","--wait","--wait-timeout","180"],{cwd:o.root,env:o.env,stdio:"inherit"})}i(
|
|
1311
|
-
i(
|
|
1308
|
+
TTA_AUTH_SECRET","TS_AUTHKEY","CF_DNS_API_TOKEN"]);function KN(e){let t=hw[e];if(!t)throw new C(`unknown setting: ${e}`,`portta config list shows the ${Object.keys(hw).length} settings this understands`);return t}i(KN,"setting");function oX(e,t){let n=VN(e,".env");je(n,t)}i(oX,"write");async function JN(e){let t=Oa(e),n=O({profile:t.profile}),r=Object.entries(hw).map(([s,a])=>({setting:s,variable:a.key,value:gw.has(a.key)?n.env[a.key]?"<set>":"":n.env[a.key]??"",description:a.description})),o=new T(
|
|
1309
|
+
t);if(o.json){o.data({root:n.root,settings:r});return}for(let s of r)o.line(`${s.setting.padEnd(22)} ${String(s.value).padEnd(24)} ${s.description}`)}i(JN,"configList");async function YN(e,t){let n=Oa(t),r=O({profile:n.profile}),o=KN(e);if(gw.has(o.key))throw new U(`${e} is a secret and is never printed`,"portta doctor reports whether it is set");let s=r.env[o.key]??"",a=new T(n);a.json?a.data({setting:e,variable:o.key,value:s}):a.line(s)}i(YN,"configGet");async function sX(e,t,n,r){let o=O({root:e,
|
|
1310
|
+
profile:t,overrides:n});r.progress("recreating gateway components"),await _("docker",["compose",...we(o),"up","-d","--remove-orphans","--wait","--wait-timeout","180"],{cwd:o.root,env:o.env,stdio:"inherit"})}i(sX,"apply");async function iX(){for(let e of["https://api.ipify.org","https://ifconfig.me/ip","https://icanhazip.com"])try{let t=await fetch(e,{signal:AbortSignal.timeout(5e3)});if(!t.ok)continue;let n=(await t.text()).trim();if(/^(\d{1,3}\.){3}\d{1,3}$/.test(n))return n}catch{}return null}
|
|
1311
|
+
i(iX,"detectPublicIp");async function aX(e,t,n){if(!Gd(t))throw new C(`domain.mode must be one of: ${Ga.join(", ")}`);let r=O({root:e}),o={PORTTA_DOMAIN_MODE:t};if(t==="auto"){n.progress("detecting this host's public address");let s=await iX()??r.env.PORTTA_PUBLIC_IP??null;if(!s)throw new L("no public address could be detected for this host","set it yourself: portta config set domain.publicIp <address>");o.PORTTA_PUBLIC_IP=s;let a=r.env.PORTTA_AUTO_DOMAIN_PROVIDER,c=Wa(s,a&&Vd(a)?a:"sslip.io");if(!c)
|
|
1312
1312
|
throw new L(`${s} is not an IPv4 address`);o.PORTTA_DOMAIN=c,n.progress(`projects will answer on *.${c}`);for(let u of Uv(c))n.progress(` ${u}`);r.config.bindAddress==="127.0.0.1"&&(n.warning("Traefik still listens on 127.0.0.1, so these names resolve here but nothing answers from outside"),n.hint("portta public enable exposes the HTTP services that opted in"))}if(t==="custom"){let s=r.env.PORTTA_DOMAIN;if(!s||s==="localhost")throw new L("domain mode custom needs a domain","set it first: port\
|
|
1313
|
-
ta config set gateway.domain dev.example.com");n.hint(`*.${s} must resolve to this host; portta dns check confirms it`)}return t==="local"&&(o.PORTTA_DOMAIN="localhost",n.hint("projects will answer on *.localhost, which only resolves on this machine")),o}i(
|
|
1314
|
-
`)[0]?.trim()??"";return e.exitCode===0&&t?t:null}i(
|
|
1313
|
+
ta config set gateway.domain dev.example.com");n.hint(`*.${s} must resolve to this host; portta dns check confirms it`)}return t==="local"&&(o.PORTTA_DOMAIN="localhost",n.hint("projects will answer on *.localhost, which only resolves on this machine")),o}i(aX,"setDomainMode");async function cX(){let e=await _("tailscale",["ip","-4"],{reject:!1}),t=e.stdout.split(`
|
|
1314
|
+
`)[0]?.trim()??"";return e.exitCode===0&&t?t:null}i(cX,"tailscaleAddress");async function lX(e,t,n){if(!kn(t))throw new C(`panel.access must be one of: ${Kr.join(", ")}`);let r=O({root:e}),o={PORTTA_WEB_EXPOSE:t,PORTTA_WEB:"true"},s=r.env.PORTTA_AUTH_MODE==="required";if(!rn(t)&&!s)throw new U(`panel access '${t}' answers whoever finds the address while the panel answers everybody as the local operator`,"portta config set panel.auth required then open /setup to create the owner");if(rn(t)&&!s&&
|
|
1315
1315
|
t!=="local"&&(n.warning(`anybody who reaches the panel over the ${t==="tailscale"?"tailnet":"VPN"} is the local operator`),n.hint("portta config set panel.auth required asks who they are instead")),t==="vpn"&&r.config.profile==="remote-public")throw new U("the panel must not be routed on the tailnet hostname while Traefik binds every interface","portta config set panel.access domain routes it on the gateway's own domain");switch(t){case"public":if(r.config.profile!=="local"&&r.config.tailscaleEnabled)
|
|
1316
1316
|
throw new U("panel access `public` cannot be combined with the Tailscale attachment","use panel.access tailscale, or set tailscale.enabled false");o.PORTTA_WEB_BIND_ADDRESS="0.0.0.0",n.warning("the panel will be reachable from every network this host is on; authentication is enforced by the proxy");break;case"domain":{let a=r.env.PORTTA_PANEL_ADVERTISED_HOST??"";if(!a||a==="localhost"||/^[0-9.]+$/.test(a))throw new U(`panel access 'domain' needs a hostname to route on, and this host advertises ${a||
|
|
1317
|
-
"nothing"}`,"portta config set panel.host portta.example.com");if(!r.config.tlsEnabled)throw new U("a panel routed on the domain would carry its credential in clear text","enable TLS first: portta config set tls.enabled true");o.PORTTA_WEB_BIND_ADDRESS="127.0.0.1",n.warning(`the panel will answer on https://${a}, behind the same login page a protected project gets`);break}case"tailscale":{let a=await
|
|
1318
|
-
up`, then set this again");o.PORTTA_WEB_BIND_ADDRESS=a,o.PORTTA_PANEL_ADVERTISED_HOST=a;break}case"local":o.PORTTA_WEB_BIND_ADDRESS="127.0.0.1",o.PORTTA_PANEL_ADVERTISED_HOST="127.0.0.1";break;case"vpn":o.PORTTA_WEB_BIND_ADDRESS="127.0.0.1";break}return o}i(
|
|
1317
|
+
"nothing"}`,"portta config set panel.host portta.example.com");if(!r.config.tlsEnabled)throw new U("a panel routed on the domain would carry its credential in clear text","enable TLS first: portta config set tls.enabled true");o.PORTTA_WEB_BIND_ADDRESS="127.0.0.1",n.warning(`the panel will answer on https://${a}, behind the same login page a protected project gets`);break}case"tailscale":{let a=await cX();if(!a)throw new L("this host has no Tailscale address","connect it yourself with `tailscale\
|
|
1318
|
+
up`, then set this again");o.PORTTA_WEB_BIND_ADDRESS=a,o.PORTTA_PANEL_ADVERTISED_HOST=a;break}case"local":o.PORTTA_WEB_BIND_ADDRESS="127.0.0.1",o.PORTTA_PANEL_ADVERTISED_HOST="127.0.0.1";break;case"vpn":o.PORTTA_WEB_BIND_ADDRESS="127.0.0.1";break}return o}i(lX,"setPanelAccess");function uX(e,t,n){let r=O({root:e});if(t==="required")return r.env.PORTTA_AUTH_SECRET||n.hint("portta web up generates the session secret; nothing prints it"),{PORTTA_AUTH_MODE:"required"};let o=r.env.PORTTA_WEB_EXPOSE||
|
|
1319
1319
|
"local";if(!kn(o)||!rn(o))throw new U(`the panel is reached over '${o}', which answers whoever finds the address`,`portta config set panel.access <${Xd.join("|")}> then set panel.auth disabled`);let s=r.env.PORTTA_WEB_BIND_ADDRESS||"127.0.0.1";if(o==="local"&&!(s==="127.0.0.1"||s==="localhost"||s==="::1"||s==="[::1]")&&r.env.PORTTA_AUTH_ALLOW_LAN!=="true")throw new U(`the panel is bound to ${s}, so turning the login off offers it to every device on this network`,"set PORTTA_AUTH_ALLOW_LAN=true\
|
|
1320
|
-
in .env to accept that, or portta config set panel.access local");return o!=="local"&&n.warning(`anybody who reaches the panel over the ${o==="tailscale"?"tailnet":"VPN"} is now the local operator`),{PORTTA_AUTH_MODE:"disabled"}}i(
|
|
1321
|
-
includes(t))throw new C(`${e} must be one of: ${c.allowed.join(", ")}`);let u;e==="panel.access"?u=await
|
|
1322
|
-
"nothing was restarted: run portta up to apply it"):await
|
|
1323
|
-
"Users"),
|
|
1324
|
-
|
|
1325
|
-
lastUsedAt:Yn.nullable(),enabled:l.boolean(),user:l.string()}).strict(),"ApiToken"),
|
|
1326
|
-
eatedApiToken"),
|
|
1327
|
-
|
|
1328
|
-
string().min(1).max(64)).max(64).nullable().describe("Null restores the default")}).strict(),"SetAgentPermissions");var
|
|
1329
|
-
"developer"]),sequential:l.boolean(),slugs:l.array(l.string())}),ww=l.object({identity:yw,groups:l.array(
|
|
1320
|
+
in .env to accept that, or portta config set panel.access local");return o!=="local"&&n.warning(`anybody who reaches the panel over the ${o==="tailscale"?"tailnet":"VPN"} is now the local operator`),{PORTTA_AUTH_MODE:"disabled"}}i(uX,"setPanelAuth");async function XN(e,t,n,r){let o=Oa(r),s=new T(o),a=O({profile:o.profile}),c=KN(e);if(gw.has(c.key))throw new U(`${e} is a secret and is not set this way`,"edit .env; portta web up generates PORTTA_AUTH_SECRET when it is empty");if(c.allowed&&!c.allowed.
|
|
1321
|
+
includes(t))throw new C(`${e} must be one of: ${c.allowed.join(", ")}`);let u;e==="panel.access"?u=await lX(a.root,t,s):e==="panel.auth"?u=uX(a.root,t,s):e==="domain.mode"?u=await aX(a.root,t,s):u={[c.key]:t},e==="gateway.domain"&&t&&a.config.domainMode!=="custom"&&(s.hint("domain.mode is not custom, so this value is not in use yet"),s.hint("portta config set domain.mode custom applies it")),oX(a.root,u),e==="panel.access"&&Pa(a.root,a.config.profile),s.progress(`${e} = ${t}`),n.apply===!1?s.hint(
|
|
1322
|
+
"nothing was restarted: run portta up to apply it"):await sX(a.root,o.profile,u,s),s.json&&s.data({setting:e,value:t,applied:n.apply!==!1,changed:u})}i(XN,"configSet");function QN(e){let t=O({profile:Oa(e).profile});xt(VN(t.root,".env")),new T(Oa(e)).progress("configuration prepared from .env.example; existing values preserved")}i(QN,"configPrepare");import{existsSync as kQ,readFileSync as _Q}from"node:fs";import{join as PQ}from"node:path";import{fileURLToPath as EQ,pathToFileURL as AQ}from"node:url";import{gunzipSync as OQ}from"node:zlib";var Ne=i((e,t)=>e.meta({ref:t}),"named"),Yn=l.number().describe("Unix timestamp in seconds"),bw=Ne(l.enum(wo).describe("What this account may do, everywhere"),"Role"),pX=Ne(l.object({id:l.string(),name:l.string(),email:l.string(),role:bw,banned:l.boolean(),banReason:l.string().nullable(),banExpires:Yn.nullable(),twoFactorEnabled:l.boolean(),createdAt:Yn,projects:l.array(l.object({id:l.number(),slug:l.string(),name:l.string()}).strict())}).strict(),"User"),jTe=Ne(l.object({users:l.array(pX)}).strict(),
|
|
1323
|
+
"Users"),ITe=Ne(l.object({name:l.string().min(1).max(120),email:l.email(),password:l.string().min(10).max(128),role:bw.default("viewer"),projects:l.array(l.number().int().positive()).max(200).optional()}).strict(),"CreateUser"),DTe=Ne(l.object({role:bw}).strict(),"SetRole"),NTe=Ne(l.object({password:l.string().min(10).max(128)}).strict(),"SetPassword"),LTe=Ne(l.object({banned:l.boolean(),reason:l.string().max(500).optional(),days:l.number().int().min(1).max(3650).optional()}).strict(),"BanUser"),
|
|
1324
|
+
MTe=Ne(l.object({projects:l.array(l.number().int().positive()).max(200)}).strict(),"SetUserProjects"),dX=Ne(l.object({id:l.string(),createdAt:Yn,expiresAt:Yn,ipAddress:l.string().nullable(),userAgent:l.string().nullable()}).strict(),"UserSession"),zTe=Ne(l.object({sessions:l.array(dX)}).strict(),"UserSessions"),eL=Ne(l.object({id:l.string(),name:l.string(),start:l.string().nullable(),actor:l.string(),actorKind:l.enum(["human","agent"]),scopes:l.array(l.string()),createdAt:Yn,expiresAt:Yn.nullable(),
|
|
1325
|
+
lastUsedAt:Yn.nullable(),enabled:l.boolean(),user:l.string()}).strict(),"ApiToken"),FTe=Ne(l.object({tokens:l.array(eL)}).strict(),"ApiTokens"),BTe=Ne(l.object({name:l.string().min(1).max(80),actorKind:l.enum(["human","agent"]).default("agent"),scopes:l.array(l.string()).max(200).optional(),expiresInDays:l.number().int().min(1).max(365).optional()}).strict(),"CreateApiToken"),UTe=Ne(l.object({token:l.string().describe("The secret. Shown here and nowhere else, ever."),credential:eL}).strict(),"Cr\
|
|
1326
|
+
eatedApiToken"),fX=Ne(l.object({id:l.string(),at:Yn,userId:l.string().nullable(),userEmail:l.string().nullable(),principalKind:l.enum(["local","user","token"]),actor:l.string(),action:l.enum(Fv),resourceType:l.string(),resourceId:l.string().nullable(),resourceName:l.string().nullable(),project:l.string().nullable().describe("Project slug, when the entry is about one"),ipAddress:l.string().nullable(),metadata:l.record(l.string(),l.unknown())}).strict(),"AuditEntry"),qTe=Ne(l.object({entries:l.array(
|
|
1327
|
+
fX),nextBefore:l.string().nullable().describe("Pass as ?before= for the next page")}).strict(),"AuditPage"),HTe=Ne(l.object({permissions:l.array(l.string()).describe("In force right now"),defaults:l.array(l.string()).describe("What an agent holds when nothing is set"),available:l.array(l.string()).describe("Every permission this installation knows"),configured:l.boolean().describe("False when the default is what is in force")}).strict(),"AgentPermissions"),ZTe=Ne(l.object({permissions:l.array(l.
|
|
1328
|
+
string().min(1).max(64)).max(64).nullable().describe("Null restores the default")}).strict(),"SetAgentPermissions");var mX=l.enum(["user","developer","all"]),yw=l.object({version:l.string(),revision:l.string().nullable(),hash:l.string()}),hX=l.object({id:l.string(),text:l.string(),level:l.number().int(),line:l.number().int()}),tL=l.object({slug:l.string(),title:l.string(),description:l.string(),audience:l.enum(["user","developer"]),section:l.string(),category:l.string(),source:l.string(),url:l.string(),kind:l.enum(["markdown","api"])}),gX=l.object({title:l.string(),category:l.string(),audience:l.enum(["user",
|
|
1329
|
+
"developer"]),sequential:l.boolean(),slugs:l.array(l.string())}),ww=l.object({identity:yw,groups:l.array(gX),pages:l.array(tL)}),Vp=l.object({identity:yw,page:tL.extend({markdown:l.string(),headings:l.array(hX)})}),vw=l.object({identity:yw,results:l.array(l.object({slug:l.string(),title:l.string(),description:l.string(),audience:l.enum(["user","developer"]),section:l.string(),category:l.string(),url:l.string(),anchor:l.string().nullable(),excerpt:l.string()}))}),Kp=l.object({audience:mX.default(
|
|
1330
1330
|
"all")}).strict(),Sw=Kp.extend({q:l.string().trim().min(1).max(200),limit:l.coerce.number().int().min(1).max(50).default(10)}),xw=l.object({slug:l.string().regex(/^[a-z0-9]+(?:[/-][a-z0-9]+)*$/),anchor:l.string().min(1).max(300).optional()}).strict();var $=i((e,t)=>e.meta({ref:t}),"named"),ye=l.number().describe("Unix timestamp in seconds"),Jp=$(l.enum(["gateway","integrated","external","standalone"]).describe("How the gateway classifies a container"),"Ownership"),Yp=$(l.object({id:l.string().describe("Stable key used to pick an icon, for example postgres, nginx or docker"),label:l.string().describe("Short human label shown next to the icon")}).strict(),"ServiceTech"),ut=$(l.enum(["created","running","paused","restarting","removing","exited",
|
|
1331
|
-
"dead"]),"ContainerState"),us=$(l.enum(["healthy","unhealthy","starting","none"]),"Health"),rL=$(l.enum(["local","vpn","public"]).describe("Where a routed URL can be reached from"),"UrlScope"),Xp=$(l.enum(["internal","local","lan","private","protected","public"]).describe("Who can reach an endpoint"),"EndpointScope"),
|
|
1331
|
+
"dead"]),"ContainerState"),us=$(l.enum(["healthy","unhealthy","starting","none"]),"Health"),rL=$(l.enum(["local","vpn","public"]).describe("Where a routed URL can be reached from"),"UrlScope"),Xp=$(l.enum(["internal","local","lan","private","protected","public"]).describe("Who can reach an endpoint"),"EndpointScope"),bX=$(l.enum(["starttls-sni","tls-sni","unsupported","unevaluated"]).describe("Whether a TCP protocol can be told apart by hostname on a shared port"),"TcpRouting"),Dr=$(l.enum(["htt\
|
|
1332
1332
|
p","postgres","mysql","redis","mongodb","memcached","search","amqp","clickhouse","smtp","tcp","worker"]),"ServiceKind"),Qp=$(l.object({ip:l.string(),hostPort:l.number().int(),containerPort:l.number().int(),protocol:l.string()}).strict(),"PublishedPort"),Ta=$(l.object({url:l.string().describe("Absolute URL served by Traefik"),host:l.string(),scope:rL,scheme:l.enum(["http","https"])}).strict(),"RouteUrl"),oL=$(l.object({type:l.string(),name:l.string().nullable(),source:l.string(),destination:l.string(),
|
|
1333
|
-
rw:l.boolean()}).strict(),"MountSummary"),
|
|
1334
|
-
hidden:l.boolean().optional()}).strict(),"ServiceOverrides"),
|
|
1333
|
+
rw:l.boolean()}).strict(),"MountSummary"),yX=$(l.object({displayName:l.string().optional(),description:l.string().optional(),color:l.string().optional(),pinned:l.boolean().optional(),archived:l.boolean().optional(),primaryService:l.string().optional(),hiddenServices:l.array(l.string()).optional(),serviceOrder:l.array(l.string()).optional()}).strict(),"EnvironmentOverrides"),kw=$(l.object({alias:l.string().optional().describe("An additional hostname, routed by Traefik"),note:l.string().optional(),
|
|
1334
|
+
hidden:l.boolean().optional()}).strict(),"ServiceOverrides"),wX=$(l.object({id:l.string().describe("Docker container id"),name:l.string(),image:l.string(),state:ut,status:l.string(),health:us,createdAt:ye,startedAt:ye.nullable(),uptimeSeconds:l.number().nullable(),ownership:Jp,gatewayComponent:l.string().nullable(),environment:l.string().nullable().describe("Environment key (COMPOSE_PROJECT_NAME on this Node)"),service:l.string().nullable().describe("Compose service name"),workingDir:l.string().
|
|
1335
1335
|
nullable(),namespace:l.string().nullable(),group:l.string().nullable().describe("Optional portta.project logical project label"),networks:l.array(l.string()),onGatewayNetwork:l.boolean(),traefikEnabled:l.boolean(),ports:l.array(Qp),exposedPorts:l.array(l.number().int()),kind:Dr,tech:Yp,urls:l.array(Ta),mounts:l.array(oL),labels:l.record(l.string(),l.string()),restartCount:l.number().int(),exitCode:l.number().int().nullable(),oneOff:l.boolean().describe("A docker compose run container: it belongs\
|
|
1336
|
-
to the environment but is not one of its services"),completed:l.boolean().describe("Exited 0 with no restart policy: a one-shot that did its job, not a service that is down"),overrides:kw.optional().describe("Absent when nothing was overridden")}).strict(),"ContainerSummary"),
|
|
1337
|
-
nullable(),configFiles:l.array(l.string())}).strict(),"EnvironmentOperable"),
|
|
1338
|
-
{ok:l.boolean().describe("True only when every requested step succeeded or was skipped"),project:l.string(),action:l.enum(["start","stop","restart"]),requested:l.number().int(),succeeded:l.number().int(),failed:l.number().int(),skipped:l.number().int(),results:l.array(
|
|
1339
|
-
string())}).strict(),"EnvironmentPorttaRecords"),
|
|
1340
|
-
object({name:l.string().describe("COMPOSE_PROJECT_NAME; the Environment key on this Node"),presence:l.enum(["live","remembered"]).describe("live: it has containers on this Node. remembered: the panel saw it once and kept where it ran; it can be started through the runner, or forgotten"),integrated:l.boolean(),workingDir:l.string().nullable(),operable:
|
|
1341
|
-
eds the runner"),namespace:l.string().nullable(),group:l.string().nullable().describe("Optional portta.project label; a hint, not a Project"),services:l.array(
|
|
1342
|
-
uptimeSeconds:l.number().nullable(),overrides:
|
|
1343
|
-
l","escaped","missing","inaccessible"]).describe("Where this Project sits relative to Projects Home"),"ProjectLocation"),
|
|
1344
|
-
"ProjectEnvironment"),iL=$(l.object({key:l.string().max(32),value:l.string().min(1).max(64)}).strict(),"ProjectTag"),
|
|
1345
|
-
runningCount:l.number().int(),unhealthyCount:l.number().int()}).strict())}).strict(),"ProjectSummary"),
|
|
1346
|
-
l.string()),middlewares:l.array(l.string()),service:l.string(),provider:l.string(),status:l.string().describe("Traefik verdict: enabled, disabled or warning"),errors:l.array(l.string()).describe("Traefik error text when it rejected the router"),servers:l.array(l.string()).describe("Backends Traefik resolved for this router")}).strict(),"TraefikRouter"),
|
|
1347
|
-
string().nullable(),routers:l.array(aL),fetchedAt:ye}).strict(),"TraefikVerdict"),
|
|
1348
|
-
{id:l.string(),project:l.string(),service:l.string(),container:l.string().describe("Unique container name used as the Traefik backend"),port:l.number().int(),host:l.string(),url:l.string(),mode:
|
|
1349
|
-
d host. Never a password or a hash."),project:l.string().nullable(),service:l.string().nullable(),label:l.string()}).strict(),"ExposureEntry"),
|
|
1350
|
-
on names that cannot be listed. Any of them means no address on this host can be called protected.")}).strict(),"ExposureView"),
|
|
1351
|
-
"AI crawlers that collect text to train models, such as GPTBot and ClaudeBot"),live:l.boolean().describe("AI agents that read a page because a person asked, such as ChatGPT-User"),preview:l.boolean().describe("Link previews in chats and social networks, such as Slackbot")}).strict().describe("Which kinds of crawler may read a hostname. true lets that kind in."),"CrawlerPolicy"),
|
|
1352
|
-
lt."),exceptions:l.array(l.object({project:l.string().describe("The slug of the project"),name:l.string(),policy:ls.nullable().describe("Null when the environments of the project disagree"),mixed:l.boolean().describe("True when the environments of the project do not all follow the same exception")}).strict()).describe("Only the projects this caller may see, including the ones whose environments disagree")}).strict(),"CrawlerSettings"),
|
|
1353
|
-
ception set for this project, or null when it follows the default"),effective:ls,mixed:l.boolean().describe("True when the environments of this project do not all have the same exception"),byEnvironment:l.record(l.string(),ls).describe("What each environment follows, which decides the verdict of each of its addresses")}).strict(),"ProjectCrawlers"),
|
|
1354
|
-
nullable(),status:l.enum(["M","A","D","U"]).nullable().describe("Against the last commit; U is not tracked yet"),ignored:l.boolean().describe("Listed because git ignores it, such as node_modules. Never read."),readable:l.enum(["text","hidden","binary","large","omitted"]).describe("hidden: usually holds a secret, so only its existence is shown"),diff:l.boolean().describe("Whether there are changes to show against the last commit")}).strict(),"ProjectFile"),
|
|
1355
|
-
describe("The environments of this project that have a copy of their files"),environment:l.string().nullable(),branch:l.string().nullable(),head:l.object({hash:l.string(),subject:l.string(),at:l.number().int()}).strict().nullable(),changed:l.number().int(),untracked:l.number().int(),ahead:l.number().int().nullable(),collectedAt:l.number().int().nullable(),truncated:l.boolean().describe("The project is bigger than the copy: the changed files come first"),files:l.array(
|
|
1356
|
-
View"),
|
|
1357
|
-
ta overlay"),planned:l.boolean().describe("Whether a plan can be reviewed"),registered:l.boolean().describe("A project already has this folder")}).strict(),"DiscoveredFolder"),
|
|
1336
|
+
to the environment but is not one of its services"),completed:l.boolean().describe("Exited 0 with no restart policy: a one-shot that did its job, not a service that is down"),overrides:kw.optional().describe("Absent when nothing was overridden")}).strict(),"ContainerSummary"),vX=$(l.object({ok:l.boolean().describe("Whether Compose can be driven for this project from the labels Docker recorded"),reason:l.string().nullable().describe("Why it is not operable, when it is not"),workingDir:l.string().
|
|
1337
|
+
nullable(),configFiles:l.array(l.string())}).strict(),"EnvironmentOperable"),SX=$(l.object({ok:l.boolean().describe("Whether start can run by iterating the containers that still exist"),reason:l.string().nullable(),via:l.enum(["iteration","runner"]).nullable()}).strict(),"EnvironmentStartable"),xX=$(l.object({service:l.string(),containerId:l.string(),action:l.enum(["start","stop"]),ok:l.boolean(),skipped:l.boolean(),error:l.string().nullable()}).strict(),"EnvironmentActionEntry"),n$e=$(l.object(
|
|
1338
|
+
{ok:l.boolean().describe("True only when every requested step succeeded or was skipped"),project:l.string(),action:l.enum(["start","stop","restart"]),requested:l.number().int(),succeeded:l.number().int(),failed:l.number().int(),skipped:l.number().int(),results:l.array(xX)}).strict(),"EnvironmentActionResult"),sL=$(l.object({overrides:l.number().int(),aliases:l.number().int(),projectLinks:l.number().int(),accessBridges:l.array(l.string()),accessForwarders:l.array(l.string()),accessFiles:l.array(l.
|
|
1339
|
+
string())}).strict(),"EnvironmentPorttaRecords"),r$e=$(l.object({environment:l.string(),containers:l.array(l.object({id:l.string(),name:l.string(),service:l.string().nullable(),state:ut,image:l.string()}).strict()),networks:l.array(l.string()),volumes:l.array(l.object({name:l.string(),sizeBytes:l.number().nullable().describe("Null: the panel has no volume inspect")}).strict()),workingDir:l.string().nullable(),records:sL,runnerAvailable:l.boolean()}).strict(),"EnvironmentRemovalPreview"),o$e=$(l.
|
|
1340
|
+
object({name:l.string().describe("COMPOSE_PROJECT_NAME; the Environment key on this Node"),presence:l.enum(["live","remembered"]).describe("live: it has containers on this Node. remembered: the panel saw it once and kept where it ran; it can be started through the runner, or forgotten"),integrated:l.boolean(),workingDir:l.string().nullable(),operable:vX.describe("Whether the runner can find this environment on the host"),startable:SX.describe("Whether start can iterate existing containers, or ne\
|
|
1341
|
+
eds the runner"),namespace:l.string().nullable(),group:l.string().nullable().describe("Optional portta.project label; a hint, not a Project"),services:l.array(wX),serviceCount:l.number().int(),runningCount:l.number().int(),completedCount:l.number().int().optional().describe("Services that exited 0 with no restart policy; they count as fine, not as down"),healthyCount:l.number().int(),unhealthyCount:l.number().int(),networks:l.array(l.string()),urls:l.array(Ta),scopes:l.array(rL),startedAt:ye.nullable(),
|
|
1342
|
+
uptimeSeconds:l.number().nullable(),overrides:yX.optional().describe("Absent when nothing was overridden"),location:l.enum(["managed","external","escaped","missing","inaccessible"]).optional()}).strict(),"Environment"),kX=$(l.enum(["manual","label","path"]).describe("Why this environment belongs to this Project"),"AdoptionSource"),_X=$(l.enum(["resolved","conflict","ambiguous","unattributed"]).describe("How sure the panel is of an association"),"AttributionState"),_w=$(l.enum(["managed","externa\
|
|
1343
|
+
l","escaped","missing","inaccessible"]).describe("Where this Project sits relative to Projects Home"),"ProjectLocation"),s$e=_w.options,PX=$(l.object({environment:l.string().describe("COMPOSE_PROJECT_NAME, the Environment key"),source:kX,attribution:_X.optional(),running:l.boolean(),serviceCount:l.number().int(),runningCount:l.number().int(),completedCount:l.number().int().optional().describe("Services that exited 0 with no restart policy"),unhealthyCount:l.number().int(),urls:l.array(Ta)}).strict(),
|
|
1344
|
+
"ProjectEnvironment"),iL=$(l.object({key:l.string().max(32),value:l.string().min(1).max(64)}).strict(),"ProjectTag"),i$e=$(l.object({id:l.string(),slug:l.string(),name:l.string(),description:l.string().nullable(),archived:l.boolean(),relativePath:l.string().nullable(),location:_w,tags:l.array(iL),environmentCount:l.number().int(),runningEnvironmentCount:l.number().int(),environments:l.array(l.object({name:l.string().describe("COMPOSE_PROJECT_NAME"),running:l.boolean(),serviceCount:l.number().int(),
|
|
1345
|
+
runningCount:l.number().int(),unhealthyCount:l.number().int()}).strict())}).strict(),"ProjectSummary"),a$e=$(l.object({id:l.string(),slug:l.string(),name:l.string(),description:l.string().nullable(),archived:l.boolean(),relativePath:l.string().nullable(),resolvedPath:l.string().nullable(),location:_w,tags:l.array(iL),environments:l.array(PX)}).strict(),"Project"),aL=$(l.object({name:l.string(),rule:l.string(),hosts:l.array(l.string()).describe("Every Host rule name, lowercased"),entryPoints:l.array(
|
|
1346
|
+
l.string()),middlewares:l.array(l.string()),service:l.string(),provider:l.string(),status:l.string().describe("Traefik verdict: enabled, disabled or warning"),errors:l.array(l.string()).describe("Traefik error text when it rejected the router"),servers:l.array(l.string()).describe("Backends Traefik resolved for this router")}).strict(),"TraefikRouter"),c$e=$(l.object({available:l.boolean().describe("False when the API is off or unreachable"),reason:l.string().nullable(),baseUrl:l.string(),dashboardUrl:l.
|
|
1347
|
+
string().nullable(),routers:l.array(aL),fetchedAt:ye}).strict(),"TraefikVerdict"),l$e=$(l.object({containerId:l.string(),available:l.boolean(),reason:l.string().nullable(),expectedHosts:l.array(l.string()).describe("Hostnames derived from labels, for comparison"),routers:l.array(aL.extend({dashboardUrl:l.string().nullable()}).strict()),fetchedAt:ye}).strict(),"ServiceTraefik"),EX=$(l.enum(["public","protected"]),"ShareMode"),AX=$(l.enum(["active","expired","dangling"]),"ShareState"),OX=$(l.object(
|
|
1348
|
+
{id:l.string(),project:l.string(),service:l.string(),container:l.string().describe("Unique container name used as the Traefik backend"),port:l.number().int(),host:l.string(),url:l.string(),mode:EX,user:l.string().nullable().describe("Username for a protected share; never a password"),createdAt:ye,expiresAt:ye,expiresInSeconds:l.number(),state:AX}).strict(),"Share"),cL=$(l.object({host:l.string(),mode:l.enum(["protected","public"]),user:l.string().nullable().describe("The login name of a protecte\
|
|
1349
|
+
d host. Never a password or a hash."),project:l.string().nullable(),service:l.string().nullable(),label:l.string()}).strict(),"ExposureEntry"),u$e=$(l.object({enforced:l.boolean().describe("True on a public host: a hostname with no entry is closed. Elsewhere protection is optional."),entries:l.array(cL),openRouters:l.object({count:l.number().int(),names:l.array(l.string()).describe("Only those this caller may see; count is the whole host.")}).strict().describe("Containers answering with no login\
|
|
1350
|
+
on names that cannot be listed. Any of them means no address on this host can be called protected.")}).strict(),"ExposureView"),p$e=$(l.object({ok:l.literal(!0),entry:cL.nullable().describe("Null once the entry was removed"),password:l.string().optional().describe("Shown once, when a credential was generated. Only its hash is stored."),note:l.string()}).strict(),"ExposureResult"),ls=$(l.object({search:l.boolean().describe("Search engines such as Googlebot and Bingbot"),train:l.boolean().describe(
|
|
1351
|
+
"AI crawlers that collect text to train models, such as GPTBot and ClaudeBot"),live:l.boolean().describe("AI agents that read a page because a person asked, such as ChatGPT-User"),preview:l.boolean().describe("Link previews in chats and social networks, such as Slackbot")}).strict().describe("Which kinds of crawler may read a hostname. true lets that kind in."),"CrawlerPolicy"),d$e=$(l.object({default:ls.describe("What every project follows unless it has an exception. Everything blocked by defau\
|
|
1352
|
+
lt."),exceptions:l.array(l.object({project:l.string().describe("The slug of the project"),name:l.string(),policy:ls.nullable().describe("Null when the environments of the project disagree"),mixed:l.boolean().describe("True when the environments of the project do not all follow the same exception")}).strict()).describe("Only the projects this caller may see, including the ones whose environments disagree")}).strict(),"CrawlerSettings"),f$e=$(l.object({default:ls,own:ls.nullable().describe("The ex\
|
|
1353
|
+
ception set for this project, or null when it follows the default"),effective:ls,mixed:l.boolean().describe("True when the environments of this project do not all have the same exception"),byEnvironment:l.record(l.string(),ls).describe("What each environment follows, which decides the verdict of each of its addresses")}).strict(),"ProjectCrawlers"),TX=$(l.object({path:l.string().describe("Relative to the project folder, with forward slashes"),kind:l.enum(["file","dir","link"]),size:l.number().int().
|
|
1354
|
+
nullable(),status:l.enum(["M","A","D","U"]).nullable().describe("Against the last commit; U is not tracked yet"),ignored:l.boolean().describe("Listed because git ignores it, such as node_modules. Never read."),readable:l.enum(["text","hidden","binary","large","omitted"]).describe("hidden: usually holds a secret, so only its existence is shown"),diff:l.boolean().describe("Whether there are changes to show against the last commit")}).strict(),"ProjectFile"),m$e=$(l.object({environments:l.array(l.string()).
|
|
1355
|
+
describe("The environments of this project that have a copy of their files"),environment:l.string().nullable(),branch:l.string().nullable(),head:l.object({hash:l.string(),subject:l.string(),at:l.number().int()}).strict().nullable(),changed:l.number().int(),untracked:l.number().int(),ahead:l.number().int().nullable(),collectedAt:l.number().int().nullable(),truncated:l.boolean().describe("The project is bigger than the copy: the changed files come first"),files:l.array(TX)}).strict(),"ProjectFiles\
|
|
1356
|
+
View"),h$e=$(l.object({environment:l.string(),path:l.string(),content:l.string(),diff:l.string().nullable().describe("The changes against the last commit, as a patch")}).strict(),"ProjectFileContent"),$X=$(l.object({path:l.string().describe("Relative to Projects Home, with forward slashes"),composeFile:l.string(),services:l.number().int().nullable().describe("Null until the collector has analysed the folder"),modifiedAt:l.number().int(),adopted:l.boolean().describe("The folder already has a Port\
|
|
1357
|
+
ta overlay"),planned:l.boolean().describe("Whether a plan can be reviewed"),registered:l.boolean().describe("A project already has this folder")}).strict(),"DiscoveredFolder"),g$e=$(l.object({home:l.string().nullable().describe("Projects Home as the host has it, or null when nothing was published"),collectedAt:l.number().int().nullable(),folders:l.array($X)}).strict(),"DiscoveredFoldersView"),b$e=$(l.object({home:l.string().describe("Projects Home as the host has it, which the command is written\
|
|
1358
1358
|
against"),path:l.string(),composeFile:l.string(),project:l.object({name:l.string(),source:l.string()}).strict(),domain:l.string(),adopted:l.boolean(),services:l.array(l.object({name:l.string(),image:l.string().nullable(),kind:l.string(),port:l.string().nullable().describe("The port Portta would route to, for a service that speaks HTTP"),publishedPorts:l.array(l.object({host:l.string(),container:l.string()}).strict()),containerName:l.string().nullable()}).strict()),findings:l.object({publishedHostPorts:l.
|
|
1359
1359
|
array(l.string()),fixedContainerNames:l.array(l.string()),publishedDatastores:l.array(l.string()),implicitNamespace:l.boolean(),containerNameCollisions:l.array(l.object({service:l.string(),containerName:l.string(),usedBy:l.string()}).strict()),namespaceInUse:l.object({project:l.string(),workingDirs:l.array(l.string())}).strict().nullable()}).strict(),collectedAt:l.number().int(),command:l.string().describe("The terminal command that adopts this folder, with nothing decided yet")}).strict(),"Fold\
|
|
1360
|
-
erPlanView"),
|
|
1361
|
-
category:l.enum(["infrastructure","development","agents","security"]).optional(),details:l.array(l.object({status:l.enum(["pass","info","warn","fail"]),text:l.string()}).strict()).optional(),tool:l.object({installed:l.boolean(),version:l.string().nullable(),path:l.string().nullable(),minimum:l.string().optional(),recommended:l.string().optional()}).strict().optional(),rationale:l.string().optional(),docs:l.string().optional()}).strict(),"Diagnostic")
|
|
1362
|
-
nullable(),durationMs:l.number().int().nonnegative().nullable(),ageSeconds:l.number().int().nonnegative().nullable(),stale:l.boolean(),checks:l.array(
|
|
1363
|
-
{enabled:l.boolean(),running:l.boolean(),hostname:l.string()}).strict(),
|
|
1364
|
-
string(),scope:Xp,usable:l.boolean(),shareable:l.boolean(),problem:l.string().nullable()}).strict())}).strict(),nL=l.object({containerId:l.string().nullable(),state:ut.or(l.literal("absent")),health:us}).strict(),
|
|
1365
|
-
string(),privateDomain:l.string().nullable(),publicDomain:l.string().nullable(),bindAddress:l.string(),httpPort:l.string(),httpsPort:l.string(),scheme:l.enum(["http","https"]),up:l.boolean(),reachable:l.boolean(),tls:
|
|
1366
|
-
{one:l.number(),five:l.number(),fifteen:l.number()}).strict(),
|
|
1367
|
-
number().int().nullable()}).strict(),"HostBatteryInfo"),
|
|
1368
|
-
hassis, hypervisor flag and battery; null when none of them say"),architecture:Re,virtual:l.boolean().nullable(),platform:Re,distro:Re,version:Re,release:Re,kernel:Re,uptimeSeconds:Y,timezone:Re.optional().describe("The IANA zone the server clock is set to; absent in readings from an older collector"),utcOffsetMinutes:Y.optional().describe("Minutes east of UTC when the reading was taken"),cpu:
|
|
1369
|
-
cpuUtilisation:Y,cpuIdle:Y,load:pL.nullable(),storage:
|
|
1370
|
-
service:Re,cpuUtilisation:Y,memoryUsedBytes:Y,memoryLimitBytes:Y,memoryUsedPercent:Y,networkRxBytes:Y,networkTxBytes:Y,blockReadBytes:Y,blockWriteBytes:Y,pids:l.number().int().nullable()}).strict(),"ContainerResourceMetrics"),
|
|
1360
|
+
erPlanView"),y$e=$(l.object({shares:l.array(OX),domain:l.string().describe("The domain share hostnames sit under, one label deep: <project>-<service>-<id>-share.<domain>"),publicAllowed:l.boolean().describe("Whether a public share would be accepted"),maxTtlSeconds:l.number().int()}).strict(),"ShareView"),ed=$(l.object({id:l.string(),status:l.enum(["pass","info","warn","fail"]),title:l.string(),detail:l.string(),fix:l.string(),params:l.record(l.string(),l.union([l.string(),l.number()])).optional(),
|
|
1361
|
+
category:l.enum(["infrastructure","development","agents","security"]).optional(),details:l.array(l.object({status:l.enum(["pass","info","warn","fail"]),text:l.string()}).strict()).optional(),tool:l.object({installed:l.boolean(),version:l.string().nullable(),path:l.string().nullable(),minimum:l.string().optional(),recommended:l.string().optional()}).strict().optional(),rationale:l.string().optional(),docs:l.string().optional()}).strict(),"Diagnostic"),CX=ed,lL=l.object({version:l.literal(1),collectedAt:ye.
|
|
1362
|
+
nullable(),durationMs:l.number().int().nonnegative().nullable(),ageSeconds:l.number().int().nonnegative().nullable(),stale:l.boolean(),checks:l.array(CX),summary:l.object({passed:l.number().int().nonnegative(),recommendations:l.number().int().nonnegative(),problems:l.number().int().nonnegative(),information:l.number().int().nonnegative(),ok:l.boolean()}).strict()}).strict(),w$e=$(lL,"EnvironmentReport"),v$e=$(lL,"SecurityReport"),RX=l.object({enabled:l.boolean(),mode:l.string()}).strict(),jX=l.object(
|
|
1363
|
+
{enabled:l.boolean(),running:l.boolean(),hostname:l.string()}).strict(),IX=l.object({enabled:l.boolean(),domain:l.string().nullable()}).strict(),DX=l.object({expose:l.string(),routed:l.boolean(),auth:l.string(),authenticated:l.boolean(),readOnly:l.boolean(),docs:l.boolean()}).strict(),NX=l.object({enabled:l.boolean(),bindAddress:l.string(),port:l.string(),expose:l.literal("local"),advertisedHost:l.string().nullable(),authenticated:l.boolean(),endpoints:l.array(l.object({provider:l.string(),url:l.
|
|
1364
|
+
string(),scope:Xp,usable:l.boolean(),shareable:l.boolean(),problem:l.string().nullable()}).strict())}).strict(),nL=l.object({containerId:l.string().nullable(),state:ut.or(l.literal("absent")),health:us}).strict(),LX=l.object({containerId:l.string().nullable(),state:ut.or(l.literal("absent"))}).strict(),MX=l.object({name:l.string(),exists:l.boolean(),attached:l.number().int(),internal:l.boolean()}).strict(),uL=$(l.object({gatewayVersion:l.string(),panelVersion:l.string(),profile:l.string(),domain:l.
|
|
1365
|
+
string(),privateDomain:l.string().nullable(),publicDomain:l.string().nullable(),bindAddress:l.string(),httpPort:l.string(),httpsPort:l.string(),scheme:l.enum(["http","https"]),up:l.boolean(),reachable:l.boolean(),tls:RX,tailscale:jX,publicAccess:IX,panel:DX.describe("Panel exposure and authentication without the secret hash"),dashboard:NX,traefik:nL,socketProxy:LX,database:nL,network:MX,routes:l.number().int()}).strict(),"GatewayStatus"),Y=l.number().nullable(),Re=l.string().nullable(),pL=l.object(
|
|
1366
|
+
{one:l.number(),five:l.number(),fifteen:l.number()}).strict(),zX=$(l.object({manufacturer:Re,brand:Re,physicalCores:l.number().int().nullable(),logicalCores:l.number().int().nullable(),speed:Y,speedMax:Y}).strict(),"HostCpuInfo"),FX=$(l.object({vendor:Re,model:l.string(),vramBytes:Y,utilisation:Y,temperature:Y}).strict(),"HostGpuInfo"),BX=$(l.object({hasBattery:l.literal(!0),percent:Y.describe("0-1"),charging:l.boolean(),acConnected:l.boolean(),minutesRemaining:l.number().int().nullable(),cycleCount:l.
|
|
1367
|
+
number().int().nullable()}).strict(),"HostBatteryInfo"),UX=$(l.object({path:l.string(),mount:Re,filesystem:Re,totalBytes:l.number(),usedBytes:l.number(),availableBytes:l.number(),usedPercent:l.number()}).strict(),"HostStorageInfo"),qX=l.enum(["notebook","desktop","server","vm"]),HX=$(l.object({hostname:Re,manufacturer:Re,model:Re,productName:Re.describe("The commercial name, where the platform reports a trustworthy one (macOS so far)"),kind:qX.nullable().describe("What the machine is, from its c\
|
|
1368
|
+
hassis, hypervisor flag and battery; null when none of them say"),architecture:Re,virtual:l.boolean().nullable(),platform:Re,distro:Re,version:Re,release:Re,kernel:Re,uptimeSeconds:Y,timezone:Re.optional().describe("The IANA zone the server clock is set to; absent in readings from an older collector"),utcOffsetMinutes:Y.optional().describe("Minutes east of UTC when the reading was taken"),cpu:zX,memoryTotalBytes:Y,memoryUsedBytes:Y,memoryAvailableBytes:Y,memoryUsedPercent:Y,swapTotalBytes:Y,swapUsedBytes:Y,
|
|
1369
|
+
cpuUtilisation:Y,cpuIdle:Y,load:pL.nullable(),storage:UX.nullable(),gpu:l.array(FX),gpuMemory:l.object({usedBytes:l.number(),totalBytes:l.number()}).strict().nullable().optional().describe("Memory used and present on the GPUs, from nvidia-smi; absent on other GPUs"),temperatureCelsius:Y.describe("CPU package temperature in Celsius, where the platform reports one"),battery:BX.nullable().describe("Absent on a host with no battery")}).strict(),"HostMetrics"),ZX=$(l.object({id:l.string(),name:l.string(),
|
|
1370
|
+
service:Re,cpuUtilisation:Y,memoryUsedBytes:Y,memoryLimitBytes:Y,memoryUsedPercent:Y,networkRxBytes:Y,networkTxBytes:Y,blockReadBytes:Y,blockWriteBytes:Y,pids:l.number().int().nullable()}).strict(),"ContainerResourceMetrics"),GX=$(l.object({path:l.string().describe("The working directory it was read from"),branch:l.string().nullable().describe("Null when HEAD is detached or the repository has no commit yet"),detached:l.boolean(),upstream:l.string().nullable(),ahead:l.number().int().nullable().describe(
|
|
1371
1371
|
"Commits not yet pushed; null without an upstream"),behind:l.number().int().nullable().describe("Commits not yet pulled, as last fetched; null without an upstream"),head:l.object({sha:l.string(),subject:l.string(),author:l.string(),at:ye}).strict().nullable(),changed:l.number().int().describe("Tracked files with changes not committed"),untracked:l.number().int(),files:l.array(l.object({path:l.string(),status:l.enum(["M","A","D","U"]).describe("Modified, added, deleted or new (untracked)")}).strict()).
|
|
1372
|
-
describe("The first of them: changed + untracked can be longer"),lastChangeAt:ye.nullable().describe("The newest of the last commit and the files not committed"),collectedAt:ye}).strict(),"GitState"),
|
|
1373
|
-
number().int(),networkRxBytes:Y,networkTxBytes:Y,containers:l.array(
|
|
1374
|
-
"The writable layer of its containers")}).strict())}).strict().describe("What each Compose project keeps on the Docker disk. Images are shared and are not counted here"),"DockerStorageInfo"),
|
|
1375
|
-
host:l.object({cpuUtilisation:Y,memoryUsedBytes:Y,memoryUsedPercent:Y,storageUsedPercent:Y,load:pL.nullable(),gpuUtilisation:Y,temperatureCelsius:Y}).strict(),projects:l.array(l.object({id:l.string(),cpuUtilisation:Y,memoryUsedBytes:Y}).strict()),containers:l.array(l.object({id:l.string(),cpuUtilisation:Y,memoryUsedBytes:Y}).strict())}).strict(),"MetricsHistoryPoint"),
|
|
1372
|
+
describe("The first of them: changed + untracked can be longer"),lastChangeAt:ye.nullable().describe("The newest of the last commit and the files not committed"),collectedAt:ye}).strict(),"GitState"),WX=$(l.object({id:l.string(),name:l.string(),composeProject:l.string(),own:l.literal(!0).optional().describe("Set on Portta's own containers (gateway, panel, proxies)"),cpuUtilisation:Y,memoryUsedBytes:Y,gpuMemoryBytes:Y.optional().describe("What its containers hold of the GPU's memory"),containerCount:l.
|
|
1373
|
+
number().int(),networkRxBytes:Y,networkTxBytes:Y,containers:l.array(ZX),git:GX.nullable().optional()}).strict(),"ProjectResourceMetrics"),VX=$(l.object({id:l.string(),name:Re,hostname:Re}).strict(),"MetricsInstance"),KX=$(l.object({name:l.enum(["orbstack","docker-desktop","docker-engine","unknown"])}).strict(),"RuntimeHint"),JX=$(l.object({collectedAt:ye,projects:l.array(l.object({composeProject:l.string(),volumeBytes:l.number().describe("The project's named volumes"),layerBytes:l.number().describe(
|
|
1374
|
+
"The writable layer of its containers")}).strict())}).strict().describe("What each Compose project keeps on the Docker disk. Images are shared and are not counted here"),"DockerStorageInfo"),S$e=$(l.object({version:l.literal(1),instance:VX,collectedAt:ye.nullable(),ageSeconds:l.number().int().nullable(),stale:l.boolean(),collectorActive:l.boolean(),host:HX.nullable(),runtime:KX.nullable(),projects:l.array(WX),dockerStorage:JX.nullable().optional()}).strict(),"MetricsCurrent"),YX=$(l.object({timestamp:ye,
|
|
1375
|
+
host:l.object({cpuUtilisation:Y,memoryUsedBytes:Y,memoryUsedPercent:Y,storageUsedPercent:Y,load:pL.nullable(),gpuUtilisation:Y,temperatureCelsius:Y}).strict(),projects:l.array(l.object({id:l.string(),cpuUtilisation:Y,memoryUsedBytes:Y}).strict()),containers:l.array(l.object({id:l.string(),cpuUtilisation:Y,memoryUsedBytes:Y}).strict())}).strict(),"MetricsHistoryPoint"),x$e=$(l.object({windowSeconds:l.number().int(),points:l.array(YX)}).strict(),"MetricsHistory"),XX=$(l.object({projects:l.number().
|
|
1376
1376
|
int(),integratedProjects:l.number().int(),services:l.number().int(),servicesRunning:l.number().int(),servicesHealthy:l.number().int(),servicesUnhealthy:l.number().int(),containersTotal:l.number().int(),containersRunning:l.number().int(),containersGateway:l.number().int(),containersIntegrated:l.number().int(),containersExternal:l.number().int(),containersStandalone:l.number().int(),bridges:l.number().int(),forwarders:l.number().int(),routes:l.number().int(),shares:l.number().int(),sharesStale:l.number().
|
|
1377
|
-
int().describe("Shares that expired or whose target is gone")}).strict(),"OverviewCounts"),
|
|
1378
|
-
string(),ownership:Jp,containerPort:l.number().int()}).strict(),
|
|
1379
|
-
object({gateway:l.number().int(),integrated:l.number().int(),external:l.number().int(),standalone:l.number().int()}).strict(),networks:l.array(dL),ports:l.array(
|
|
1380
|
-
strict(),"Bridge"),fL=$(l.object({alias:l.string(),containerId:l.string(),project:l.string(),service:l.string(),port:l.number().int(),kind:Dr,state:ut.or(l.literal("absent")),networks:l.array(l.string())}).strict(),"Forwarder"),
|
|
1381
|
-
nullable(),forwarder:fL.nullable(),integrated:l.boolean(),routing:
|
|
1382
|
-
l.object({project:l.string(),service:l.string(),kind:Dr,endpoints:l.array(
|
|
1383
|
-
boolean().describe("Whether TCP entrypoints are currently published")}).strict(),"AccessView"),
|
|
1384
|
-
boolean(),running:l.boolean(),hostname:l.string(),state:ut.or(l.literal("absent")),health:us}).strict(),dns:l.object({provider:l.string(),cloudflareEnabled:l.boolean(),zone:l.string().nullable()}).strict(),tls:l.object({enabled:l.boolean(),mode:l.string(),acmeEmailSet:l.boolean(),caServer:l.string()}).strict()}).strict(),"NetworkView"),
|
|
1377
|
+
int().describe("Shares that expired or whose target is gone")}).strict(),"OverviewCounts"),k$e=$(l.object({gateway:uL,counts:XX,urls:l.array(Ta),problems:l.array(ed),generatedAt:ye}).strict(),"Overview"),dL=$(l.object({id:l.string(),name:l.string(),driver:l.string(),scope:l.string(),internal:l.boolean(),containerCount:l.number().int(),managed:l.boolean(),role:l.enum(["shared","control","access","project","other"])}).strict(),"NetworkSummary"),QX=l.object({ip:l.string(),containerId:l.string(),containerName:l.
|
|
1378
|
+
string(),ownership:Jp,containerPort:l.number().int()}).strict(),eQ=$(l.object({hostPort:l.number().int(),protocol:l.string(),bindings:l.array(QX),conflict:l.boolean()}).strict(),"PortUsage"),_$e=$(l.object({engine:l.object({version:l.string(),apiVersion:l.string(),os:l.string(),arch:l.string(),cpus:l.number().int(),memoryBytes:l.number(),name:l.string()}).strict(),containers:l.object({total:l.number().int(),running:l.number().int(),paused:l.number().int(),stopped:l.number().int()}).strict(),byOwnership:l.
|
|
1379
|
+
object({gateway:l.number().int(),integrated:l.number().int(),external:l.number().int(),standalone:l.number().int()}).strict(),networks:l.array(dL),ports:l.array(eQ)}).strict(),"DockerHost"),td=$(l.object({id:l.string(),containerId:l.string(),project:l.string(),service:l.string(),targetPort:l.number().int(),localPort:l.number().int().nullable(),bindIp:l.string(),kind:Dr,network:l.string(),createdAt:ye.nullable(),expiresAt:ye.nullable(),state:ut.or(l.literal("absent")),connectionString:l.string()}).
|
|
1380
|
+
strict(),"Bridge"),fL=$(l.object({alias:l.string(),containerId:l.string(),project:l.string(),service:l.string(),port:l.number().int(),kind:Dr,state:ut.or(l.literal("absent")),networks:l.array(l.string())}).strict(),"Forwarder"),tQ=$(l.object({containerId:l.string(),project:l.string(),service:l.string(),image:l.string(),kind:Dr,tech:Yp,state:ut,health:us,ports:l.array(l.number().int()),defaultPort:l.number().int().nullable(),publishedPorts:l.array(Qp),privateNetworks:l.array(l.string()),bridge:td.
|
|
1381
|
+
nullable(),forwarder:fL.nullable(),integrated:l.boolean(),routing:bX.describe("How this protocol can be routed by hostname"),routed:l.boolean().describe("Whether the container opted into a TCP router"),gatewayAddress:l.string().nullable(),gatewayConnectionString:l.string().nullable()}).strict(),"TcpService"),nQ=$(l.object({provider:l.string(),url:l.string(),scope:Xp,usable:l.boolean(),shareable:l.boolean(),problem:l.string().nullable(),connectionString:l.string()}).strict(),"ServiceEndpoint"),P$e=$(
|
|
1382
|
+
l.object({project:l.string(),service:l.string(),kind:Dr,endpoints:l.array(nQ),credentials:l.object({discovered:l.boolean(),user:l.string().nullable(),password:l.string().nullable().describe("Present only on this route; never logged or stored"),database:l.string().nullable(),source:l.string().nullable(),reason:l.string().nullable()}).strict()}).strict(),"ServiceConnection"),E$e=$(l.object({services:l.array(tQ),bridges:l.array(td),forwarders:l.array(fL),bridgeImageHint:l.string(),tcpRoutingEnabled:l.
|
|
1383
|
+
boolean().describe("Whether TCP entrypoints are currently published")}).strict(),"AccessView"),rQ=l.object({project:l.string().nullable(),service:l.string().nullable(),containerId:l.string(),containerName:l.string(),state:ut,urls:l.array(Ta),port:l.string()}).strict(),A$e=$(l.object({gateway:uL,domains:l.object({local:l.string(),private:l.string().nullable(),public:l.string().nullable(),scheme:l.enum(["http","https"])}).strict(),routes:l.array(rQ),networks:l.array(dL),tailscale:l.object({enabled:l.
|
|
1384
|
+
boolean(),running:l.boolean(),hostname:l.string(),state:ut.or(l.literal("absent")),health:us}).strict(),dns:l.object({provider:l.string(),cloudflareEnabled:l.boolean(),zone:l.string().nullable()}).strict(),tls:l.object({enabled:l.boolean(),mode:l.string(),acmeEmailSet:l.boolean(),caServer:l.string()}).strict()}).strict(),"NetworkView"),oQ=$(l.object({key:l.string(),value:l.string().nullable().describe("Never populated for a secret"),runtimeValue:l.string().nullable(),effectiveValue:l.string().nullable().
|
|
1385
1385
|
describe("Value the form should display after applying precedence and defaults"),defaultValue:l.string().nullable().describe("Canonical default when the key is absent from .env"),valueSource:l.enum(["saved","default","detected","derived","environment"]).optional().describe("Where the displayed value comes from, when that is useful to say"),secret:l.boolean(),isSet:l.boolean(),pending:l.boolean().describe("Saved value differs from the running process"),kind:l.enum(["boolean","string","number","ch\
|
|
1386
|
-
oice"]),choices:l.array(l.string()).optional(),group:l.string(),label:l.string(),help:l.string(),restartRequired:l.boolean()}).strict(),"ConfigField"),
|
|
1387
|
-
describe("Whether Traefik listens somewhere these names can actually reach it"),advice:l.string().nullable().describe("What to do about it, when something is off")}).strict(),"ProjectDomain"),
|
|
1386
|
+
oice"]),choices:l.array(l.string()).optional(),group:l.string(),label:l.string(),help:l.string(),restartRequired:l.boolean()}).strict(),"ConfigField"),sQ=$(l.object({mode:l.enum(["local","auto","custom"]),domain:l.string().describe("The base every project hostname is built on"),publicIp:l.string().nullable(),provider:l.string(),examples:l.array(l.string()).describe("Hostnames a project would get"),problem:l.string().nullable().describe("Set when the mode could not be honoured"),reachable:l.boolean().
|
|
1387
|
+
describe("Whether Traefik listens somewhere these names can actually reach it"),advice:l.string().nullable().describe("What to do about it, when something is off")}).strict(),"ProjectDomain"),iQ=$(l.object({hostname:l.string(),service:l.string()}).strict(),"TunnelRoute"),O$e=$(l.object({state:l.enum(["not-configured","configured","starting","connected","disconnected","auth-error","config-error"]).describe("What the connector is doing, distinguished so the fix is obvious"),detail:l.string(),hint:l.
|
|
1388
1388
|
string().nullable().describe("The single next step, when there is one"),enabled:l.boolean().describe("Whether the connector is part of the running stack"),zone:l.string().nullable().describe("The domain whose wildcard reaches this gateway"),wildcard:l.string().nullable(),tunnelId:l.string().nullable().describe("Not a secret: cfargotunnel only accepts records from the owning account"),credentialConfigured:l.boolean(),container:l.object({name:l.string(),state:l.string(),health:l.string()}),routes:l.
|
|
1389
|
-
array(
|
|
1390
|
-
exists:l.boolean(),writable:l.boolean()}).strict(),pendingRestart:l.boolean(),applyCommand:l.string().describe("Host command that applies saved changes"),groups:l.array(l.string())}).strict(),"ConfigView"),
|
|
1391
|
-
nullable().describe("Saved value; null for a secret"),secret:l.boolean(),fromSet:l.boolean().describe("Whether the running process had a value"),toSet:l.boolean().describe("Whether the saved file has a value"),restartRequired:l.boolean()}).strict(),"PendingChange")
|
|
1392
|
-
enum(["disabled","refused","not-prepared"]),"ApplyUnavailableReason")
|
|
1393
|
-
logTail:l.array(l.string()),profile:l.string(),applyCommand:l.string().describe("Host command that applies saved changes")}).strict(),"ApplyStatus"),
|
|
1394
|
-
nullable(),startedAt:ye.nullable(),finishedAt:ye.nullable(),exitCode:l.number().int().nullable(),logTail:l.array(l.string()),prepareCommand:l.string().describe("Host command that prepares the runner")}).strict(),"RunnerStatus"),
|
|
1395
|
-
RunnerStartResult"),
|
|
1396
|
-
string().nullable(),text:l.string()}).strict(),
|
|
1397
|
-
urce"),
|
|
1398
|
-
object({ok:l.boolean(),action:l.string(),containerId:l.string(),message:l.string()}).strict(),"ActionResult"),
|
|
1399
|
-
object({kind:
|
|
1400
|
-
ope returned by the panel API"),"ApiError");var ps=i((e,t)=>e.meta({ref:t}),"named"),hL=l.number().describe("Unix timestamp in seconds"),
|
|
1401
|
-
"service-unhealthy","environment-degraded","diagnostic","host-pressure"]),severity:l.enum(["warn","fail"]),summary:l.string(),project:l.string().nullable().describe("Project slug"),environment:l.string().nullable(),service:l.string().nullable(),href:l.string().describe("Where in the panel to act on it"),code:l.string().nullable().describe("The id of the diagnostic check behind a `diagnostic` item, so a page can say it in its own language")}).strict(),"AttentionItem"),
|
|
1402
|
-
name:l.string(),archived:l.boolean(),environmentCount:l.number().int(),runningEnvironments:l.number().int(),unhealthyServices:l.number().int(),health:l.enum(["ok","partial","unhealthy","idle"]),resources:l.object({cpuUtilisation:l.number().nullable(),memoryUsedBytes:l.number().nullable()}).strict().nullable()}).strict(),"ProjectPulse"),
|
|
1403
|
-
servicesRunning:l.number().int(),servicesUnhealthy:l.number().int(),routedUrls:l.number().int()}).strict(),resources:l.object({host:l.object({cpuUtilisation:l.number().nullable(),memoryUsedPercent:l.number().nullable(),storageUsedPercent:l.number().nullable(),stale:l.boolean(),collectorActive:l.boolean(),pressure:
|
|
1404
|
-
nullable()}).strict())}).strict(),gateway:l.object({up:l.boolean(),problems:l.array(ed)}).strict()}).strict(),"DevelopmentOverview"),
|
|
1405
|
-
nullable(),memoryLimitBytes:l.number().nullable()}).strict())}).strict(),"EnvironmentResources"),
|
|
1389
|
+
array(iQ).describe("What the connector serves, in match order"),endpointCount:l.number().describe("HTTP services this tunnel could publish"),dnsRecord:l.object({type:l.string(),name:l.string(),target:l.string(),proxied:l.boolean()}).nullable().describe("The one record the operator creates by hand, once"),imageAvailable:l.boolean().describe("Whether the connector image is already pulled")}).strict(),"TunnelView"),mL=$(l.object({fields:l.array(oQ),projectDomain:sQ,envFile:l.object({path:l.string(),
|
|
1390
|
+
exists:l.boolean(),writable:l.boolean()}).strict(),pendingRestart:l.boolean(),applyCommand:l.string().describe("Host command that applies saved changes"),groups:l.array(l.string())}).strict(),"ConfigView"),T$e=$(l.object({ok:l.boolean(),saved:l.array(l.string()),pendingRestart:l.boolean(),applyCommand:l.string(),view:mL}).strict(),"ConfigPatchResult"),aQ=$(l.object({key:l.string(),label:l.string(),group:l.string(),from:l.string().nullable().describe("Running value; null for a secret"),to:l.string().
|
|
1391
|
+
nullable().describe("Saved value; null for a secret"),secret:l.boolean(),fromSet:l.boolean().describe("Whether the running process had a value"),toSet:l.boolean().describe("Whether the saved file has a value"),restartRequired:l.boolean()}).strict(),"PendingChange"),$$e=$(l.object({ok:l.boolean(),discarded:l.array(l.string()),pendingRestart:l.boolean(),applyCommand:l.string(),view:mL}).strict(),"ConfigDiscardResult"),cQ=$(l.enum(["unavailable","idle","running","ok","failed"]),"ApplyState"),lQ=$(l.
|
|
1392
|
+
enum(["disabled","refused","not-prepared"]),"ApplyUnavailableReason"),C$e=$(l.object({state:cQ,available:l.boolean().describe("An applier container exists on this host"),reason:l.string().nullable().describe("Why the panel cannot apply, in one line"),unavailableReason:lQ.nullable(),buildsImages:l.boolean(),startedAt:ye.nullable(),finishedAt:ye.nullable(),exitCode:l.number().int().nullable(),pendingRestart:l.boolean(),pendingKeys:l.array(l.string()),pendingChanges:l.array(aQ),movesPanel:l.boolean(),
|
|
1393
|
+
logTail:l.array(l.string()),profile:l.string(),applyCommand:l.string().describe("Host command that applies saved changes")}).strict(),"ApplyStatus"),uQ=$(l.enum(["unavailable","idle","running","ok","failed"]),"RunnerState"),pQ=$(l.enum(["disabled","refused","not-prepared"]),"RunnerUnavailableReason"),Pw=$(l.object({state:uQ,available:l.boolean().describe("A runner container exists on this host"),reason:l.string().nullable().describe("Why the panel cannot operate a project, in one line"),unavailableReason:pQ.
|
|
1394
|
+
nullable(),startedAt:ye.nullable(),finishedAt:ye.nullable(),exitCode:l.number().int().nullable(),logTail:l.array(l.string()),prepareCommand:l.string().describe("Host command that prepares the runner")}).strict(),"RunnerStatus"),R$e=$(l.object({ok:l.boolean(),project:l.string(),noCache:l.boolean(),via:l.literal("runner"),runner:Pw}).strict(),"ProjectRebuildResult"),j$e=$(l.object({ok:l.boolean(),project:l.string(),action:l.literal("start"),via:l.literal("runner"),runner:Pw}).strict(),"Environment\
|
|
1395
|
+
RunnerStartResult"),I$e=$(l.object({ok:l.boolean(),project:l.string(),mode:l.enum(["keep-data","and-local-data"]),volumes:l.boolean(),via:l.enum(["runner","iteration"]),removedContainers:l.array(l.string()),cleaned:sL,remainingCommands:l.array(l.string()),runner:Pw.nullable(),note:l.string().nullable()}).strict(),"ProjectRemoveResult"),D$e=$(l.object({ok:l.literal(!0),startedAt:ye,note:l.string(),applyCommand:l.string()}).strict(),"ApplyResult"),dQ=l.object({stream:l.enum(["stdout","stderr"]),timestamp:l.
|
|
1396
|
+
string().nullable(),text:l.string()}).strict(),N$e=$(l.object({containerId:l.string(),name:l.string(),lines:l.array(dQ),truncated:l.boolean()}).strict(),"LogsResponse"),fQ=$(l.object({containerId:l.string(),service:l.string().describe("Compose service name, or the container name when unlabelled"),name:l.string().describe("Container name"),state:ut,lineCount:l.number().int(),truncated:l.boolean(),error:l.string().nullable().describe("Why this source contributed no lines")}).strict(),"ProjectLogSo\
|
|
1397
|
+
urce"),mQ=$(l.object({stream:l.enum(["stdout","stderr"]),timestamp:l.string().nullable(),text:l.string(),service:l.string().describe("Which source produced this line")}).strict(),"ProjectLogLine"),L$e=$(l.object({project:l.string(),sources:l.array(fQ),lines:l.array(mQ).describe("Merged and ordered by timestamp where one exists"),truncated:l.boolean(),ordered:l.boolean().describe("False when a source logged without timestamps, so ordering is approximate")}).strict(),"ProjectLogsResponse"),M$e=$(l.
|
|
1398
|
+
object({ok:l.boolean(),action:l.string(),containerId:l.string(),message:l.string()}).strict(),"ActionResult"),z$e=$(l.object({containerId:l.string(),name:l.string(),image:l.string(),ownership:Jp,state:ut,project:l.string().nullable(),mounts:l.array(oL),namedVolumes:l.array(l.string()),networks:l.array(l.string()),warnings:l.array(l.string()),allowed:l.boolean()}).strict(),"RemovalPreview"),hQ=$(l.enum(["container","network","bridge","health","project","config","hello"]),"LiveEventKind"),F$e=$(l.
|
|
1399
|
+
object({kind:hQ,action:l.string(),id:l.string().nullable(),name:l.string().nullable(),project:l.string().nullable(),ownership:Jp.nullable(),at:ye}).strict(),"LiveEvent"),B$e=$(l.object({applied:l.array(l.string()).describe("Filenames this call applied"),migrations:l.array(l.string()).describe("Every migration the panel has applied")}).strict(),"DatabaseMigrateResult"),U$e=$(l.object({error:l.string(),detail:l.string().optional(),hint:l.string().optional()}).strict().describe("Uniform error envel\
|
|
1400
|
+
ope returned by the panel API"),"ApiError");var ps=i((e,t)=>e.meta({ref:t}),"named"),hL=l.number().describe("Unix timestamp in seconds"),gQ=ps(l.object({level:l.enum(["normal","watch","pressured","critical"]),measured:l.boolean(),reasons:l.array(l.object({resource:l.enum(["cpu","memory","swap","storage","gpu","temperature","load","battery"]),level:l.enum(["watch","pressured","critical"]),value:l.number().describe("A ratio for anything measured 0-1, else the raw reading")}).strict())}).strict(),"HostPressure"),bQ=ps(l.object({kind:l.enum([
|
|
1401
|
+
"service-unhealthy","environment-degraded","diagnostic","host-pressure"]),severity:l.enum(["warn","fail"]),summary:l.string(),project:l.string().nullable().describe("Project slug"),environment:l.string().nullable(),service:l.string().nullable(),href:l.string().describe("Where in the panel to act on it"),code:l.string().nullable().describe("The id of the diagnostic check behind a `diagnostic` item, so a page can say it in its own language")}).strict(),"AttentionItem"),yQ=ps(l.object({slug:l.string(),
|
|
1402
|
+
name:l.string(),archived:l.boolean(),environmentCount:l.number().int(),runningEnvironments:l.number().int(),unhealthyServices:l.number().int(),health:l.enum(["ok","partial","unhealthy","idle"]),resources:l.object({cpuUtilisation:l.number().nullable(),memoryUsedBytes:l.number().nullable()}).strict().nullable()}).strict(),"ProjectPulse"),W$e=ps(l.object({generatedAt:hL,attention:l.array(bQ),projects:l.array(yQ),runtime:l.object({environmentsRunning:l.number().int(),environmentsTotal:l.number().int(),
|
|
1403
|
+
servicesRunning:l.number().int(),servicesUnhealthy:l.number().int(),routedUrls:l.number().int()}).strict(),resources:l.object({host:l.object({cpuUtilisation:l.number().nullable(),memoryUsedPercent:l.number().nullable(),storageUsedPercent:l.number().nullable(),stale:l.boolean(),collectorActive:l.boolean(),pressure:gQ}).strict().nullable(),topProjects:l.array(l.object({slug:l.string().nullable(),name:l.string(),environment:l.string(),cpuUtilisation:l.number().nullable(),memoryUsedBytes:l.number().
|
|
1404
|
+
nullable()}).strict())}).strict(),gateway:l.object({up:l.boolean(),problems:l.array(ed)}).strict()}).strict(),"DevelopmentOverview"),wQ=ps(l.object({environment:l.string(),project:l.string().nullable().describe("Project slug, when adopted"),cpuUtilisation:l.number().nullable(),memoryUsedBytes:l.number().nullable(),containerCount:l.number().int(),containers:l.array(l.object({id:l.string(),name:l.string(),service:l.string().nullable(),cpuUtilisation:l.number().nullable(),memoryUsedBytes:l.number().
|
|
1405
|
+
nullable(),memoryLimitBytes:l.number().nullable()}).strict())}).strict(),"EnvironmentResources"),V$e=ps(l.object({project:l.string(),collectedAt:hL.nullable(),stale:l.boolean(),collectorActive:l.boolean(),cpuUtilisation:l.number().nullable(),memoryUsedBytes:l.number().nullable(),hostMemoryTotalBytes:l.number().nullable(),environments:l.array(wQ)}).strict(),"ProjectResources");var ds=i((e,t)=>e.meta({ref:t}),"named"),bL=l.number().describe("Unix timestamp in seconds"),gL=ds(l.object({provider:l.string(),url:l.string().describe("An http(s) URL, or host:port for a datastore"),scope:Xp,usable:l.boolean(),shareable:l.boolean(),problem:l.string().nullable()}).strict(),"ServiceAccessEndpoint"),vQ=ds(l.object({kind:l.enum(["http","tcp","none"]).describe("How this service is reached"),primary:gL.nullable().describe("The one address to open first"),endpoints:l.array(gL),bridge:td.
|
|
1406
1406
|
nullable().describe("An open loopback bridge, for a datastore"),routed:l.boolean().describe("Whether the service opted into the gateway"),problem:l.string().nullable().describe("Why it cannot be reached, when it cannot")}).strict(),"ServiceAccess"),yL=ds(l.object({cpuUtilisation:l.number().nullable(),memoryUsedBytes:l.number().nullable(),memoryLimitBytes:l.number().nullable(),diskBytes:l.number().nullable().describe("Null: the collector has no per-container disk yet"),collectedAt:bL.nullable(),stale:l.
|
|
1407
|
-
boolean()}).strict(),"ServiceResources"),
|
|
1408
|
-
health:us,startedAt:bL.nullable(),uptimeSeconds:l.number().nullable(),restartCount:l.number().int(),exitCode:l.number().int().nullable(),completed:l.boolean().optional().describe("Exited 0 with no restart policy: a one-shot that did its job"),ports:l.array(Qp),exposedPorts:l.array(l.number().int()),networks:l.array(l.string()),onGatewayNetwork:l.boolean(),access:
|
|
1409
|
-
"Service"),
|
|
1410
|
-
erated/corpus.json",import.meta.url);try{let r=
|
|
1411
|
-
identity,results:PS(r.pages,a.q,a)}}let o=xw.parse(n),s=ES(r,o.slug,o.anchor);if(!s)throw new _e("no such document or heading");return Vp.parse({identity:r.identity,page:s})}}i(
|
|
1407
|
+
boolean()}).strict(),"ServiceResources"),SQ=ds(l.object({start:l.boolean(),stop:l.boolean(),restart:l.boolean(),logs:l.boolean(),openAccess:l.boolean().describe("A loopback bridge can be opened"),share:l.boolean().describe("A temporary hostname can be created")}).strict(),"ServiceActions"),xQ=ds(l.object({name:l.string().describe("Compose service name"),environment:l.string().describe("COMPOSE_PROJECT_NAME"),containerId:l.string(),containerName:l.string(),image:l.string(),kind:Dr,tech:Yp,state:ut,
|
|
1408
|
+
health:us,startedAt:bL.nullable(),uptimeSeconds:l.number().nullable(),restartCount:l.number().int(),exitCode:l.number().int().nullable(),completed:l.boolean().optional().describe("Exited 0 with no restart policy: a one-shot that did its job"),ports:l.array(Qp),exposedPorts:l.array(l.number().int()),networks:l.array(l.string()),onGatewayNetwork:l.boolean(),access:vQ,resources:yL.nullable(),actions:SQ,overrides:kw.optional(),hidden:l.boolean().describe("Collapsed by an environment override")}).strict(),
|
|
1409
|
+
"Service"),Q$e=ds(l.object({environment:l.string(),services:l.array(xQ),resources:yL.nullable().describe("The environment as a whole")}).strict(),"EnvironmentServices");function TQ(e){return async(t,n)=>{let r=(t==="list"?Kp:t==="search"?Sw:xw).parse(n),o=new URLSearchParams(Object.entries(r).filter(([,c])=>c!==void 0).map(([c,u])=>[c,String(u)])),a=await e(`${t==="list"?"/documentation":t==="search"?"/documentation/search":"/documentation/page"}?${o}`);return(t==="list"?ww:t==="search"?vw:Vp).parse(a)}}i(TQ,"remoteDocumentationReader");var nd="documentation.json.gz";function $Q(){let e=PQ(import.meta.dirname,nd),t=kQ(e),n=t?AQ(e):new URL("../../../../docs/.gen\
|
|
1410
|
+
erated/corpus.json",import.meta.url);try{let r=_Q(n),o=JSON.parse(t?OQ(r).toString("utf8"):r.toString("utf8"));if(o.schemaVersion!==1)throw new Error("unsupported corpus version");return o}catch{throw new L(`documentation is unavailable at ${EQ(n)}`,"reinstall this CLI or run npm run docs:generate in the checkout")}}i($Q,"loadLocalDocumentation");function CQ(e=$Q){return async(t,n)=>{let r=e();if(t==="list"){let a=Kp.parse(n);return AS(r,a.audience)}if(t==="search"){let a=Sw.parse(n);return{identity:r.
|
|
1411
|
+
identity,results:PS(r.pages,a.q,a)}}let o=xw.parse(n),s=ES(r,o.slug,o.anchor);if(!s)throw new _e("no such document or heading");return Vp.parse({identity:r.identity,page:s})}}i(CQ,"localDocumentationReader");async function rd(e,t,n){let r=n.optsWithGlobals(),o=new T(r),s=r.url?TQ(c=>de(n).client.request("GET",c)):CQ(),a=e==="show"?{slug:t,...r.anchor?{anchor:r.anchor}:{}}:{...r.audience?{audience:r.audience}:{},...e==="search"?{q:t,...r.limit?{limit:r.limit}:{}}:{}};try{let c=await s(e,a),u=r.url?
|
|
1412
1412
|
"panel":"local";if(o.json){o.data({origin:u,...c});return}let p=c.identity;if(o.line(`Portta ${p.version} documentation (${u}, ${p.hash.slice(0,12)})`),e==="show"){let{page:d}=Vp.parse(c);o.line(`${d.url}
|
|
1413
1413
|
|
|
1414
1414
|
${d.markdown}`)}else if(e==="list")for(let d of ww.parse(c).pages)o.line(`${d.slug} ${d.title} [${d.audience} / ${d.section}]`);else{let{results:d}=vw.parse(c);d.length||o.line("No matching documentation.");for(let f of d)o.line(`${f.url} ${f.title}
|
|
1415
|
-
${f.excerpt}`)}}catch(c){throw c instanceof l.ZodError?new C(c.issues.map(u=>u.message).join("; ")):c}}i(rd,"docsCommand");import{chmodSync as
|
|
1416
|
-
"newestSourceMtime");function
|
|
1417
|
-
exitCode)}i(kL,"reexecBuiltCli");import{existsSync as Nr,readdirSync as
|
|
1415
|
+
${f.excerpt}`)}}catch(c){throw c instanceof l.ZodError?new C(c.issues.map(u=>u.message).join("; ")):c}}i(rd,"docsCommand");import{chmodSync as oee,existsSync as Mr,mkdirSync as see,readdirSync as iee,readFileSync as ML,rmSync as zL}from"node:fs";import{join as yt}from"node:path";import{existsSync as od,readdirSync as RQ,statSync as wL}from"node:fs";import{join as $a}from"node:path";var jQ=["packages/cli/src","packages/cli/scripts","packages/cli/package.json","packages/core/src","packages/contracts/src"];function vL(e){return $a(e,"packages/cli/dist/cli.js")}i(vL,"checkoutCliDist");function IQ(e){return od($a(e,"packages/cli/src/cli.ts"))&&od($a(e,"package.json"))}i(IQ,"isCheckout");function SL(e){if(!od(e))return 0;let t=wL(e);if(t.isFile())return/\.(ts|mjs|json)$/.test(e)?t.mtimeMs:0;let n=0;for(let r of RQ(e,{withFileTypes:!0}))n=Math.max(n,SL($a(e,r.name)));return n}i(SL,
|
|
1416
|
+
"newestSourceMtime");function DQ(e){if(!IQ(e))return!1;let t=vL(e);if(!od(t))return!0;let n=wL(t).mtimeMs;return jQ.some(r=>SL($a(e,r))>n)}i(DQ,"checkoutCliNeedsBuild");async function xL(e,t){return DQ(e)?(t.progress("building the TypeScript CLI"),await _("npm",["run","build","--workspace=@codions/portta"],{cwd:e,stdio:"inherit"}),!0):!1}i(xL,"ensureCheckoutCli");async function kL(e){let t=await _(process.execPath,[vL(e),...process.argv.slice(2)],{cwd:e,stdio:"inherit",reject:!1});process.exit(t.
|
|
1417
|
+
exitCode)}i(kL,"reexecBuiltCli");import{existsSync as Nr,readdirSync as NQ,readFileSync as LQ}from"node:fs";import{join as vn}from"node:path";var MQ=2;function Ew(e){return e.ports.filter(t=>t.publicPort!==null).map(t=>`${t.ip}:${t.publicPort}`).join(" ")}i(Ew,"publishedBindings");function zQ(e){return e.ports.filter(t=>t.publicPort!==null).map(t=>`${t.privatePort}/${t.type}=${t.ip}:${t.publicPort}`).join(" ")}i(zQ,"bindMap");function FQ(e){return e.ports.filter(t=>t.publicPort!==null).map(t=>`${t.ip}:${t.publicPort}->${t.privatePort}/${t.type}`).join(" ")}i(FQ,"publishedWithTargets");function fs(e,t){return e.find(n=>n.labels["portta\
|
|
1418
1418
|
.managed"]==="true"&&n.labels["portta.component"]===t)}i(fs,"gatewayContainer");async function _L(e){let t=await _("docker",["network","inspect",e,"--format",'{{ .Internal }} {{ index .Labels "portta.managed" }} {{ len .Containers }}'],{reject:!1});if(t.failed)return{exists:!1,internal:!1,managed:!1,endpoints:0};let[n="",r="",o="0"]=t.stdout.trim().split(" ");return{exists:!0,internal:n==="true",managed:r==="true",endpoints:Number(o)||0}}i(_L,"networkFacts");async function Aw(e,t){let n=await _(
|
|
1419
1419
|
e,t,{reject:!1});return n.failed?null:n.stdout.trim().split(`
|
|
1420
1420
|
`)[0]??null}i(Aw,"version");async function EL(e){let t=[],n=e.env,r=e.config,o=e.root,s=n.PORTTA_STATE_DIR||vn(o,"state"),a=i((...j)=>{for(let X of j)X&&t.push(X)},"add");a(v("gateway.version","pass","gateway version",e.version)),a(Yd(n.PORTTA_PROFILE??r.profile)?v("config.profile","pass","profile",r.profile):v("config.profile","fail","profile",`unknown profile '${n.PORTTA_PROFILE}'`,"set PORTTA_PROFILE to one of: local remote-private remote-public"));let c=vn(o,".env");Nr(c)?(a(v("config.env","\
|
|
1421
1421
|
pass",".env","present")),a(Wv(Jn(c)))):a(v("config.env","warn",".env","absent; running on built-in defaults","cp .env.example .env"));let u=ZI();u.length>0&&a(v("agents.layer","warn","AI agents",`installed without the Portta layer: ${u.join(", ")}`,"portta agents install (dry run first: portta agents install --dry-run)"));let p=await qy(),d=p.find(j=>j.id==="runtime.docker");a(d??v("runtime.docker","fail","Docker","diagnostic unavailable"));let f=await fa("docker"),m=!1;f&&(m=!(await _("docker",
|
|
1422
|
-
["info"],{reject:!1})).failed,m&&a(v("runtime.context","pass","docker context",await Aw("docker",["context","show"])??"unknown")));let h=await Aw("docker",["compose","version","--short"]);if(a(h===null?v("runtime.compose","fail","docker compose","plugin missing","install the Docker Compose v2 plugin"):Rs(h,
|
|
1422
|
+
["info"],{reject:!1})).failed,m&&a(v("runtime.context","pass","docker context",await Aw("docker",["context","show"])??"unknown")));let h=await Aw("docker",["compose","version","--short"]);if(a(h===null?v("runtime.compose","fail","docker compose","plugin missing","install the Docker Compose v2 plugin"):Rs(h,MQ)?v("runtime.compose","pass","docker compose",h):v("runtime.compose","fail","docker compose",`v${h} is too old`,"install the Compose v2 plugin")),!m)return a(...p.filter(j=>j.id!=="runtime.d\
|
|
1423
1423
|
ocker")),t;let b=await _("docker",["compose",...we(e),"config","--quiet"],{cwd:o,env:n,reject:!1});a(b.failed?v("config.compose","fail","compose configuration",`the ${r.profile} profile does not render`,"portta inspect shows the file list; the error is above"):v("config.compose","pass","compose configuration",`renders for the ${r.profile} profile`));let g=await J(),y=g.filter(j=>j.state==="running"),w=await _L(r.network);w.exists?(a(v("network.shared","pass","shared network",`${r.network} (${w.
|
|
1424
1424
|
endpoints} attached)`)),a(w.managed?v("network.shared.owned","pass","shared network ownership","created by the gateway"):v("network.shared.owned","warn","shared network ownership",`'${r.network}' has no portta.managed label`,"harmless: the gateway will never remove a network it does not own"))):a(v("network.shared","fail","shared network",`'${r.network}' does not exist`,"portta bootstrap"));let P=n.PORTTA_CONTROL_NETWORK||`${r.network}-control`,x=await _L(P);a(x.exists?x.internal?v("network.cont\
|
|
1425
1425
|
rol","pass","control network",`${P} (internal)`):v("network.control","fail","control network",`${P} is not marked internal`,"the Docker socket proxy must sit on an internal network; recreate the gateway"):v("network.control","warn","control network","not created yet",`portta up ${r.profile}`));let E=fs(g,"traefik");E?(a(E.state==="running"&&E.health==="healthy"?v("traefik.state","pass","traefik","running and healthy"):E.state==="running"?v("traefik.state","warn","traefik",`running, health=${E.health??
|
|
1426
1426
|
"none"}`,"portta logs traefik"):v("traefik.state","fail","traefik",`state=${E.state}`,`portta up ${r.profile}`)),a(Vv(E.image)),a((E.mounts??[]).some(j=>j.source.includes("docker.sock"))?v("traefik.socket","fail","docker socket","the Docker socket is mounted into Traefik","remove the bind mount; Traefik must use the socket proxy on the control network"):v("traefik.socket","pass","docker socket","not mounted into Traefik"))):a(v("traefik.state","warn","traefik","container not created",`portta up ${r.
|
|
1427
1427
|
profile}`));let A=fs(g,"socket-proxy");if(!A)a(v("proxy.state","warn","docker socket proxy","container not created",`portta up ${r.profile}`));else{a(A.state==="running"?v("proxy.state","pass","docker socket proxy","running"):v("proxy.state","fail","docker socket proxy",`state=${A.state}`,`portta up ${r.profile}`));let j=Ew(A);a(j?v("proxy.exposure","fail","docker socket proxy exposure",`publishes host ports: ${j}`,"the Docker API must never be reachable from the host or the network"):v("proxy.e\
|
|
1428
1428
|
xposure","pass","docker socket proxy exposure","no host ports published"));let X=(A.mounts??[]).find(le=>le.source.includes("docker.sock"));a(X?X.readWrite?v("proxy.socket","fail","docker socket mount","mounted read-write","mount /var/run/docker.sock read-only (:ro)"):v("proxy.socket","pass","docker socket mount","read-only"):v("proxy.socket","warn","docker socket mount","could not determine mount mode"))}if(r.webEnabled){let j=Mt(o);a(Nr(j)?v("db.file","pass","panel database",j):v("db.file","wa\
|
|
1429
|
-
rn","panel database",`${j} not created yet; the panel creates it on first boot`,"portta web up"))}let N=(n.PORTTA_WEB_EXPOSE||"local")==="public";if(E&&E.state==="running"){let j=
|
|
1429
|
+
rn","panel database",`${j} not created yet; the panel creates it on first boot`,"portta web up"))}let N=(n.PORTTA_WEB_EXPOSE||"local")==="public";if(E&&E.state==="running"){let j=zQ(E);a(v("exposure.binds","pass","published ports",j||"none")),a(Xv(r.profile,j,N))}for(let j of y.filter(X=>X.labels["portta.managed"]==="true")){let X=FQ(j);Yv(X)&&a(v("exposure.sensitive","fail","sensitive port exposure",`${j.name} publishes a database or Docker API port on all interfaces: ${X}`,"bind it to 127.0.0.\
|
|
1430
1430
|
1 or remove the published port"))}let F=r.profile!=="local"&&r.tailscaleEnabled?"tailscale":"host";if(a(v("config.attachment","pass","traefik attachment",F)),F==="tailscale"){let j=fs(g,"tailscale");if(!j)a(v("tailscale.state","warn","tailscale","container not created",`portta up ${r.profile}`));else{if(j.state==="running"&&j.health==="healthy"){let le=await _("docker",["exec",j.id,"tailscale","ip","-4"],{reject:!1}),tn=le.failed?"":le.stdout.trim().split(`
|
|
1431
1431
|
`)[0]??"";a(tn?v("tailscale.state","pass","tailscale",`connected as ${tn}`):v("tailscale.state","fail","tailscale","running but has no tailnet address","check TS_AUTHKEY and the tailnet's device approval settings"))}else a(v("tailscale.state","fail","tailscale",`state=${j.state} health=${j.health??""}`,"portta logs tailscale"));E&&a(E.networkMode?.startsWith("container:")?v("tailscale.netns","pass","traefik network namespace","shared with tailscale"):v("tailscale.netns","fail","traefik network n\
|
|
1432
1432
|
amespace",`traefik is not in the tailscale namespace (${E.networkMode??"unknown"})`,`portta up ${r.profile}`)),a(Nr(vn(s,"tailscale"))?v("tailscale.state.dir","pass","tailscale state","persisted under state/tailscale"):v("tailscale.state.dir","warn","tailscale state","state directory missing","portta bootstrap"))}let X=!!n.TS_AUTHKEY;a(!X&&!Nr(vn(s,"tailscale/tailscaled.state"))?v("tailscale.authkey","fail","tailscale auth","no TS_AUTHKEY and no persisted state","set TS_AUTHKEY in .env; prefer a\
|
|
1433
1433
|
n ephemeral, tagged, pre-authorized key"):v("tailscale.authkey","pass","tailscale auth",X?"auth key set":"using persisted state"))}a(Qv(r.dashboardEnabled,n.PORTTA_DASHBOARD_BIND_ADDRESS||"127.0.0.1",n.PORTTA_DASHBOARD_PORT||"8080"));let D=n.PORTTA_WEB_BIND_ADDRESS||"127.0.0.1",V=n.PORTTA_WEB_PORT||"8081";r.webEnabled&&a(...eS({expose:n.PORTTA_WEB_EXPOSE||"local",bindAddress:D,port:V,authMode:n.PORTTA_AUTH_MODE||"disabled",secretPresent:!!n.PORTTA_AUTH_SECRET,readOnly:re(n.PORTTA_WEB_READ_ONLY),
|
|
1434
1434
|
allowLan:re(n.PORTTA_AUTH_ALLOW_LAN)})),a(n.PORTTA_AUTH_SECRET?v("auth.secret","pass","authentication signing secret","set"):v("auth.secret","fail","authentication signing secret","PORTTA_AUTH_SECRET is unset","portta bootstrap (generates it without printing it)"));let M=fs(g,"auth"),K=vn(o,"state/auth/protections.json");if(a(nS(Nr(K),Jn(K),!!M)),a(tS("auth.service","authentication service",!!M,M?.state??null,M?.health??null,"portta logs portta-auth")),r.profile==="remote-public"){M?.state!=="\
|
|
1435
1435
|
running"&&a(v("public.auth","fail","public host","portta-auth is not running, so every routed hostname is closed","portta up then portta logs portta-auth"));let j=An(g);j.length>0&&a(v("public.gate","fail","public host",`routed with no login gate, so open to the internet: ${j.join(", ")}`,"portta runtime down <path>, then portta adopt <path> and portta runtime up <path> to plan it behind the gate")),re(n.PORTTA_RUNNER_PUBLIC)&&a(v("public.runner","warn","public host","PORTTA_RUNNER_PUBLIC is o\
|
|
1436
|
-
n: a signed-in panel session can start, stop and remove projects","remove PORTTA_RUNNER_PUBLIC from .env to operate projects on the host only"));let X=
|
|
1436
|
+
n: a signed-in panel session can start, stop and remove projects","remove PORTTA_RUNNER_PUBLIC from .env to operate projects on the host only"));let X=UQ(o);X.length>0&&a(v("public.exposure","warn","public host",`routed with no decision, so closed: ${X.join(", ")}`,"portta adopt <path> --protect <service> or --public <service>, or portta protect host|open <host>"))}if(r.tcpEnabled){a(r.profile==="remote-public"?v("tcp.profile","fail","tcp entrypoints","enabled on the remote-public profile, whe\
|
|
1437
1437
|
re Traefik binds every interface","set PORTTA_TCP=false; reach databases over the VPN or a loopback bridge"):v("tcp.profile","pass","tcp entrypoints",`postgres :${n.PORTTA_TCP_POSTGRES_PORT||5432}, redis :${n.PORTTA_TCP_REDIS_PORT||6379} on ${r.bindAddress}`)),a(r.tlsEnabled?v("tcp.tls","pass","tcp tls",`certificates configured (${r.tlsMode})`):v("tcp.tls","warn","tcp tls","no certificate configured; Traefik will serve a self-signed one","sslmode=require works; for verify-full run: portta tls in\
|
|
1438
1438
|
it"));let j=y.filter(le=>Object.keys(le.labels).some(tn=>tn.startsWith("traefik.tcp.routers."))),X=j.filter(le=>le.networks.includes(r.network)).map(le=>le.name);a(X.length>0?v("tcp.network","fail","routed datastores",`on the shared HTTP network: ${X.join(" ")}`,`attach them to ${n.PORTTA_ACCESS_NETWORK||`${r.network}-access`} instead; see docs/product/guides/tcp-routing.md`):v("tcp.network","pass","routed datastores",`${j.length} routed, none on the shared network`))}else a(v("tcp.profile","pas\
|
|
1439
1439
|
s","tcp entrypoints","disabled"));if(r.webEnabled){let j=fs(g,"web");if(N){let le=j?Ew(j):"";a(le?v("web.bind","fail","web panel",`published directly on the host at ${le}, bypassing the authenticating entrypoint`,"remove the ports: entry; docker/compose/features/panel-public.yaml owns this port"):v("web.bind","pass","web panel",`reached only through Traefik's authenticated panel entrypoint on ${D}:${V}`))}else or(D)?a(v("web.bind","pass","web panel",`enabled on ${D}:${V} (loopback)`)):Jr(D)?a(v(
|
|
1440
1440
|
"web.bind","fail","web panel",`enabled and bound to ${D} with nothing authenticating it`,"portta config set panel.access public (or set PORTTA_WEB_BIND_ADDRESS=127.0.0.1)")):a(v("web.bind","pass","web panel",`enabled on ${D}:${V} (access: ${n.PORTTA_WEB_EXPOSE||"local"})`));if(n.PORTTA_WEB_EXPOSE==="vpn"&&r.profile==="remote-public"&&a(v("web.expose","fail","web panel routing","routed on the tailnet hostname while Traefik answers the internet","portta web up --expose domain, or set PORTTA_WEB_\
|
|
1441
1441
|
EXPOSE=local")),n.PORTTA_WEB_EXPOSE==="domain"){let le=n.PORTTA_PANEL_ADVERTISED_HOST??"";a(r.tlsEnabled?v("web.expose","pass","web panel routing",`routed on ${le} over HTTPS`):v("web.expose","fail","web panel routing","routed on the domain with TLS off, so the credential crosses in clear text","portta config set tls.enabled true"))}a(j?j.state==="running"?v("web.state","pass","web panel container",`${j.state} (${j.health??"none"})`):v("web.state","warn","web panel container",j.state,"portta web\
|
|
1442
1442
|
up"):v("web.state","warn","web panel container","not running","portta web up"));let X=fs(g,"web-socket-proxy");if(X){let le=Ew(X);a(le?v("web.proxy","fail","web panel socket proxy",`published on the host: ${le}`,"it must be reachable only from the panel; do not add a ports: entry to docker/compose/features/web.yaml"):v("web.proxy","pass","web panel socket proxy","unpublished, reachable only from the panel"))}}else a(v("web.bind","pass","web panel","disabled"));if(a(v("domain.mode","pass","proje\
|
|
1443
|
-
ct domain mode",`${r.domainMode} (*.${r.domain})`)),r.domainProblem&&a(v("domain.resolved","fail","project domain",r.domainProblem,"portta config set domain.mode auto")),a(...await
|
|
1443
|
+
ct domain mode",`${r.domainMode} (*.${r.domain})`)),r.domainProblem&&a(v("domain.resolved","fail","project domain",r.domainProblem,"portta config set domain.mode auto")),a(...await BQ(r,n)),r.tlsEnabled)if(r.tlsMode==="acme"){let j=r.acmeChallenge==="http";a(n.ACME_EMAIL?v("tls.acme","pass","ACME configuration",j?`${n.ACME_EMAIL} over HTTP-01`:`${n.ACME_EMAIL} via ${n.ACME_DNS_PROVIDER??""}`):v("tls.acme","fail","ACME configuration","ACME_EMAIL is not set","set ACME_EMAIL in .env")),j?(a(v("tls.\
|
|
1444
1444
|
acme.challenge","pass","ACME challenge","HTTP-01: one certificate per hostname, issued on first request")),a(r.bindAddress==="0.0.0.0"?v("tls.acme.reachable","pass","ACME reachability",":80 is bound on every interface"):v("tls.acme.reachable","fail","ACME reachability",`HTTP-01 needs :80 reachable from the internet, and Traefik binds ${r.bindAddress}`,"portta public enable, or use ACME_CHALLENGE=dns"))):(a(v("tls.acme.challenge","pass","ACME challenge",`DNS-01: one wildcard for *.${r.domain}`)),
|
|
1445
1445
|
a(n.CF_DNS_API_TOKEN?v("tls.acme.credential","pass","ACME DNS credential","CF_DNS_API_TOKEN is set"):v("tls.acme.credential","fail","ACME DNS credential","DNS-01 cannot issue anything without a provider credential","set CF_DNS_API_TOKEN, or use ACME_CHALLENGE=http for per-hostname certificates")));let X=vn(s,"traefik/acme/acme.json");if(Nr(X)){let le=Jn(X);a(le==="600"?v("tls.acme.perms","pass","ACME store permissions",le):v("tls.acme.perms","fail","ACME store permissions",`${le??"unknown"} is t\
|
|
1446
1446
|
oo permissive`,"chmod 600 state/traefik/acme/acme.json"))}else a(v("tls.acme.store","warn","ACME store","no certificate has been issued yet"))}else r.tlsMode==="local"?a(v("tls.local","pass","TLS","local certificate mode")):a(v("tls.mode","fail","TLS mode",`unknown TLS_MODE '${r.tlsMode}'`,"use TLS_MODE=local or acme"));else a(v("tls.disabled","pass","TLS","disabled (plain HTTP)"));let q=eo(y,r.domain,r.tlsEnabled?"https":"http");a(v("routes.count","pass","routed services",String(q.length)));let R=ef(
|
|
@@ -1451,71 +1451,71 @@ filter(j=>j.labels["portta.component"]==="access-bridge");a(v("access.bridges","
|
|
|
1451
1451
|
labels["portta.access.project"],le=j.labels["portta.access.service"];return!y.some(tn=>tn.labels["com.docker.compose.project"]===X&&tn.labels["com.docker.compose.service"]===le)}).map(j=>j.labels["portta.access.id"]??j.name);a(ks.length>0?v("access.stale","warn","stale access bridges",`target gone: ${ks.join(" ")}`,"portta access gc"):v("access.stale","pass","stale access bridges","none"));let _s=y.filter(j=>j.labels["portta.component"]==="access-forwarder"),Ma=_s.filter(j=>j.networks.includes(r.
|
|
1452
1452
|
network)).map(j=>j.labels["portta.forward.alias"]??j.name);a(Ma.length>0?v("access.forwarder.network","fail","published forwarders",`attached to the shared HTTP network: ${Ma.join(" ")}`,`a forwarder belongs on the project network and ${n.PORTTA_ACCESS_NETWORK||`${r.network}-access`} only`):v("access.forwarder.network","pass","published forwarders",`${_s.length} on the access network only`));let Ps=g.filter(j=>j.labels["portta.managed"]==="true"&&["exited","dead"].includes(j.state)).map(j=>j.name);
|
|
1453
1453
|
if(a(Ps.length>0?v("orphans","warn","stopped gateway containers",Ps.join(" "),`portta up ${r.profile} (or remove them explicitly)`):v("orphans","pass","stopped gateway containers","none")),r.webEnabled){let j=n.PORTTA_WEB_EXPOSE||"local";a(["local","tailscale","public","vpn","domain"].includes(j)?v("panel.access","pass","panel access",`${j} (bind ${D}:${V})`):v("panel.access","fail","panel access",`unknown mode '${j}'`,"portta config set panel.access public|tailscale|local"))}a(...p.filter(j=>j.
|
|
1454
|
-
id!=="runtime.docker"));let Hr=await fa("tailscale");if(!Hr)a(v("vpn.tailscale","warn","tailscale","not found","optional; the panel can also be reached publicly or over an SSH tunnel"));else{let j=await Aw(Hr,["ip","-4"]);a(j?v("vpn.tailscale","pass","tailscale",`connected (${j})`):v("vpn.tailscale","warn","tailscale","installed but not connected","tailscale up (run it yourself; Portta never authenticates it for you)"))}return t}i(EL,"runDoctor");async function
|
|
1454
|
+
id!=="runtime.docker"));let Hr=await fa("tailscale");if(!Hr)a(v("vpn.tailscale","warn","tailscale","not found","optional; the panel can also be reached publicly or over an SSH tunnel"));else{let j=await Aw(Hr,["ip","-4"]);a(j?v("vpn.tailscale","pass","tailscale",`connected (${j})`):v("vpn.tailscale","warn","tailscale","installed but not connected","tailscale up (run it yourself; Portta never authenticates it for you)"))}return t}i(EL,"runDoctor");async function BQ(e,t){let n=[],r=e.domain,o=t.
|
|
1455
1455
|
PORTTA_WEB_EXPOSE||"local";if(r==="localhost"||r.endsWith(".localhost"))return n.push(Kv(await PL("portta-probe.localhost"))),o!=="local"&&n.push(v("domain.reachable","warn","project hostnames","*.localhost only resolves on this machine, and the panel is reached from elsewhere","portta config set domain.mode auto")),n;n.push(v("dns.domain","pass","domain",r));let s=(await PL(`portta-probe.${r}`))[0];if(!s)n.push(v("dns.wildcard","fail","wildcard DNS",`*.${r} does not resolve`,"portta dns setup"));else if(Ka(
|
|
1456
1456
|
s))n.push(v("dns.wildcard","pass","wildcard DNS",`*.${r} -> ${s} (this machine)`));else{let u=t.PORTTA_PUBLIC_IP??"";n.push(u?s===u?v("dns.wildcard","pass","wildcard DNS",`*.${r} -> ${s} (this host)`):v("dns.wildcard","warn","wildcard DNS",`*.${r} -> ${s}, and this host is ${u}`,"normal behind a proxy or CDN that forwards here; otherwise point the wildcard at this host, or refresh the address: portta config set domain.mode auto"):v("dns.wildcard","pass","wildcard DNS",`*.${r} -> ${s}`))}let a=e.
|
|
1457
1457
|
bindAddress,c=s?Jv(r,s,a):null;if(c)n.push(c),o!=="local"&&n.push(v("domain.reachable.remote","warn","project hostnames",`*.${r} resolves to loopback, and the panel is reached from elsewhere`,"point the wildcard at this host, or portta config set domain.mode auto"));else if(or(a)){let u=t.PORTTA_PUBLIC_IP??"",p=u&&gD(u)?`portta config set gateway.bindAddress ${u} serves them on that network only`:"portta public enable exposes the HTTP services that opted in";n.push(v("domain.reachable","warn",
|
|
1458
|
-
"project hostnames",`*.${r} points here, but Traefik listens on ${a} only`,p))}else n.push(v("domain.reachable","pass","project hostnames",`*.${r}, served on ${a}`));return n}i(
|
|
1459
|
-
otections.json"))}catch{return[]}let r=[];for(let o of
|
|
1458
|
+
"project hostnames",`*.${r} points here, but Traefik listens on ${a} only`,p))}else n.push(v("domain.reachable","pass","project hostnames",`*.${r}, served on ${a}`));return n}i(BQ,"domainChecks");async function PL(e){try{let{resolve4:t,lookup:n}=await import("node:dns/promises");try{return await t(e)}catch{return(await n(e,{family:4,all:!0})).map(o=>o.address)}}catch{return[]}}i(PL,"resolveIpv4");function UQ(e){let t=vn(e,"runtime","compose");if(!Nr(t))return[];let n;try{n=Ze(vn(e,"state/auth/pr\
|
|
1459
|
+
otections.json"))}catch{return[]}let r=[];for(let o of NQ(t))try{let s=JSON.parse(LQ(vn(t,o,"plan.json"),"utf8"));for(let a of s.services??[])a.host&&!Ge(n,a.host)&&r.push(a.host)}catch{}return r}i(UQ,"undecidedHosts");import{existsSync as qQ}from"node:fs";import{join as AL}from"node:path";async function Ow(e){let t=await _("docker",["container","inspect",$s,"--format",`{{ index .Config.Labels "${e}" }}`],{reject:!1});return t.exitCode===0?t.stdout.trim():null}i(Ow,"label");async function HQ(){let e=await _("docker",["container","inspect",$s,"--format","{{ .State.Status }}"],{reject:!1});return e.exitCode===0?e.stdout.trim():null}i(HQ,"state");async function ms(){return await Ow("portta.managed")!=="true"||await HQ()==="running"?!1:(await _("docker",["rm","-f",$s],{reject:!1})).exitCode===
|
|
1460
1460
|
0}i(ms,"removeApplier");async function OL(e){let t=await Ow("portta.component")==="apply";if(!re(e.env.PORTTA_APPLY??"false"))return t?await ms()?{action:"removed"}:{action:"absent"}:{action:"absent"};let n=zv(e.env);if(n!==null)return t&&await ms(),{action:"refused",reason:n};let r=Mv(e.root,e.version);if(t){if(await Ow("portta.apply.spec")===r)return{action:"kept"};if(!await ms())return{action:"failed",reason:"the running applier could not be replaced"}}let o=AL(e.root,"docker","images","apply"),
|
|
1461
|
-
s=Se(e.version).apply;if(!
|
|
1462
|
-
"docker create failed"}}i(OL,"ensureApplier");import{existsSync as hs,readdirSync as
|
|
1463
|
-
n.name))}i(CL,"findDemoStacks");function RL(e,t){let n=e.files.flatMap(r=>["-f",r]);return t==="up"?["compose",...n,"up","-d"]:["compose",...n,"down","-v"]}i(RL,"demoComposeArgs");function
|
|
1464
|
-
return null}}i(
|
|
1465
|
-
ts create --slug ${a.slug} --path ${a.relativePath}`))}}i(
|
|
1466
|
-
lone the example repositories there, or set PORTTA_PROJECTS_HOME in .env to the directory that holds them")}i(sd,"requireDemoStacks");async function Cw(e,t){let n=jL(e),r=sd(e);n.step("demo stacks");for(let o of r)n.progress(`starting ${o.name}`),await _("docker",RL(o,"up"),{cwd:o.dir,stdio:"inherit"});await
|
|
1467
|
-
{cwd:r.dir,stdio:"inherit"})}}i(Rw,"demoStacksDown");function
|
|
1468
|
-
now()+t;for(;Date.now()<n;){if(await jw(e))return;await new Promise(r=>setTimeout(r,
|
|
1469
|
-
p",{..._n});a.status===409?n.progress("panel already has an owner"):a.ok?(n.progress(`created demo owner ${_n.email}`),o=!0):(await t.request("POST","/auth/setup",{..._n}),o=!0)}else n.progress("panel already has an owner");let s=await
|
|
1470
|
-
host:n},body:JSON.stringify({email:_n.email,password:_n.password}),signal:AbortSignal.timeout(15e3)});if(!r.ok)return;let o=r.headers.get("set-cookie")?.split(";")[0];if(!o)return;let s=await fetch(`${e}/api/auth/tokens`,{method:"POST",headers:{"content-type":"application/json",origin:t,host:n,cookie:o},body:JSON.stringify({name:"dev-demo",actorKind:"human"}),signal:AbortSignal.timeout(15e3)});if(!s.ok)return;let a=await s.json();return typeof a.token=="string"?a.token:void 0}catch{return}}i(
|
|
1471
|
-
"mintDevDemoToken");import{existsSync as
|
|
1461
|
+
s=Se(e.version).apply;if(!qQ(AL(o,"Dockerfile")))return{action:"failed",reason:`no applier image source at ${o}`};if((await _("docker",["image","inspect",s],{reject:!1})).exitCode!==0&&(await _("docker",["build","--build-arg",`PORTTA_VERSION=${e.version}`,"-t",s,o],{reject:!1,stdio:"stream"})).exitCode!==0)return{action:"failed",reason:`could not build ${s}`};let c=await _("docker",Lv(e.root,r,e.version),{reject:!1});return c.exitCode===0?{action:"created"}:{action:"failed",reason:c.stderr.trim()||
|
|
1462
|
+
"docker create failed"}}i(OL,"ensureApplier");import{existsSync as hs,readdirSync as ZQ,readFileSync as GQ}from"node:fs";import{basename as TL,join as Lr}from"node:path";var $L=".portta",Tw="compose.portta.yaml",$w="compose.yaml",WQ=12e4,VQ=500,KQ="portta-demo-",JQ="portta.example.json";function YQ(e){return hs(e)?ZQ(e,{withFileTypes:!0}).filter(t=>t.isDirectory()&&t.name.startsWith(KQ)).map(t=>Lr(e,t.name)).sort():[]}i(YQ,"demoDirectories");function CL(e){return YQ(e).map(t=>{if(!hs(Lr(t,$w)))return null;let n=Lr($L,Tw),r=hs(Lr(t,n))||hs(Lr(t,Tw));return{name:TL(t),dir:t,files:r?[$w,hs(Lr(t,n))?n:Tw]:[$w],overlay:r}}).filter(t=>t!==null).sort((t,n)=>t.name.localeCompare(
|
|
1463
|
+
n.name))}i(CL,"findDemoStacks");function RL(e,t){let n=e.files.flatMap(r=>["-f",r]);return t==="up"?["compose",...n,"up","-d"]:["compose",...n,"down","-v"]}i(RL,"demoComposeArgs");function XQ(e){let t=Lr(e,$L,JQ);if(!hs(t))return null;try{let r=JSON.parse(GQ(t,"utf8")).project;return typeof r?.slug!="string"||typeof r.name!="string"?null:{slug:r.slug,name:r.name,description:typeof r.description=="string"?r.description:null,relativePath:typeof r.relativePath=="string"?r.relativePath:TL(e)}}catch{
|
|
1464
|
+
return null}}i(XQ,"readDemoProject");async function QQ(e,t,n){let r=t.map(a=>XQ(a.dir)).filter(a=>a!==null);if(r.length===0)return;let{client:o,output:s}=de(e,{actor:void 0,actorKind:"human",...n?{token:n}:{}});for(let a of r){let c=await o.answer("POST","/projects",a);c.ok?s.progress(`registered Project ${a.name} (${a.slug})`):c.status===409?s.progress(`Project ${a.slug} already registered`):(s.warning(`could not register Project ${a.slug}: the panel answered ${c.status}`),s.hint(`portta projec\
|
|
1465
|
+
ts create --slug ${a.slug} --path ${a.relativePath}`))}}i(QQ,"registerDemoProjects");function jL(e){return new T(pa(e))}i(jL,"outputFor");function IL(e){let t=O({profile:pa(e).profile,required:!1}),n=t.env.HOME??process.env.HOME??"",r=t.env.PORTTA_PROJECTS_HOME?.trim()||qc(n,typeof process.getuid=="function"&&process.getuid()===0);return Hc(r,t.root,n)}i(IL,"demoHome");function sd(e){let t=IL(e),n=CL(t);if(n.length>0)return n;throw new L(`--demo found no portta-demo-* Compose project in ${t}`,"c\
|
|
1466
|
+
lone the example repositories there, or set PORTTA_PROJECTS_HOME in .env to the directory that holds them")}i(sd,"requireDemoStacks");async function Cw(e,t){let n=jL(e),r=sd(e);n.step("demo stacks");for(let o of r)n.progress(`starting ${o.name}`),await _("docker",RL(o,"up"),{cwd:o.dir,stdio:"inherit"});await QQ(e,r,t)}i(Cw,"demoStacksUp");async function Rw(e){let t=jL(e),n=CL(IL(e));if(n.length!==0){t.step("demo stacks");for(let r of n)t.progress(`stopping ${r.name}`),await _("docker",RL(r,"down"),
|
|
1467
|
+
{cwd:r.dir,stdio:"inherit"})}}i(Rw,"demoStacksDown");function eee(e){let t=O({profile:pa(e).profile,required:!1}),n=t.config.webExpose==="public"?"127.0.0.1":t.env.PORTTA_WEB_BIND_ADDRESS??"127.0.0.1",r=t.config.webPort||Number(t.env.PORTTA_WEB_PORT??8081);return`http://${n}:${r}/api/health`}i(eee,"panelHealthUrl");async function jw(e){try{let t=await fetch(eee(e),{signal:AbortSignal.timeout(3e3)});return t.ok||t.status===401}catch{return!1}}i(jw,"panelIsReachable");async function Iw(e,t=WQ){let n=Date.
|
|
1468
|
+
now()+t;for(;Date.now()<n;){if(await jw(e))return;await new Promise(r=>setTimeout(r,VQ))}throw new L("the panel did not become reachable in time","start it with `portta web up` or `portta dev`, then retry")}i(Iw,"waitForPanel");async function DL(e){let{client:t,output:n}=de(e,{actor:void 0,actorKind:"human"}),r=await t.request("GET","/auth/status");if(r.mode==="open"){n.progress("panel is open; demo owner is not needed");return}let o=!1;if(r.setupRequired){let a=await t.answer("POST","/auth/setu\
|
|
1469
|
+
p",{..._n});a.status===409?n.progress("panel already has an owner"):a.ok?(n.progress(`created demo owner ${_n.email}`),o=!0):(await t.request("POST","/auth/setup",{..._n}),o=!0)}else n.progress("panel already has an owner");let s=await tee(t.url);return(o||s)&&n.progress(`sign in as ${_n.email} / ${_n.password}`),s}i(DL,"ensureDevDemoOwner");async function tee(e){try{let t=e,n=new URL(e).host,r=await fetch(`${e}/api/auth/sign-in/email`,{method:"POST",headers:{"content-type":"application/json",origin:t,
|
|
1470
|
+
host:n},body:JSON.stringify({email:_n.email,password:_n.password}),signal:AbortSignal.timeout(15e3)});if(!r.ok)return;let o=r.headers.get("set-cookie")?.split(";")[0];if(!o)return;let s=await fetch(`${e}/api/auth/tokens`,{method:"POST",headers:{"content-type":"application/json",origin:t,host:n,cookie:o},body:JSON.stringify({name:"dev-demo",actorKind:"human"}),signal:AbortSignal.timeout(15e3)});if(!s.ok)return;let a=await s.json();return typeof a.token=="string"?a.token:void 0}catch{return}}i(tee,
|
|
1471
|
+
"mintDevDemoToken");import{existsSync as nee}from"node:fs";import{join as NL}from"node:path";async function Dw(e){let t=await _("docker",["container","inspect",ii,"--format",`{{ index .Config.Labels "${e}" }}`],{reject:!1});return t.exitCode===0?t.stdout.trim():null}i(Dw,"label");async function ree(){let e=await _("docker",["container","inspect",ii,"--format","{{ .State.Status }}"],{reject:!1});return e.exitCode===0?e.stdout.trim():null}i(ree,"state");async function gs(){return await Dw("portta.managed")!=="true"||await ree()==="running"?!1:(await _("docker",["rm","-f",ii],{reject:!1})).
|
|
1472
1472
|
exitCode===0}i(gs,"removeRunner");async function LL(e){let t=await Dw("portta.component")==="runner";if(!re(e.env.PORTTA_RUNNER??"false"))return t?await gs()?{action:"removed"}:{action:"absent"}:{action:"absent"};let n=GE(e.env);if(n!==null)return t&&await gs(),{action:"refused",reason:n};let r=ZE(e.root,e.version);if(t){if(await Dw("portta.runner.spec")===r)return{action:"kept"};if(!await gs())return{action:"failed",reason:"the running runner could not be replaced"}}let o=NL(e.root,"docker","im\
|
|
1473
|
-
ages","apply"),s=Se(e.version).apply;if(!
|
|
1474
|
-
stderr.trim()||"docker create failed"}}i(LL,"ensureRunner");function
|
|
1475
|
-
mpose",...we(s),...t],{cwd:s.root,env:s.env,stdio:n,reject:r.reject})}i(Xt,"compose");function Lw(e,t,n){try{Ha(e,t)}catch(r){n?.progress(`warn could not record the applied settings: ${r.message}`)}}i(Lw,"recordApplied");function Mw(e){let t=yt(e,".env");return me(Mr(t)?ML(t,"utf8"):"")}i(Mw,"envBeforeUp");function FL(e,t){let n=yt(e,"state/auth");
|
|
1476
|
-
"0"}.${t[1]??"0"}`}i(Nw,"series");async function
|
|
1477
|
-
n)`:"behind authentication"};if(!o.ok)return{version:n,detail:`unreachable (HTTP ${o.status})`};let s=await o.json();return{version:s.panelVersion??n,detail:s.panelVersion??"unknown"}}catch{return{version:n,detail:n?`${n} (from the image tag; the panel did not answer)`:"not running"}}}i(
|
|
1473
|
+
ages","apply"),s=Se(e.version).apply;if(!nee(NL(o,"Dockerfile")))return{action:"failed",reason:`no runner image source at ${o}`};if((await _("docker",["image","inspect",s],{reject:!1})).exitCode!==0&&(await _("docker",["build","--build-arg",`PORTTA_VERSION=${e.version}`,"-t",s,o],{reject:!1,stdio:"stream"})).exitCode!==0)return{action:"failed",reason:`could not build ${s}`};let c=await _("docker",HE(e.root,r,e.version),{reject:!1});return c.exitCode===0?{action:"created"}:{action:"failed",reason:c.
|
|
1474
|
+
stderr.trim()||"docker create failed"}}i(LL,"ensureRunner");function aee(){return{PORTTA_WEB:"true",PORTTA_WEB_DEV:"true",PORTTA_WEB_BUILD:"false",PORTTA_AUTH_IMAGE:"",PORTTA_WEB_IMAGE:""}}i(aee,"checkoutLocalEnv");function cee(e,t){let n=yt(e,".env");je(n,t)}i(cee,"persistEnv");function lee(e){let t=O({profile:fe(e).profile}).composeFiles;return t.includes(Kd)||t.includes(Jd)}i(lee,"buildsLocally");function fe(e){return e.optsWithGlobals()}i(fe,"globals");async function Xt(e,t,n="inherit",r={}){let o=fe(e),s=O({profile:o.profile});return _("docker",["co\
|
|
1475
|
+
mpose",...we(s),...t],{cwd:s.root,env:s.env,stdio:n,reject:r.reject})}i(Xt,"compose");function Lw(e,t,n){try{Ha(e,t)}catch(r){n?.progress(`warn could not record the applied settings: ${r.message}`)}}i(Lw,"recordApplied");function Mw(e){let t=yt(e,".env");return me(Mr(t)?ML(t,"utf8"):"")}i(Mw,"envBeforeUp");function FL(e,t){let n=yt(e,"state/auth");see(n,{recursive:!0,mode:448}),oee(n,448);let r=yt(e,".env");xt(r),Pa(e,t)}i(FL,"ensureAuthState");function Nw(e){let t=e.split(".");return`${t[0]??
|
|
1476
|
+
"0"}.${t[1]??"0"}`}i(Nw,"series");async function uee(e){let t=e.env.PORTTA_WEB_IMAGE??"",n=t.includes(":")?t.slice(t.lastIndexOf(":")+1):null;if(!e.config.webEnabled)return{version:null,detail:"disabled"};let r=e.config.webExpose==="public"?"127.0.0.1":e.env.PORTTA_WEB_BIND_ADDRESS??"127.0.0.1";try{let o=await fetch(`http://${r}:${e.config.webPort}/api/health`,{signal:AbortSignal.timeout(3e3)});if(o.status===401)return{version:n,detail:n?`${n} (from the image tag; the API is behind authenticatio\
|
|
1477
|
+
n)`:"behind authentication"};if(!o.ok)return{version:n,detail:`unreachable (HTTP ${o.status})`};let s=await o.json();return{version:s.panelVersion??n,detail:s.panelVersion??"unknown"}}catch{return{version:n,detail:n?`${n} (from the image tag; the panel did not answer)`:"not running"}}}i(uee,"panelReport");async function BL(e){let t=fe(e),n=new T(t),r=O({required:!1}),o=ur,s=r.version,a=Nw(o)===Nw(s);if(!n.json&&!r.composeFiles.length){n.data(ai());return}let c=await uee(r);if(n.json){n.data({cli:o,
|
|
1478
1478
|
built:Gc??null,gateway:s,panel:c.version,root:r.root,compatible:a,apiSeries:Nw(s)});return}n.line(ai()),n.line(` gateway ${s} (${r.root})`),n.line(` panel ${c.detail}`),a||(n.warning(`this CLI is ${o} and the installation is ${s}`),n.hint(`update the installation with portta setup, or install the matching CLI: npm install -g @codions/portta@${s}`))}i(BL,"versionCommand");async function zw(e,t){let n=fe(t),r=new T(n),o=O({profile:n.profile});if(r.step("checkout"),await Ct(),(await _("docke\
|
|
1479
1479
|
r",["compose","version","--short"],{reject:!1})).exitCode!==0)throw new _e("Docker Compose v2 is required",Fe.precondition);xt(yt(o.root,".env")),rs(o.root),FL(o.root,o.config.profile);let a=await Zt(o.config.network);r.progress(`${a.padEnd(8)} shared network ${o.config.network}`),e.skipPull||await Xt(t,["pull","--ignore-buildable"]),await Uw(t)}i(zw,"bootstrapCommand");async function Fw(e,t,n){e&&n.setOptionValueWithSource("profile",e,"cli"),xt(yt(O({profile:e??fe(n).profile}).root,".env")),t.localRelease&&
|
|
1480
1480
|
Tp(O({profile:e??fe(n).profile}));let r=O({profile:e??fe(n).profile});if(t.localRelease&&(r.env.PORTTA_LOCAL_RELEASE="true"),t.demo&&sd(n),r.config.profile==="remote-public"&&r.config.tcpEnabled)throw new U("TCP entrypoints must not run on the remote-public profile");if(r.config.profile==="remote-public"&&r.config.webEnabled&&r.config.webExpose==="vpn")throw new U("the panel must not be routed on the tailnet hostname while Traefik binds every interface","portta web up --expose domain routes it\
|
|
1481
|
-
on the gateway's own domain, behind the same login page");let o=new T(fe(n)),s=
|
|
1481
|
+
on the gateway's own domain, behind the same login page");let o=new T(fe(n)),s=lee(n);if(o.step("gateway components"),await Ct(),await Op(r),await Zt(r.config.network),r.config.tcpEnabled&&await Zt(r.config.accessNetwork),FL(r.root,r.config.profile),r.config.profile==="remote-public"){let f=await J(!0),m=An(f),h=DS(f),b="run portta runtime down <path>, then portta adopt and portta runtime up it again";if(m.length>0&&!h)throw new U(`these services route with no login gate, so starting a public g\
|
|
1482
1482
|
ateway would open them: ${m.join(", ")}`,b);m.length>0&&o.warning(`routed with no login gate, so open to the internet: ${m.join(", ")}. ${b}`)}let a=Mw(r.root);o.progress(s?"starting components, building local images":"starting components");let c=!t.attach,u=await Xt(n,["up",t.attach?"":"-d",...s?["--build"]:[],t.attach?"":"--remove-orphans",...c?["--wait","--wait-timeout","180"]:[]].filter(Boolean),"inherit",c?{reject:!1}:{});if(c&&u.exitCode!==0)throw new L("the gateway did not report healthy \
|
|
1483
1483
|
within 180s","portta logs shows what it is doing; portta doctor checks the rest");Lw(r.root,a,o),await qp(r.config.profile,o);let p=await OL(r);p.action==="created"&&o.progress("ok applier ready; the panel can apply settings without a terminal"),p.action==="removed"&&o.progress("ok applier removed (PORTTA_APPLY is false)"),p.action==="refused"&&o.progress(`warn not preparing the applier: ${p.reason}`),p.action==="failed"&&o.progress(`warn ${p.reason}; settings still apply w\
|
|
1484
1484
|
ith: portta up`);let d=await LL(r);d.action==="created"&&o.progress("ok runner ready; the panel can operate a project without a terminal"),d.action==="removed"&&o.progress("ok runner removed (PORTTA_RUNNER is false)"),d.action==="refused"&&o.progress(`warn not preparing the runner: ${d.reason}`),d.action==="failed"&&o.progress(`warn ${d.reason}; project operations still run from a shell`),t.demo&&(await jw(n)||await Ea({},n),await Iw(n),await Cw(n),await Ca({},n))}i(Fw,"upCom\
|
|
1485
1485
|
mand");async function Bw(e,t,n){e&&n.setOptionValueWithSource("profile",e,"cli");let r=O({profile:e??fe(n).profile,required:!1}),o=new T(fe(n));if(await xL(r.root,o)){await kL(r.root);return}t.demo&&sd(n);let s=!Mr(yt(r.root,".env"));o.progress(`dev runs: ${[...t.reset?["wipe Portta-managed containers and volumes"]:[],...s?["prepare the checkout"]:[],"start gateway components","start the panel","create the development owner",...t.demo?["start example stacks from Projects Home"]:[],"list routed h\
|
|
1486
|
-
ostnames"].join(" -> ")}`),t.reset&&await
|
|
1487
|
-
nelDatabaseArtefacts");var
|
|
1488
|
-
let n=new Map;for(let r of e){if(!
|
|
1489
|
-
await et(
|
|
1490
|
-
"docker",u,{cwd:p,stdio:"inherit"})}await Xt(e,["down","-v","--remove-orphans"]),await ms(),await gs(),_a(fe(e).profile,n);for(let a of await J()){if(a.labels["portta.managed"]!=="true")continue;let c=No(a.name,"container");(await _("docker",["rm","-f",c],{reject:!1})).exitCode===0&&n.progress(`removed ${c}`)}let o=0;for(let a of
|
|
1491
|
-
0&&n.progress(`cleared ${s.join(", ")}`)}i(
|
|
1486
|
+
ostnames"].join(" -> ")}`),t.reset&&await bee(n),s&&(n.setOptionValueWithSource("yes",!0,"cli"),await zw({skipPull:!0},n)),cee(O({profile:e??fe(n).profile}).root,aee());let a=lw({dev:!0},n);await Fw(e,{attach:!1},n),await Iw(n);let c=await DL(n);await uw(a,n,!1,c),t.demo&&await Cw(n,c),await Ca({},n)}i(Bw,"devCommand");async function UL(e,t){e.demo&&await Rw(t),await Xt(t,["down"]),await ms(),await gs(),_a(fe(t).profile,new T(fe(t)))}i(UL,"downCommand");function pee(e){return rr(Mt(e))}i(pee,"pa\
|
|
1487
|
+
nelDatabaseArtefacts");var dee=["state/metrics","state/environment"];function fee(e){let t=[];for(let n of dee){let r=yt(e,n);if(Mr(r)){for(let o of iee(r,{withFileTypes:!0}))zL(yt(r,o.name),{recursive:!0,force:!0});t.push(n)}}return t}i(fee,"clearRegenerableState");function mee(e,t){return e.labels["portta.managed"]==="true"||(e.labels["portta.project"]??"").trim()!==""||e.networks.includes(t.shared)?!0:!!(t.access&&e.networks.includes(t.access))}i(mee,"isPorttaOwnedContainer");function hee(e,t){
|
|
1488
|
+
let n=new Map;for(let r of e){if(!mee(r,{shared:t.sharedNetwork,access:t.accessNetwork}))continue;let o=r.labels["com.docker.compose.project"];!o||o===t.gatewayProject||n.has(o)||n.set(o,r.labels["com.docker.compose.project.working_dir"]||null)}return[...n.entries()].map(([r,o])=>({name:r,workingDir:o})).sort((r,o)=>r.name.localeCompare(o.name))}i(hee,"porttaOwnedComposeProjects");var gee="stop every Portta-managed stack, drop their volumes, and restart this checkout as if it were new?";async function bee(e){
|
|
1489
|
+
await et(gee,fe(e).yes===!0),await Ct();let t=O({profile:fe(e).profile}),n=new T(fe(e));n.step("Portta runtime"),await Rw(e);let r=await J();for(let a of hee(r,{gatewayProject:t.config.projectName,sharedNetwork:t.config.network,accessNetwork:t.config.accessNetwork})){let c=No(a.name,"compose project"),u=["compose","--project-name",c],p=a.workingDir&&Mr(a.workingDir)?a.workingDir:void 0;p&&u.push("--project-directory",p),u.push("down","--volumes","--remove-orphans"),n.progress(`stopping ${c}`),await _(
|
|
1490
|
+
"docker",u,{cwd:p,stdio:"inherit"})}await Xt(e,["down","-v","--remove-orphans"]),await ms(),await gs(),_a(fe(e).profile,n);for(let a of await J()){if(a.labels["portta.managed"]!=="true")continue;let c=No(a.name,"container");(await _("docker",["rm","-f",c],{reject:!1})).exitCode===0&&n.progress(`removed ${c}`)}let o=0;for(let a of pee(t.root))Mr(a)&&(zL(a,{force:!0}),o+=1);n.progress(o>0?`removed the panel database (${o} file(s))`:"the panel database was already absent");let s=fee(t.root);s.length>
|
|
1491
|
+
0&&n.progress(`cleared ${s.join(", ")}`)}i(bee,"wipePorttaRuntime");async function qL(e,t){await Bw(void 0,{reset:!0,demo:e.demo},t)}i(qL,"resetCommand");async function HL(e){let t=O({profile:fe(e).profile}).root,n=Mw(t);await Xt(e,["up","-d","--force-recreate","--wait","--wait-timeout","180"]),Lw(t,n)}i(HL,"restartCommand");async function ZL(e,t,n){let r=fe(n);if(r.json){let o=await Xt(n,["logs","--no-color","--no-log-prefix","--tail",t.tail??"200",...e?[e]:[]],"pipe");new T(r).data({lines:o.stdout.
|
|
1492
1492
|
split(`
|
|
1493
1493
|
`).filter(Boolean)})}else await Xt(n,["logs",...t.follow===!1?[]:["--follow"],"--tail",t.tail??"200",...e?[e]:[]])}i(ZL,"logsCommand");async function GL(e){xt(yt(O({profile:fe(e).profile}).root,".env")),await Xt(e,["config","--quiet"]),await Xt(e,["pull","--ignore-buildable"]),await et("recreate gateway components with the pulled images?",fe(e).yes===!0);let t=O({profile:fe(e).profile}).root,n=Mw(t);await Xt(e,["up","-d","--force-recreate","--wait","--wait-timeout","180"]),Lw(t,n)}i(GL,"updateCo\
|
|
1494
1494
|
mmand");async function WL(e){let t=fe(e),n=O({profile:t.profile}),r=new T(t),o=new Set(["TS_AUTHKEY","CF_DNS_API_TOKEN","PORTTA_AUTH_SECRET"]),s=Object.fromEntries(Object.entries(n.env).filter(([a])=>a.startsWith("PORTTA_")||["TLS_ENABLED","TLS_MODE","PUBLIC_DOMAIN","PRIVATE_DOMAIN","TAILSCALE_ENABLED"].includes(a)).map(([a,c])=>[a,o.has(a)?c?"<set>":"<unset>":c]));if(r.json)r.data({profile:n.config.profile,configuration:s,composeFiles:n.composeFiles});else{r.line(`profile: ${n.config.profile}`);
|
|
1495
1495
|
for(let[a,c]of Object.entries(s).sort())r.line(`${a}=${c}`);r.line(`compose files: ${n.composeFiles.join(", ")}`)}}i(WL,"inspectCommand");async function VL(e){let t=fe(e),n=O({profile:t.profile}),r=await J(),o=eo(r,n.config.domain,n.config.tlsEnabled?"https":"http"),s=r.filter(u=>u.labels["portta.managed"]==="true"),a={version:n.version,instance:{name:n.config.projectName},profile:n.config.profile,domain:n.config.domain,bindAddress:n.config.bindAddress,network:{name:n.config.network,exists:await Lg(
|
|
1496
1496
|
n.config.network)},components:s.map(u=>({name:u.name,state:u.state,component:u.labels["portta.component"]??null})),projectCount:Ns(r,n.config.domain,n.config.tlsEnabled?"https":"http").length,routeCount:o.length,tls:n.config.tlsEnabled,public:n.config.publicEnabled},c=new T(t);if(c.json)c.data(a);else{c.line(`portta ${a.version} \xB7 ${a.profile} \xB7 ${a.domain}`),c.line(`network ${a.network.exists?"ready":"missing"} \xB7 ${a.components.length} components \xB7 ${a.routeCount} routes`);for(let u of a.
|
|
1497
|
-
components)c.line(`${u.component??u.name} ${u.state}`)}}i(VL,"statusCommand");function
|
|
1497
|
+
components)c.line(`${u.component??u.name} ${u.state}`)}}i(VL,"statusCommand");function yee(e){return e.map(t=>({line:`${t.status==="pass"?"ok ":t.status==="info"?"info":t.status==="warn"?"warn":"FAIL"} ${t.message}`,...t.fix&&t.status!=="pass"?{hint:t.fix}:{}}))}i(yee,"doctorReport");async function Uw(e){let t=fe(e),n=O({profile:t.profile}),r=(await EL(n)).map(c=>({id:c.id,status:c.status,message:`${c.title}: ${c.detail}`,...c.fix?{fix:c.fix}:{}}));for(let c of n.composeFiles)r.push({id:`compos\
|
|
1498
1498
|
e:${c}`,status:Mr(yt(n.root,c))?"pass":"fail",message:`${c} exists`});let o=KL(n.root);if(o.length>0){let c=new Set((await J()).map(p=>p.name)),u=o.filter(p=>!c.has(p.container));r.push(u.length===0?{id:"aliases",status:"pass",message:`${o.length} hostname alias(es) routed`}:{id:"aliases",status:"fail",message:`alias target missing: ${u.map(p=>`${p.host} -> ${p.container}`).join(", ")}`,fix:"remove the alias in the panel, or start the environment again"})}let s=r.filter(c=>c.status==="fail"),a=new T(
|
|
1499
|
-
t);if(a.json)a.data({ok:s.length===0,instance:{name:n.config.projectName},checks:r});else for(let c of
|
|
1499
|
+
t);if(a.json)a.data({ok:s.length===0,instance:{name:n.config.projectName},checks:r});else for(let c of yee(r))a.line(c.line),c.hint&&a.hint(c.hint);if(s.length)throw new _e(`${s.length} doctor check(s) failed`)}i(Uw,"doctorCommand");function KL(e){let t=yt(e,"config/traefik/dynamic/portta-aliases.yaml");if(!Mr(t))return[];try{return Wr(ML(t,"utf8"))}catch{return[]}}i(KL,"readAliases");async function Ca(e,t){let n=fe(t),r=O({profile:n.profile}),o=r.config.tlsEnabled?"https":"http",s=eo(await J(),
|
|
1500
1500
|
r.config.domain,o).map(p=>({...p,alias:!1})),a=KL(r.root).map(p=>({project:p.project,service:p.service,container:p.container,hostname:p.host,url:`${o}://${p.host}`,port:String(p.port),state:"alias",alias:!0})),c=[...s,...a].filter(p=>!e.project||p.project===e.project).sort((p,d)=>p.hostname.localeCompare(d.hostname)),u=new T(n);if(u.json)u.data({instance:{name:r.config.projectName},routes:c});else for(let p of c)u.line(`${p.url} ${p.project??"-"} ${p.service??p.container}${p.alias?" alias":""}`)}
|
|
1501
|
-
i(Ca,"urlsCommand");import{chmodSync as zr,copyFileSync as
|
|
1502
|
-
`}i(
|
|
1503
|
-
o=r.stdout.trim();return r.failed||!o||(await _(o,[n,`VACUUM INTO '${t.replaceAll("'","''")}'`],{reject:!1})).failed||!Dt(t)?!1:(zr(t,384),!0)}i(
|
|
1504
|
-
replace(/\.\d+Z$/,"Z"),host:
|
|
1505
|
-
d)}if(f.failed)throw new L(`could not write ${a}`,f.stderr.trim());let m=
|
|
1506
|
-
"T"],n=e,r=0;for(;n>=1024&&r<t.length-1;)n/=1024,r+=1;return`${r===0?n:n.toFixed(1)}${t[r]}`}i(
|
|
1507
|
-
that archive has no Portta manifest");let p=
|
|
1501
|
+
i(Ca,"urlsCommand");import{chmodSync as zr,copyFileSync as wee,cpSync as qw,existsSync as Dt,mkdirSync as id,mkdtempSync as YL,readFileSync as vee,rmSync as Hw,statSync as See,writeFileSync as xee}from"node:fs";import{hostname as kee,tmpdir as XL}from"node:os";import{dirname as QL,join as ve}from"node:path";function Zw(e){return e.optsWithGlobals()}i(Zw,"globals");var eM=1;function tM(e){return[".env","VERSION","config","state"].filter(t=>Dt(ve(e,t)))}i(tM,"backupPaths");function _ee(e){return`${JSON.stringify(e)}
|
|
1502
|
+
`}i(_ee,"renderManifest");function Pee(e){try{let t=JSON.parse(e);return t.version!==eM||typeof t.portta!="string"||typeof t.created!="string"||typeof t.host!="string"?null:t}catch{return null}}i(Pee,"parseManifest");async function JL(e){let t=await _("docker",["inspect","-f","{{.State.Running}}",e],{reject:!1});return!t.failed&&t.stdout.trim()==="true"}i(JL,"containerRunning");async function Eee(e,t){let n=Mt(e.root);if(!Dt(n))return!1;let r=await _("sh",["-c","command -v sqlite3"],{reject:!1}),
|
|
1503
|
+
o=r.stdout.trim();return r.failed||!o||(await _(o,[n,`VACUUM INTO '${t.replaceAll("'","''")}'`],{reject:!1})).failed||!Dt(t)?!1:(zr(t,384),!0)}i(Eee,"dumpDatabase");async function nM(e,t){let n=Zw(t),r=new T(n),o=O({profile:n.profile}),s=new Date().toISOString().replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z"),a=e.output??ve(o.root,`portta-backup-${s}.tar.gz`),c=YL(ve(XL(),"portta-backup-"));zr(c,448);try{xee(ve(c,"portta-backup.json"),_ee({version:eM,portta:o.version,created:new Date().toISOString().
|
|
1504
|
+
replace(/\.\d+Z$/,"Z"),host:kee()||"unknown"}));let u=tM(o.root);for(let h of u)id(ve(c,"tree",QL(h)),{recursive:!0}),qw(ve(o.root,h),ve(c,"tree",h),{recursive:!0});let p=!1;e.database!==!1&&(p=await Eee(o,ve(c,"panel.db")),p||(r.warning("the panel database was not included"),r.hint("it exists once the panel has started, and copying it needs sqlite3 on this host; --no-database silences this")));let d=process.umask(63),f;try{f=await _("tar",["-czf",a,"-C",c,"."],{reject:!1})}finally{process.umask(
|
|
1505
|
+
d)}if(f.failed)throw new L(`could not write ${a}`,f.stderr.trim());let m=See(a).size;if(r.json){r.data({file:a,size:m,paths:u,database:p});return}r.progress("backup written"),r.line(` file ${a}`),r.line(` size ${Aee(m)}`),r.line(` contents ${u.length} path(s)${p?" + database":""}`),r.line(""),r.warning("this archive contains credentials: .env, the panel password hash and any tokens")}finally{Hw(c,{recursive:!0,force:!0})}}i(nM,"backupCommand");function Aee(e){let t=["B","K","M","G",
|
|
1506
|
+
"T"],n=e,r=0;for(;n>=1024&&r<t.length-1;)n/=1024,r+=1;return`${r===0?n:n.toFixed(1)}${t[r]}`}i(Aee,"humanSize");async function rM(e,t,n){let r=Zw(n),o=new T(r),s=O({profile:r.profile});if(!e)throw new C("which backup?","portta restore <file>");if(!Dt(e))throw new C(`no such file: ${e}`);let a=YL(ve(XL(),"portta-restore-"));zr(a,448);try{if((await _("tar",["-xzf",e,"-C",a],{reject:!1})).failed)throw new C("that file is not a Portta backup");let u=ve(a,"portta-backup.json");if(!Dt(u))throw new C("\
|
|
1507
|
+
that archive has no Portta manifest");let p=Pee(vee(u,"utf8"));if(!p)throw new C("that archive has an unreadable Portta manifest");if(o.progress(`restoring a backup taken from Portta ${p.portta}`),!t.force&&await JL(`${s.env.PORTTA_PROJECT_NAME||"portta"}-traefik-1`))throw new L("the gateway is running","portta down, then restore; or pass --force to replace configuration underneath it");let d=new Date().toISOString().replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z"),f=ve(s.root,"state",`restore-${d}`);
|
|
1508
1508
|
id(f,{recursive:!0});for(let b of[".env","config"])Dt(ve(s.root,b))&&qw(ve(s.root,b),ve(f,b),{recursive:!0});o.progress(`kept what was there under ${f}`);let m=ve(a,"tree");if(Dt(m)){for(let b of tM(m))qw(ve(m,b),ve(s.root,b),{recursive:!0,force:!0});o.progress("configuration and state restored")}Dt(ve(s.root,".env"))&&zr(ve(s.root,".env"),384);let h=ve(a,"panel.db");if(Dt(h)){let b=await JL(`${s.env.PORTTA_PROJECT_NAME||"portta"}-web-1`),g=Mt(s.root);if(b)o.warning("the panel is running, so its\
|
|
1509
|
-
database was not replaced"),o.hint(`portta web down then: portta restore ${e} --force`);else{id(QL(g),{recursive:!0});for(let y of rr(g))Hw(y,{force:!0});
|
|
1510
|
-
ed",mode:448},{path:"state/cloudflared/credentials.json",mode:384},{path:"state/runner",mode:448},{path:"state/ssh",mode:448},{path:"state/auth",mode:448}];async function oM(e,t){let n=Zw(t),r=new T(n),o=O({profile:n.profile}),s=e.dryRun??!1,a=[];r.progress("Repair");for(let{path:p,mode:d}of Ly){let f=ve(o.root,p);if(!Dt(f)){if(a.push(`create ${p}`),s){r.line(` would create ${p}`);continue}id(f,{recursive:!0}),zr(f,d),r.progress(`created ${p}`)}}for(let{path:p,mode:d}of
|
|
1509
|
+
database was not replaced"),o.hint(`portta web down then: portta restore ${e} --force`);else{id(QL(g),{recursive:!0});for(let y of rr(g))Hw(y,{force:!0});wee(h,g),zr(g,384),o.progress("panel database restored")}}o.line(""),o.progress("restore complete"),o.hint("portta up then portta doctor")}finally{Hw(a,{recursive:!0,force:!0})}}i(rM,"restoreCommand");var Oee=[{path:".env",mode:384},{path:"state/traefik/acme",mode:448},{path:"state/traefik/acme/acme.json",mode:384},{path:"state/cloudflar\
|
|
1510
|
+
ed",mode:448},{path:"state/cloudflared/credentials.json",mode:384},{path:"state/runner",mode:448},{path:"state/ssh",mode:448},{path:"state/auth",mode:448}];async function oM(e,t){let n=Zw(t),r=new T(n),o=O({profile:n.profile}),s=e.dryRun??!1,a=[];r.progress("Repair");for(let{path:p,mode:d}of Ly){let f=ve(o.root,p);if(!Dt(f)){if(a.push(`create ${p}`),s){r.line(` would create ${p}`);continue}id(f,{recursive:!0}),zr(f,d),r.progress(`created ${p}`)}}for(let{path:p,mode:d}of Oee){let f=ve(o.root,p);
|
|
1511
1511
|
if(!Dt(f))continue;let m=Jn(f),h=d.toString(8);if(!(!m||m===h)){if(a.push(`chmod ${p} ${h}`),s){r.line(` would change ${p} from ${m} to ${h}`);continue}zr(f,d),r.progress(`${p} is now ${h} (was ${m})`)}}let c=[o.env.PORTTA_NETWORK||"portta"];re(o.env.PORTTA_TCP)&&c.push(o.env.PORTTA_ACCESS_NETWORK||"portta-access");for(let p of c){if(!(await _("docker",["network","inspect",p],{reject:!1})).failed)continue;if(a.push(`create network ${p}`),s){r.line(` would create network ${p}`);continue}(await _(
|
|
1512
1512
|
"docker",["network","create","--label","portta.managed=true",p],{reject:!1})).failed?r.warning(`could not create network ${p}`):r.progress(`created network ${p}`)}if(s){if(r.line(""),r.json){r.data({dryRun:!0,changes:a});return}r.progress(a.length===0?"nothing to repair":`${a.length} thing(s) would be repaired`);return}if(r.progress("reconciling containers"),(await _("docker",["compose",...we(o),"up","-d","--remove-orphans"],{cwd:o.root,env:o.env,stdio:"inherit",reject:!1})).failed)throw new L("\
|
|
1513
|
-
the gateway did not come up","portta doctor");if(r.line(""),r.json){r.data({dryRun:!1,changes:a});return}r.progress(a.length===0?"nothing needed repairing; containers reconciled":`${a.length} thing(s) repaired; containers reconciled`),r.hint("portta doctor confirms the result")}i(oM,"repairCommand");import{lookup as
|
|
1513
|
+
the gateway did not come up","portta doctor");if(r.line(""),r.json){r.data({dryRun:!1,changes:a});return}r.progress(a.length===0?"nothing needed repairing; containers reconciled":`${a.length} thing(s) repaired; containers reconciled`),r.hint("portta doctor confirms the result")}i(oM,"repairCommand");import{lookup as Tee}from"node:dns/promises";import{join as $ee}from"node:path";function Xn(e){return e.optsWithGlobals()}i(Xn,"globals");async function sM(e,t){let n=Xn(t),r=O({profile:n.profile}),s=(await J()).flatMap(p=>p.ports.filter(d=>d.publicPort!==null).map(d=>({container:p.name,ip:d.ip,hostPort:d.publicPort,containerPort:d.privatePort,protocol:d.type}))),a=null;if(e.publicIp)try{let p=await fetch("https://api.ipify.org",{signal:AbortSignal.timeout(3e3)});a=p.ok?await p.text():null}catch{}let c={instance:{name:r.config.projectName},bindAddress:r.config.bindAddress,publicIp:a,
|
|
1514
1514
|
bindings:s,publicBindings:s.filter(p=>["0.0.0.0","::"].includes(p.ip))},u=new T(n);if(u.json)u.data(c);else{u.line(`gateway bind: ${c.bindAddress}`),a&&u.line(`public ip: ${a}`);for(let p of s)u.line(`${p.ip}:${p.hostPort} ${p.container} ${p.containerPort}/${p.protocol}`)}}i(sM,"networkStatus");async function iM(e){let t=Xn(e),n=O({profile:t.profile}),r={enabled:n.config.publicEnabled,profile:n.config.profile,domain:n.config.publicDomain,bindAddress:n.config.bindAddress},o=new T(t);o.json?o.data(
|
|
1515
|
-
r):o.line(r.enabled?`enabled on ${r.domain??"<unset>"}`:"disabled")}i(iM,"publicStatus");async function Ra(e,t,n){let r=O({profile:Xn(n).profile}),o
|
|
1515
|
+
r):o.line(r.enabled?`enabled on ${r.domain??"<unset>"}`:"disabled")}i(iM,"publicStatus");async function Ra(e,t,n){let r=O({profile:Xn(n).profile}),o=$ee(r.root,".env");je(o,{[e]:t})}i(Ra,"writeSetting");async function aM(e){let t=Xn(e),n=O({profile:t.profile}),r=n.config.publicDomain??(n.config.domainMode!=="local"&&n.config.domain!=="localhost"?n.config.domain:null);if(!r)throw new L("public access needs a domain, and this host has only localhost","portta config set domain.mode auto derives o\
|
|
1516
1516
|
ne from this host's address");if(n.config.tcpEnabled)throw new U("public access cannot be enabled while TCP entrypoints are active");let o=An(await J(!0));if(o.length>0)throw new U(`these running services route with no login gate, so they would be open on a public host: ${o.join(", ")}`,"stop each project (portta runtime down <path>), enable public access, then portta adopt and portta runtime up it again");await et(`serve this host's HTTP services on *.${r} over the internet? Each site stays clo\
|
|
1517
1517
|
sed until you decide who may open it`,t.yes===!0),await Ra("PUBLIC_ENABLED","true",e),n.config.publicDomain||await Ra("PUBLIC_DOMAIN",r,e),await Ra("PORTTA_PROFILE","remote-public",e);let s=O({profile:"remote-public"});await _("docker",["compose",...we(s),"up","-d"],{cwd:s.root,env:s.env,stdio:"inherit"})}i(aM,"publicEnable");async function cM(e){await Ra("PUBLIC_ENABLED","false",e),await Ra("PORTTA_PROFILE","remote-private",e),new T(Xn(e)).progress("public access disabled; run portta up to appl\
|
|
1518
|
-
y the private profile")}i(cM,"publicDisable");async function
|
|
1518
|
+
y the private profile")}i(cM,"publicDisable");async function Cee(e){try{return[...new Set((await Tee(e,{all:!0})).map(t=>t.address))]}catch{return[]}}i(Cee,"resolved");async function lM(e){let t=Xn(e),n=O({profile:t.profile}),r=n.config.publicDomain??n.config.privateDomain??n.config.domain,o=`probe.${r}`,s=await Cee(o),a={domain:r,hostname:o,addresses:s,resolves:s.length>0},c=new T(t);if(c.json?c.data(a):c.line(a.resolves?`${o} -> ${s.join(", ")}`:`${o} does not resolve`),!a.resolves)throw new L(
|
|
1519
1519
|
`wildcard DNS does not resolve for ${r}`)}i(lM,"dnsCheck");async function uM(e){let t=Xn(e),n=O({profile:t.profile}),r={enabled:n.env.CLOUDFLARE_ENABLED==="true",zone:n.env.CLOUDFLARE_ZONE??null,domain:n.config.publicDomain??n.config.privateDomain??n.config.domain,tokenSet:!!n.env.CLOUDFLARE_API_TOKEN},o=new T(t);if(o.json)o.data(r);else for(let[s,a]of Object.entries(r))o.line(`${s}: ${String(a)}`)}i(uM,"dnsStatus");async function Gw(e,t,n){let r=await fetch(`https://api.cloudflare.com/client/v4${e}`,
|
|
1520
1520
|
{...n,headers:{authorization:`Bearer ${t}`,"content-type":"application/json",...n?.headers??{}},signal:AbortSignal.timeout(1e4)}),o=await r.json();if(!r.ok||!o.success)throw new L(o.errors?.[0]?.message??`Cloudflare returned HTTP ${r.status}`);return o.result}i(Gw,"cloudflare");async function pM(e,t){let n=Xn(t),r=O({profile:n.profile}),o=r.env.CLOUDFLARE_ZONE,s=r.env.CLOUDFLARE_API_TOKEN,a=r.config.publicDomain??r.config.privateDomain;if(!o||!a)throw new L("CLOUDFLARE_ZONE and PUBLIC_DOMAIN or \
|
|
1521
1521
|
PRIVATE_DOMAIN are required");let c=e.target;if(!c)throw new C("--target <ip> is required");let u={type:"A",name:`*.${a}`,content:c,ttl:1,proxied:!1},p=new T(n);if(e.dryRun||!s){if(p.data(u),!s&&!e.dryRun)throw new L("CLOUDFLARE_API_TOKEN is not set","create the printed record manually or set a scoped Zone:DNS:Edit token");return}await et(`create or update ${u.name} -> ${c} in Cloudflare?`,n.yes===!0);let d=await Gw(`/zones?name=${encodeURIComponent(o)}`,s);if(!d[0])throw new L(`Cloudflare zone \
|
|
@@ -1523,38 +1523,38 @@ not found: ${o}`);let f=await Gw(`/zones/${d[0].id}/dns_records?type=A&name=${en
|
|
|
1523
1523
|
ts/${ns(e)}`);if(r.json)return r.data(o);if(r.line(`${o.name} (${o.slug})${o.archived?" \xB7 archived":""}`),o.description&&r.line(` ${o.description}`),o.resolvedPath&&r.line(` ${o.resolvedPath} \xB7 ${o.location}`),o.environments.length>0){r.line(" environments:");for(let s of o.environments)r.line(` ${s.environment.padEnd(24)} ${s.running?`${s.runningCount}/${s.serviceCount} running`:"stopped"}${s.unhealthyCount?` \xB7 ${s.unhealthyCount} unhealthy`:""} [${s.source}]`)}}i(fM,"projectsSh\
|
|
1524
1524
|
ow");async function mM(e,t){let{client:n,output:r}=de(t),o=e.name??e.slug,s=e.slug??o?.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,""),a=await n.request("POST","/projects",{slug:s,name:o,description:e.description??null,...e.path?{relativePath:e.path}:{}});if(r.json)return r.data(a);r.progress(`created ${a.name} (${a.slug})`)}i(mM,"projectsCreate");async function hM(e,t){let{client:n,output:r}=de(t),o=await n.request("GET",`/projects/${ns(e)}/resources`);if(r.json)return r.data(o);o.
|
|
1525
1525
|
collectorActive||r.warning("the metrics collector is not running: `portta host watch`");let s=i(c=>c===null?"-":`${Math.round(c/1048576)} MB`,"mb"),a=i(c=>c===null?"-":`${Math.round(c)}%`,"pct");r.line(`${o.project}: CPU ${a(o.cpuUtilisation)} \xB7 RAM ${s(o.memoryUsedBytes)}${o.stale?" (stale)":""}`);for(let c of o.environments){r.line(` ${c.environment}: CPU ${a(c.cpuUtilisation)} \xB7 RAM ${s(c.memoryUsedBytes)}`);for(let u of c.containers)r.line(` ${(u.service??u.name).padEnd(20)} ${a(u.
|
|
1526
|
-
cpuUtilisation).padStart(5)} ${s(u.memoryUsedBytes)}`)}}i(hM,"projectsResources");async function gM(e,t,n){let{client:r,output:o}=de(n),s=await r.request("GET",`/environments/${ns(e)}/logs${nD({service:t.service,tail:t.tail})}`);if(o.json)return o.data(s);for(let a of s.lines)o.line(`${a.service.padEnd(12)} | ${a.line}`)}i(gM,"envLogs");import{readFileSync as
|
|
1527
|
-
!0?null:t.user??"reviewer";if(o!==null&&!/^[A-Za-z0-9._-]{1,64}$/.test(o))throw new C(`invalid username: ${o}`);let s=bM(n,t.entrypoint),a=t.passwordStdin!==!0,c=a?op():
|
|
1526
|
+
cpuUtilisation).padStart(5)} ${s(u.memoryUsedBytes)}`)}}i(hM,"projectsResources");async function gM(e,t,n){let{client:r,output:o}=de(n),s=await r.request("GET",`/environments/${ns(e)}/logs${nD({service:t.service,tail:t.tail})}`);if(o.json)return o.data(s);for(let a of s.lines)o.line(`${a.service.padEnd(12)} | ${a.line}`)}i(gM,"envLogs");import{readFileSync as Ree}from"node:fs";function Sn(e){return e.optsWithGlobals()}i(Sn,"globals");function bM(e,t){let n=t??(O({profile:Sn(e).profile}).config.tlsEnabled?"websecure":"web");if(!/^[A-Za-z0-9_-]+$/.test(n))throw new C(`invalid entrypoint: ${n}`);return n}i(bM,"entryPointFor");function Ww(e){if(!e)return null;let{hash:t,...n}=e;return n}i(Ww,"publicRecord");async function yM(e,t,n){let r=dt(e);if(t.passwordOnly===!0&&t.user!==void 0)throw new C("--password-only and --user ask for opposite things: pick one");let o=t.passwordOnly===
|
|
1527
|
+
!0?null:t.user??"reviewer";if(o!==null&&!/^[A-Za-z0-9._-]{1,64}$/.test(o))throw new C(`invalid username: ${o}`);let s=bM(n,t.entrypoint),a=t.passwordStdin!==!0,c=a?op():Ree(0,"utf8").trim();if(!c)throw new C("no password on stdin");let u=O({profile:Sn(n).profile}),p=u.root,d=await sp(Ze(Pr(p).store),{host:r,entryPoint:s,user:o,password:c,...t.label?{label:t.label}:{},...t.project?{project:t.project}:{},...t.service?{service:t.service}:{}});Jo(p,d,u.config.profile);let f=new T(Sn(n)),m={protection:Ww(
|
|
1528
1528
|
Ge(d,r)),generated:a,...a?{password:c}:{}};f.json?f.data(m):(f.line(`protected: ${r}`),f.line(o===null?"password only: no username is asked for":`user: ${o}`),a&&(f.line(`password: ${c}`),f.warning("this is the only time the generated password is shown")),f.hint("on a public host this takes effect at once; elsewhere add portta-forward-auth@file to the router"))}i(yM,"protectHost");async function wM(e,t,n){let r=dt(e),o=O({profile:Sn(n).profile}),s=o.root,a=ip(Ze(Pr(s).store),{host:r,entryPoint:bM(
|
|
1529
1529
|
n,t.entrypoint),...t.label?{label:t.label}:{},...t.project?{project:t.project}:{},...t.service?{service:t.service}:{}});Jo(s,a,o.config.profile);let c=new T(Sn(n));c.json?c.data({protection:Ww(Ge(a,r))}):(c.line(`open to everybody: ${r}`),c.warning("no login is asked for this host; `portta protect host` puts one back"))}i(wM,"openHost");async function vM(e,t){let n=dt(e),r=O({profile:Sn(t).profile}),o=r.root,s=dI(Ze(Pr(o).store),n);if(!s)throw new C(`host has no protection record: ${n}`);Jo(o,s,
|
|
1530
|
-
r.config.profile),new T(Sn(t)).progress(`removed the record for ${n}; on a public host it is now closed`)}i(vM,"unprotectHost");async function SM(e,t){let r=O({profile:Sn(t).profile}).root,o=Ze(Pr(r).store),a=(e?[Ge(o,dt(e))].filter(u=>u!==null):o.protections).map(Ww),c=new T(Sn(t));if(c.json)c.data({protections:a});else if(!a.length)c.progress("no matching hosts");else for(let u of a)c.line(`${u.host} ${u.mode} ${u.user??"-"} ${u.scope} epoch ${u.epoch}`)}i(SM,"protectStatus");import{isIP as
|
|
1531
|
-
put is not a valid API token");return t}i(
|
|
1532
|
-
nel-host must be a lowercase hostname: ${r}`);if(r!==t&&(!r.endsWith(`.${t}`)||r.split(".").length!==t.split(".").length+1))throw new C(`--panel-host must be ${t} or one label under it, covered by *.${t}: ${r}`);let o=e.ip===void 0?0:
|
|
1533
|
-
TLS_ENABLED:"true",TLS_MODE:"acme",ACME_EMAIL:n,ACME_DNS_PROVIDER:"cloudflare",PORTTA_WEB:"true",PORTTA_WEB_EXPOSE:"domain",PORTTA_PANEL_ADVERTISED_HOST:r,PORTTA_PANEL_URL:`https://${r}`,PORTTA_AUTH_MODE:"required"},records:[{type:s,name:t,content:a,proxied:!1},{type:s,name:`*.${t}`,content:a,proxied:!1}]}}i(
|
|
1534
|
-
config.tcpEnabled)throw new U("public access cannot be configured while TCP entrypoints are active");let u=[];try{u=await J(!0)}catch(w){if(!c)throw w}let p=An(u);if(p.length>0)throw new U(`these running services route with no login gate, so they would be open on a public host: ${p.join(", ")}`,"stop each project (portta runtime down <path>), configure public access, then portta adopt and portta runtime up it again");let d=
|
|
1530
|
+
r.config.profile),new T(Sn(t)).progress(`removed the record for ${n}; on a public host it is now closed`)}i(vM,"unprotectHost");async function SM(e,t){let r=O({profile:Sn(t).profile}).root,o=Ze(Pr(r).store),a=(e?[Ge(o,dt(e))].filter(u=>u!==null):o.protections).map(Ww),c=new T(Sn(t));if(c.json)c.data({protections:a});else if(!a.length)c.progress("no matching hosts");else for(let u of a)c.line(`${u.host} ${u.mode} ${u.user??"-"} ${u.scope} epoch ${u.epoch}`)}i(SM,"protectStatus");import{isIP as jee}from"node:net";import{join as Iee}from"node:path";var xM=/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+$/,Dee=/^[^\s@,;'"]+@[^\s@,;'"]+\.[^\s@,;'"]+$/;async function Nee(){let e=[];for await(let t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")}i(Nee,"readFirstLine");async function Lee(e){let t=((await e()).split(/\r?\n/)[0]??"").trim();if(!t)throw new C("--cloudflare-token-stdin was given but standard input held no token");if(/[\s"'#\\]/.test(t))throw new C("the token on standard in\
|
|
1531
|
+
put is not a valid API token");return t}i(Lee,"readToken");function Mee(e){let t=e.domain;if(!t)throw new C("--domain is required","portta public init --domain example.com --email you@example.com");if(!xM.test(t))throw new C(`--domain must be a lowercase hostname with a dot, such as example.com: ${t}`);let n=e.email;if(!n)throw new C("--email is required (the ACME contact)");if(!Dee.test(n))throw new C(`--email is not an email address: ${n}`);let r=e.panelHost??t;if(!xM.test(r))throw new C(`--pa\
|
|
1532
|
+
nel-host must be a lowercase hostname: ${r}`);if(r!==t&&(!r.endsWith(`.${t}`)||r.split(".").length!==t.split(".").length+1))throw new C(`--panel-host must be ${t} or one label under it, covered by *.${t}: ${r}`);let o=e.ip===void 0?0:jee(e.ip);if(e.ip!==void 0&&o===0)throw new C(`--ip is not an IPv4 or IPv6 address: ${e.ip}`);let s=o===6?"AAAA":"A",a=e.ip??"<server-ip>";return{panelHost:r,values:{PORTTA_PROFILE:"remote-public",PUBLIC_ENABLED:"true",PUBLIC_DOMAIN:t,PORTTA_DOMAIN_MODE:"custom",PORTTA_DOMAIN:t,
|
|
1533
|
+
TLS_ENABLED:"true",TLS_MODE:"acme",ACME_EMAIL:n,ACME_DNS_PROVIDER:"cloudflare",PORTTA_WEB:"true",PORTTA_WEB_EXPOSE:"domain",PORTTA_PANEL_ADVERTISED_HOST:r,PORTTA_PANEL_URL:`https://${r}`,PORTTA_AUTH_MODE:"required"},records:[{type:s,name:t,content:a,proxied:!1},{type:s,name:`*.${t}`,content:a,proxied:!1}]}}i(Mee,"planPublicInit");async function kM(e,t,n={}){let r=t.optsWithGlobals(),o=Mee(e),s=e.cloudflareTokenStdin?await Lee(n.readStdin??Nee):void 0,a=O({profile:r.profile}),c=e.dryRun===!0;if(a.
|
|
1534
|
+
config.tcpEnabled)throw new U("public access cannot be configured while TCP entrypoints are active");let u=[];try{u=await J(!0)}catch(w){if(!c)throw w}let p=An(u);if(p.length>0)throw new U(`these running services route with no login gate, so they would be open on a public host: ${p.join(", ")}`,"stop each project (portta runtime down <path>), configure public access, then portta adopt and portta runtime up it again");let d=Iee(a.root,".env"),f=me(En(d)),m=s===void 0?o.values:{...o.values,CF_DNS_API_TOKEN:s},
|
|
1535
1535
|
h=Object.entries(m).filter(([w,P])=>f.get(w)!==P).map(([w])=>w),b=s!==void 0||!!f.get("CF_DNS_API_TOKEN");c||(await et(`write the public-server settings for ${o.values.PUBLIC_DOMAIN} to ${d}? Nothing is started`,r.yes===!0),h.length>0&&je(d,m));let g=new T(r),y={domain:o.values.PUBLIC_DOMAIN,panelHost:o.panelHost,dryRun:c,written:c?!1:h.length>0,keys:h,tokenSet:b,records:o.records,tokenPermission:"Zone, DNS, Edit on the zone",next:["portta up remote-public","portta dns check",`printf %s "$PASSWO\
|
|
1536
1536
|
RD" | portta auth bootstrap --url https://${o.panelHost} --allow-remote --name <name> --email <email> --password-stdin`,"portta doctor"]};if(g.json){g.data(y);return}g.line(c?"dry run: nothing was written":h.length>0?`wrote ${d}`:"already configured; nothing changed"),g.line(`${c?"would set":"keys"}: ${h.length>0?h.join(", "):"(none)"}`),g.line(),g.line("DNS records to create (DNS only, not proxied):");for(let w of o.records)g.line(` ${w.type} ${w.name} ${w.content}`);g.line(),g.line("Cloudflar\
|
|
1537
1537
|
e token permission: Zone, DNS, Edit on the zone"),b||g.line("CF_DNS_API_TOKEN is not set: put the token in .env or rerun with --cloudflare-token-stdin"),g.line(),g.line("Create the owner as soon as DNS and the certificate answer, before sharing the address: until it"),g.line("exists, whoever reaches the panel first can claim it at /setup. In this mode the panel has no"),g.line("loopback port, so the command goes through its own https address."),g.line(),g.line("Next:");for(let w of y.next)g.line(
|
|
1538
|
-
` ${w}`)}i(kM,"publicInit");import{realpathSync as
|
|
1539
|
-
function
|
|
1540
|
-
if(d instanceof _e&&d.exitCode===Fe.refused)return Vw(r,"unauthorized",d.message,d.hint??"sign in with `portta auth login`, or ask for access to the Project",[]);throw d}let a=[];for(let d of s){let f=d.resolvedPath?ad(d.resolvedPath):null;if(!f)continue;let m=
|
|
1538
|
+
` ${w}`)}i(kM,"publicInit");import{realpathSync as zee}from"node:fs";import{resolve as EM}from"node:path";function ad(e){try{return zee(e)}catch{return null}}i(ad,"safeRealpath");async function _M(e,t){let n=await _("git",["-C",e,...t],{reject:!1});return n.exitCode===0?n.stdout.trim():null}i(_M,"git");async function Fee(e){let t=await _M(e,["rev-parse","--show-toplevel"]),n=t?ad(t):null,r=null;if(n){let o=await _M(e,["rev-parse","--git-common-dir"]);o&&(r=ad(EM(e,o,"..")))}return{path:e,gitRoot:n,commonRoot:r}}i(Fee,"pathFacts");function Bee(e,t){return e===t||e.startsWith(`${t}/`)}i(Bee,"inside");
|
|
1539
|
+
function Uee(e,t){return e.path===t?"root":Bee(e.path,t)?"subdirectory":e.commonRoot===t&&e.gitRoot!==t?"worktree":null}i(Uee,"basisOf");async function qee(e){let t=await e.request("GET","/projects");return Promise.all(t.projects.map(n=>e.request("GET",`/projects/${ns(n.slug)}`)))}i(qee,"registeredProjects");async function Hee(e,t){let n=EM(e),r=ad(n);if(!r)throw new C(`${n} does not exist on this host`,"pass an absolute path to a directory that exists");let o=await Fee(r),s;try{s=await qee(t)}catch(d){
|
|
1540
|
+
if(d instanceof _e&&d.exitCode===Fe.refused)return Vw(r,"unauthorized",d.message,d.hint??"sign in with `portta auth login`, or ask for access to the Project",[]);throw d}let a=[];for(let d of s){let f=d.resolvedPath?ad(d.resolvedPath):null;if(!f)continue;let m=Uee(o,f);m&&a.push({project:d,path:f,basis:m})}if(a.length===0)return Vw(r,"unknown",`${r} belongs to no Project the panel knows`,"create the Project with `portta projects create --path <dir>`, or check `portta projects list`",[]);let c=Math.
|
|
1541
1541
|
max(...a.map(d=>d.path.length)),u=a.filter(d=>d.path.length===c);if(u.length>1)return Vw(r,"ambiguous",`${r} could belong to ${u.map(d=>d.project.slug).join(" or ")}; nothing was chosen`,"name the Project explicitly, or fix the duplicate directory in the panel",u.map(d=>({slug:d.project.slug,path:d.path,basis:d.basis})));let p=u[0];return{resolved:!0,path:r,basis:p.basis,project:{id:p.project.id,slug:p.project.slug,name:p.project.name,path:p.path},worktree:p.basis==="worktree"&&o.gitRoot&&o.commonRoot?
|
|
1542
|
-
{path:o.gitRoot,mainPath:o.commonRoot}:null}}i(
|
|
1543
|
-
hint&&e.hint(t.error.hint),process.exitCode=PM[t.error.kind];return}e.line(`${t.project.name} (${t.project.slug}) \xB7 by ${t.basis}`),t.worktree&&e.line(` worktree of ${t.worktree.mainPath}`),e.line(` path ${t.project.path}`)}i(
|
|
1544
|
-
ssets","reinstall the `@codions/portta` npm package");return n}i(
|
|
1545
|
-
ig","traefik","dynamic"),r=ge(t,"config","traefik","dynamic");ld(r,{recursive:!0});for(let p of ja(n)){let d=ge(r,p);Qn(d)||cd(ge(n,p),d)}let o=ge(t,"bin");ld(o,{recursive:!0});let s=import.meta.dirname,a=
|
|
1546
|
-
`),cd(ge(s,"cli.js"),c)}
|
|
1542
|
+
{path:o.gitRoot,mainPath:o.commonRoot}:null}}i(Hee,"resolvePath");function Vw(e,t,n,r,o){return{resolved:!1,path:e,error:{kind:t,message:n,hint:r,candidates:o}}}i(Vw,"failure");var PM={unknown:Fe.failure,ambiguous:Fe.failure,unauthorized:Fe.refused};function Zee(e,t){if(e.json){e.data(t),t.resolved||(process.exitCode=PM[t.error.kind]);return}if(!t.resolved){e.error(`${t.error.kind}: ${t.error.message}`);for(let n of t.error.candidates)e.line(` ${n.slug.padEnd(20)} ${n.path} [${n.basis}]`);t.error.
|
|
1543
|
+
hint&&e.hint(t.error.hint),process.exitCode=PM[t.error.kind];return}e.line(`${t.project.name} (${t.project.slug}) \xB7 by ${t.basis}`),t.worktree&&e.line(` worktree of ${t.worktree.mainPath}`),e.line(` path ${t.project.path}`)}i(Zee,"reportOutcome");async function AM(e,t){let{client:n,output:r}=de(t),o=await Hee(e.path??process.cwd(),n);Zee(r,o)}i(AM,"projectsResolve");import{chmodSync as Gee,copyFileSync as cd,cpSync as CM,existsSync as Qn,mkdirSync as ld,readdirSync as ja,realpathSync as OM,rmSync as RM,writeFileSync as Wee}from"node:fs";import{homedir as TM}from"node:os";import{dirname as Vee,join as ge,resolve as bs}from"node:path";import{fileURLToPath as Kee}from"node:url";function Jee(e){return e.optsWithGlobals()}i(Jee,"globals");function Kw(e){return Number(/^v?(\d+)/.exec(e)?.[1]??0)}i(Kw,"major");async function $M(e,t){let n=await _(e,t,{reject:!1});return{ok:n.exitCode===0,value:n.stdout.trim()}}i($M,"available");function Yee(){let e=process.env.PORTTA_RUNTIME_ROOT;if(e)return bs(e);let n=[ge(import.meta.dirname,"runtime"),ge(import.meta.dirname,"..","runtime")].find(r=>Qn(ge(r,"VERSION")));if(!n)throw new L("the Portta package does not contain its runtime a\
|
|
1544
|
+
ssets","reinstall the `@codions/portta` npm package");return n}i(Yee,"packagedRuntime");var Xee="compose";function Qee(e,t){let n=ge(t,"runtime");if(!(Qn(n)&&OM(e)===OM(n))){for(let r of Qn(n)?ja(n):[])r!==Xee&&RM(ge(n,r),{recursive:!0,force:!0});CM(e,n,{recursive:!0,force:!0})}}i(Qee,"refreshRuntimeCache");function ete(e,t){ld(t,{recursive:!0}),Qee(e,t);for(let p of ja(e)){if(p==="config")continue;let d=ge(t,p);RM(d,{recursive:!0,force:!0}),CM(ge(e,p),d,{recursive:!0,force:!0})}let n=ge(e,"conf\
|
|
1545
|
+
ig","traefik","dynamic"),r=ge(t,"config","traefik","dynamic");ld(r,{recursive:!0});for(let p of ja(n)){let d=ge(r,p);Qn(d)||cd(ge(n,p),d)}let o=ge(t,"bin");ld(o,{recursive:!0});let s=import.meta.dirname,a=Kee(import.meta.url),c=ge(o,"portta");if(bs(a)!==bs(s)){for(let p of ja(s).filter(d=>d.endsWith(".js")))cd(ge(s,p),ge(o,p));Wee(ge(o,"package.json"),`{ "type": "module" }
|
|
1546
|
+
`),cd(ge(s,"cli.js"),c)}Gee(c,493);let u=ge(s,nd);Qn(u)&&cd(u,ge(o,nd))}i(ete,"installRuntime");async function jM(e,t){let n=Jee(t),r=new T(n);if(process.platform==="win32")throw new L("setup requires a POSIX host");let o=oh(),s=bs(e.dir??o??ge(TM(),"portta")),a=e.profile??n.profile??"local",c=Yee(),u=[],p=i((x,E,A)=>{u.push({step:x,status:E,detail:A}),r.json||r.progress(`${E.padEnd(8)} ${A}`)},"record"),d=process.versions.node;if(Kw(d)<24)throw new L(`Node ${d} is too old`,"Node 24 or newer is \
|
|
1547
1547
|
required");p("node","ok",`Node ${d}`),await Ct();let f=await $M("docker",["version","--format","{{.Server.Version}}"]);if(!f.ok||Kw(f.value)<24)throw new L("Docker Engine 24 or newer is required","setup never installs Docker or invokes a system package manager");let m=await $M("docker",["compose","version","--short"]);if(!m.ok||Kw(m.value)<2)throw new L("Docker Compose v2 is required");if(p("docker","ok",`Docker ${f.value}, Compose ${m.value}`),e.dryRun){p("runtime","planned",`install packaged r\
|
|
1548
1548
|
untime in ${s}`),p("environment","planned",`prepare .env from .env.example in ${s}, keeping set values`),p("network","planned","ensure the shared gateway network"),p("gateway","planned",`pull pinned images and start profile ${a}`),r.json&&r.data({dryRun:!0,target:s,steps:u});return}if(await et(`set up Portta in ${s}?`,n.yes===!0),Qn(s)&&ja(s).length>0&&!Qn(ge(s,"docker","compose","compose.yaml")))throw new U(`${s} exists and is not a Portta installation`,"choose an empty --dir; setup never overw\
|
|
1549
|
-
rites an unrelated directory");ld(
|
|
1549
|
+
rites an unrelated directory");ld(Vee(s),{recursive:!0});let h=Qn(ge(s,"VERSION"));ete(c,s),p("runtime",h?"updated":"created",`${s}`);let b=ge(s,".env");xt(b),p("environment","updated","environment prepared from .env.example"),rs(s),p("directories","ok","gateway state directories");let g=O({root:s,profile:a}),y=await Zt(g.config.network);p("network",y,`shared network ${g.config.network}`),e.skipPull?p("images","skipped","image pull disabled"):(await _("docker",["compose",...we(g),"pull","--ignor\
|
|
1550
1550
|
e-buildable"],{cwd:s,env:g.env}),p("images","ok","pinned images pulled"));let w=me(En(b));await _("docker",["compose",...we(g),"up","-d","--wait","--wait-timeout","180"],{cwd:s,env:g.env}),p("gateway","ok",`gateway up on ${a}`);try{Ha(s,w)}catch(x){p("applied","skipped",`could not record the applied settings: ${x.message}`)}if(!(await _("docker",["compose",...we(g),"ps","--status","running","--quiet"],{cwd:s,env:g.env})).stdout.trim())throw new L("gateway started but no component remained runnin\
|
|
1551
1551
|
g",`run portta doctor inside ${s}`);if(p("doctor","ok","gateway components are running"),r.json){r.data({dryRun:!1,target:s,steps:u});return}r.progress(""),r.progress(`Portta is installed in ${s}.`),bs(s)!==bs(ge(TM(),"portta"))&&r.progress(`Run portta from anywhere with PORTTA_HOME=${s} exported, or from inside that directory.`),r.progress(`The panel is off by default: portta web up starts it on http://127.0.0.1:${g.config.webPort}`),r.progress("portta doctor checks the installation.")}i(jM,"se\
|
|
1552
|
-
tupCommand");import{existsSync as
|
|
1552
|
+
tupCommand");import{existsSync as tte}from"node:fs";import{join as Jw}from"node:path";var nte=l.object({id:l.string(),mode:l.enum(["public","protected"]),host:l.string(),entryPoint:l.string(),container:l.string(),port:l.number(),expiresAt:l.number(),user:l.string().nullable().optional()}).passthrough();function Ia(e){return e.optsWithGlobals()}i(Ia,"globals");function IM(e){return Jw(O({profile:Ia(e).profile}).root,"config/traefik/dynamic/portta-shares.yaml")}i(IM,"path");function rte(e){return O({profile:Ia(e).profile}).root}i(rte,"root");function Yw(e){let t=IM(e);if(!tte(t))return[];
|
|
1553
1553
|
let n=En(t).split(`
|
|
1554
|
-
`).find(r=>r.startsWith(Zc));return n?l.array(
|
|
1554
|
+
`).find(r=>r.startsWith(Zc));return n?l.array(nte).parse(JSON.parse(n.slice(Zc.length))):[]}i(Yw,"read");function DM(e,t){St(IM(e),VE(t))}i(DM,"write");function NM(e,t){let n=rte(e),r=Jw(n,"state/auth/protections.json"),o=Ze(r),s={...o,protections:o.protections.filter(a=>!t.has(a.scope))};Zr(r,s),St(Jw(n,"config/traefik/dynamic/portta-auth.yaml"),Gr(s))}i(NM,"removeScopes");async function LM(e){let t=Yw(e),n=new T(Ia(e));if(n.json)n.data({shares:t});else if(!t.length)n.progress("nothing is share\
|
|
1555
1555
|
d");else for(let r of t)n.line(`${r.id} ${r.mode} ${r.host} ${r.container}:${r.port} ${r.expiresAt}`)}i(LM,"shareList");async function MM(e,t){if(!/^[A-Za-z0-9]+$/.test(e))throw new C(`invalid share id: ${e}`);let n=Yw(t);if(!n.some(r=>r.id===e))throw new C(`no share ${e}`);DM(t,n.filter(r=>r.id!==e)),NM(t,new Set([`share:${e}`])),new T(Ia(t)).progress(`share ${e} revoked; the project router was not touched`)}i(MM,"shareRevoke");async function zM(e){let t=Yw(e),n=Math.floor(Date.now()/1e3),r=t.filter(
|
|
1556
|
-
o=>o.expiresAt>n);r.length!==t.length&&(DM(e,r),NM(e,new Set(t.filter(o=>o.expiresAt<=n).map(o=>`share:${o.id}`)))),new T(Ia(e)).progress(`removed ${t.length-r.length} expired share(s)`)}i(zM,"shareGc");import{chmodSync as FM,existsSync as Da,mkdirSync as
|
|
1557
|
-
rm"];n.input!==void 0&&o.push("-i"),o.push("--network",n.network??"none");for(let s of n.volumes??[])o.push("--volume",s);for(let[s,a]of Object.entries(n.env??{}))o.push("--env",`${s}=${a}`);return o.push(r,...t),_("docker",o,{input:n.input,reject:!1})}i(ys,"runInToolbox");function pd(e){return e.optsWithGlobals()}i(pd,"globals");function Qw(e){let t=er(e,"config/tls");return{directory:t,caKey:er(t,"portta-ca.key"),caCertificate:er(t,"portta-ca.crt"),leafKey:er(t,"wildcard.key"),leafCertificate:er(t,"wildcard.crt"),dynamic:er(e,"config/traefik/dynamic/local-tls.yaml")}}i(Qw,"tlsPaths");function
|
|
1556
|
+
o=>o.expiresAt>n);r.length!==t.length&&(DM(e,r),NM(e,new Set(t.filter(o=>o.expiresAt<=n).map(o=>`share:${o.id}`)))),new T(Ia(e)).progress(`removed ${t.length-r.length} expired share(s)`)}i(zM,"shareGc");import{chmodSync as FM,existsSync as Da,mkdirSync as ste,writeFileSync as ite}from"node:fs";import{platform as ud}from"node:os";import{join as er}from"node:path";async function ote(e){return!(await _("docker",["image","inspect",e],{reject:!1})).failed}i(ote,"toolboxExists");async function Xw(e,t){let n=Se(t).toolbox;if(await ote(n))return n;if((await _("docker",["build","-q","--build-arg",`PORTTA_VERSION=${t}`,"-t",n,`${e}/docker/images/toolbox`],{reject:!1})).failed)throw new L("could not build the toolbox image",`docker build -t ${n} docker/images/toolbox/`);return n}i(Xw,"ensureToolbox");async function ys(e,t,n={}){let r=await Xw(e,rh(e)),o=["run","--\
|
|
1557
|
+
rm"];n.input!==void 0&&o.push("-i"),o.push("--network",n.network??"none");for(let s of n.volumes??[])o.push("--volume",s);for(let[s,a]of Object.entries(n.env??{}))o.push("--env",`${s}=${a}`);return o.push(r,...t),_("docker",o,{input:n.input,reject:!1})}i(ys,"runInToolbox");function pd(e){return e.optsWithGlobals()}i(pd,"globals");function Qw(e){let t=er(e,"config/tls");return{directory:t,caKey:er(t,"portta-ca.key"),caCertificate:er(t,"portta-ca.crt"),leafKey:er(t,"wildcard.key"),leafCertificate:er(t,"wildcard.crt"),dynamic:er(e,"config/traefik/dynamic/local-tls.yaml")}}i(Qw,"tlsPaths");function ate(){return`# Generated by \`portta tls init\`. Safe to delete: re-run the command to
|
|
1558
1558
|
# recreate it. The certificate and key live in config/tls/, which is git-ignored.
|
|
1559
1559
|
tls:
|
|
1560
1560
|
stores:
|
|
@@ -1565,39 +1565,39 @@ tls:
|
|
|
1565
1565
|
certificates:
|
|
1566
1566
|
- certFile: /etc/traefik/tls/wildcard.crt
|
|
1567
1567
|
keyFile: /etc/traefik/tls/wildcard.key
|
|
1568
|
-
`}i(
|
|
1569
|
-
`),n=t.findIndex(r=>r.includes("Subject Alternative Name"));return n===-1?[]:[...(t[n+1]??"").matchAll(/DNS:([^,\s]+)/g)].map(r=>r[1])}i(
|
|
1570
|
-
s=await r("-text");return{expires:o.failed?null:o.stdout.trim().replace(/^notAfter=/,""),names:s.failed?[]:
|
|
1568
|
+
`}i(ate,"localTlsDynamic");function cte(e){let t=e.split(`
|
|
1569
|
+
`),n=t.findIndex(r=>r.includes("Subject Alternative Name"));return n===-1?[]:[...(t[n+1]??"").matchAll(/DNS:([^,\s]+)/g)].map(r=>r[1])}i(cte,"parseSubjectAltNames");async function BM(e,t){if(!Da(t))return{expires:null,names:[]};let n=await _("which",["openssl"],{reject:!1}),r=i(async(...a)=>n.failed||!n.stdout.trim()?ys(e,["openssl","x509","-in","/in/cert.pem","-noout",...a],{volumes:[`${t}:/in/cert.pem:ro`]}):_("openssl",["x509","-in",t,"-noout",...a],{reject:!1}),"read"),o=await r("-enddate"),
|
|
1570
|
+
s=await r("-text");return{expires:o.failed?null:o.stdout.trim().replace(/^notAfter=/,""),names:s.failed?[]:cte(s.stdout)}}i(BM,"certificateFacts");async function UM(e){let t=pd(e),n=O({profile:t.profile}),r=Qw(n.root),o=await BM(n.root,r.leafCertificate),s=await BM(n.root,r.caCertificate),a={enabled:n.config.tlsEnabled,mode:n.config.tlsMode,domain:n.config.domain,certificate:{present:Da(r.leafCertificate),path:r.leafCertificate,expires:o.expires,names:o.names},authority:{present:Da(r.caCertificate),
|
|
1571
1571
|
path:r.caCertificate,expires:s.expires},acme:n.config.tlsMode==="acme"?{emailSet:!!n.env.ACME_EMAIL,directory:n.env.ACME_CA_SERVER,provider:n.env.ACME_DNS_PROVIDER}:null},c=new T(t);if(c.json){c.data(a);return}if(c.line(`enabled: ${a.enabled}`),c.line(`mode: ${a.mode}`),c.line(`domain: ${a.domain}`),a.acme){c.line(`acme email: ${a.acme.emailSet?"set":"<unset>"}`),c.line(`acme directory: ${a.acme.directory??""}`),c.line(`dns provider: ${a.acme.provider??""}`);return}c.line(`local CA: ${a.authority.
|
|
1572
|
-
present?a.authority.path:"not created"}`),a.authority.present||c.hint("portta tls init"),a.certificate.present&&(c.line(`certificate: ${a.certificate.path}`),a.certificate.names.length&&c.line(`covers: ${a.certificate.names.join(", ")}`),a.certificate.expires&&c.line(`expires: ${a.certificate.expires}`))}i(UM,"tlsStatus");async function qM(e){let t=pd(e),n=new T(t),r=O({profile:t.profile});await Ct();let o=Qw(r.root),s=r.config.domain;if(
|
|
1572
|
+
present?a.authority.path:"not created"}`),a.authority.present||c.hint("portta tls init"),a.certificate.present&&(c.line(`certificate: ${a.certificate.path}`),a.certificate.names.length&&c.line(`covers: ${a.certificate.names.join(", ")}`),a.certificate.expires&&c.line(`expires: ${a.certificate.expires}`))}i(UM,"tlsStatus");async function qM(e){let t=pd(e),n=new T(t),r=O({profile:t.profile});await Ct();let o=Qw(r.root),s=r.config.domain;if(ste(o.directory,{recursive:!0}),FM(o.directory,448),Da(o.caKey))
|
|
1573
1573
|
n.progress("reusing the existing local CA");else{n.progress("creating a local certificate authority");let u=await ys(r.root,["sh","-c",["set -e",'openssl req -x509 -newkey rsa:4096 -sha256 -days 1825 -nodes -keyout /out/portta-ca.key -out /out/portta-ca.crt -subj "/CN=Portta local CA/O=Portta" -addext "basicConstraints=critical,CA:TRUE,pathlen:0" -addext "keyUsage=critical,keyCertSign,cRLSign"',"chmod 600 /out/portta-ca.key"].join(`
|
|
1574
1574
|
`)],{volumes:[`${o.directory}:/out`]});if(u.failed)throw new L("could not create the CA",u.stderr.trim()||"see docs/product/guides/dns-and-tls.md");n.progress(`created ${o.caCertificate}`)}n.progress(`issuing a wildcard certificate for *.${s}`);let a=await ys(r.root,["sh","-c",["set -e",'openssl req -newkey rsa:2048 -nodes -keyout /out/wildcard.key -out /tmp/wildcard.csr -subj "/CN=*.$DOMAIN"','printf "subjectAltName=DNS:*.%s,DNS:%s\\nextendedKeyUsage=serverAuth\\nbasicConstraints=CA:FALSE\\n" "$DO\
|
|
1575
1575
|
MAIN" "$DOMAIN" > /tmp/ext',"openssl x509 -req -in /tmp/wildcard.csr -CA /out/portta-ca.crt -CAkey /out/portta-ca.key -CAcreateserial -out /out/wildcard.crt -days 397 -sha256 -extfile /tmp/ext","chmod 600 /out/wildcard.key"].join(`
|
|
1576
|
-
`)],{volumes:[`${o.directory}:/out`],env:{DOMAIN:s}});if(a.failed)throw new L("could not issue the certificate",a.stderr.trim()||"see docs/product/guides/dns-and-tls.md");for(let u of[o.caKey,o.leafKey])try{FM(u,384)}catch{}n.progress(`issued ${o.leafCertificate} for *.${s}`),
|
|
1576
|
+
`)],{volumes:[`${o.directory}:/out`],env:{DOMAIN:s}});if(a.failed)throw new L("could not issue the certificate",a.stderr.trim()||"see docs/product/guides/dns-and-tls.md");for(let u of[o.caKey,o.leafKey])try{FM(u,384)}catch{}n.progress(`issued ${o.leafCertificate} for *.${s}`),ite(o.dynamic,ate());let c=er(r.root,".env");je(c,{TLS_ENABLED:"true",TLS_MODE:"local"}),n.progress("TLS enabled in .env"),n.line(""),HM(n,o.caCertificate),n.hint(`then: portta up ${r.config.profile}`)}i(qM,"tlsInit");function HM(e,t){
|
|
1577
1577
|
e.line("Trusting the local CA"),e.line("This writes to your operating system trust store, so the gateway will not do it for you. Run the command that matches your system:"),e.line(""),ud()==="darwin"?(e.line(" sudo security add-trusted-cert -d -r trustRoot \\"),e.line(` -k /Library/Keychains/System.keychain "${t}"`)):ud()==="linux"?(e.line(` sudo cp "${t}" /usr/local/share/ca-certificates/portta-ca.crt`),e.line(" sudo update-ca-certificates")):e.line(` Import ${t} into your system trust s\
|
|
1578
1578
|
tore as a root certificate.`),e.line(""),e.line("Firefox keeps its own store: Settings -> Privacy & Security -> Certificates -> View Certificates -> Authorities -> Import."),e.line("Remove it later with: portta tls untrust")}i(HM,"printTrust");async function ZM(e){let t=pd(e),n=O({profile:t.profile}),r=Qw(n.root);if(!Da(r.caCertificate))throw new L("no local CA yet","portta tls init");HM(new T(t),r.caCertificate)}i(ZM,"tlsTrust");async function GM(e){let t=pd(e),n=O({profile:t.profile}),r=new T(
|
|
1579
|
-
t);r.line("Removing the local CA from the trust store"),ud()==="darwin"?(r.line(' sudo security delete-certificate -c "Portta local CA" \\'),r.line(" /Library/Keychains/System.keychain")):ud()==="linux"?(r.line(" sudo rm -f /usr/local/share/ca-certificates/portta-ca.crt"),r.line(" sudo update-ca-certificates --fresh")):r.line(' Remove "Portta local CA" from your system trust store.'),r.line(""),r.line(`To delete the key material as well: rm -rf ${
|
|
1580
|
-
return er(e,"config/tls")}i(
|
|
1581
|
-
exitCode=r.exitCode)}i(VM,"toolboxRun");import{chmodSync as KM,closeSync as
|
|
1582
|
-
"80";return`http://${t==="tailscale"?"tailscale":"traefik"}:${n}`}i(
|
|
1583
|
-
|
|
1579
|
+
t);r.line("Removing the local CA from the trust store"),ud()==="darwin"?(r.line(' sudo security delete-certificate -c "Portta local CA" \\'),r.line(" /Library/Keychains/System.keychain")):ud()==="linux"?(r.line(" sudo rm -f /usr/local/share/ca-certificates/portta-ca.crt"),r.line(" sudo update-ca-certificates --fresh")):r.line(' Remove "Portta local CA" from your system trust store.'),r.line(""),r.line(`To delete the key material as well: rm -rf ${lte(n.root)}`)}i(GM,"tlsUntrust");function lte(e){
|
|
1580
|
+
return er(e,"config/tls")}i(lte,"paths");function dd(e){return e.optsWithGlobals()}i(dd,"globals");async function WM(e){let t=O({profile:dd(e).profile}),n=await Xw(t.root,t.version),r=new T(dd(e));dd(e).json?r.data({image:n}):r.progress(`toolbox ready: ${n}`)}i(WM,"toolboxBuild");async function VM(e,t){if(e.length===0)throw new C("toolbox run needs a command");let n=O({profile:dd(t).profile}),r=await ys(n.root,e,{network:"bridge"});r.stdout&&process.stdout.write(r.stdout),r.stderr&&process.stderr.write(r.stderr),r.exitCode!==0&&(process.
|
|
1581
|
+
exitCode=r.exitCode)}i(VM,"toolboxRun");import{chmodSync as KM,closeSync as ute,existsSync as fd,mkdirSync as pte,openSync as dte,readFileSync as fte,rmSync as JM,writeFileSync as YM}from"node:fs";import{join as ws}from"node:path";import{ReadStream as mte}from"node:tty";function vs(e){return e.optsWithGlobals()}i(vs,"globals");function md(e){let t=ws(e,"state/cloudflared");return{directory:t,config:ws(t,"config.yml"),credentials:ws(t,"credentials.json")}}i(md,"tunnelPaths");function XM(e){return`${e.PORTTA_PROJECT_NAME||"portta"}-cloudflared-1`}i(XM,"tunnelContainer");function QM(e){let t=md(e);return fd(t.config)&&fd(t.credentials)}i(QM,"tunnelConfigured");function hte(e){let t=Qd({profile:e.config.profile,tailscaleEnabled:e.config.tailscaleEnabled}),n=e.env.PORTTA_HTTP_PORT||
|
|
1582
|
+
"80";return`http://${t==="tailscale"?"tailscale":"traefik"}:${n}`}i(hte,"defaultOrigin");async function gte(e){let t=XM(e.env),n=await _("docker",["inspect","-f","{{.State.Status}}",t],{reject:!1}),r=await _("docker",["inspect","-f","{{if .State.Health}}{{.State.Health.Status}}{{end}}",t],{reject:!1}),o=await _("docker",["logs","--tail","200",t],{reject:!1});return{container:t,state:n.failed?null:n.stdout.trim()||null,health:r.failed?null:r.stdout.trim()||null,logTail:`${o.stdout}${o.stderr}`}}i(
|
|
1583
|
+
gte,"containerFacts");async function bte(e){let t=await gte(e);return{status:QE({tokenConfigured:QM(e.root),zoneConfigured:!!e.env.CLOUDFLARE_TUNNEL_ZONE,enabled:e.config.tunnelEnabled,containerState:t.state,containerHealth:t.health,logTail:t.logTail}),container:t.container,containerState:t.state??"absent"}}i(bte,"readStatus");async function ev(e){let t=vs(e),n=O({profile:t.profile}),r=new T(t),{status:o,container:s,containerState:a}=await bte(n),c=n.env.CLOUDFLARE_TUNNEL_ZONE??"",u=n.env.CLOUDFLARE_TUNNEL_ID??
|
|
1584
1584
|
"",p=fd(md(n.root).credentials);if(r.json){r.data({state:o.state,detail:o.detail,hint:o.hint,zone:c||null,wildcard:c?`*.${c}`:null,tunnel:u||null,connector:{container:s,state:a},credential:p});return}r.line(""),r.line("Cloudflare Tunnel"),r.line(""),r.line(` state ${o.state}`),r.line(` domain ${c||"<unset>"}`),c&&r.line(` wildcard *.${c}`),r.line(` tunnel ${u||"<unset>"}`),r.line(` connector ${s} (${a})`),r.line(` credential ${p?"configured":"not set"}`),r.line(""),o.
|
|
1585
|
-
state==="connected"?r.progress(`carrying traffic for *.${c}`):o.state==="starting"||o.state==="not-configured"||o.state==="configured"?r.progress(o.detail):r.error(o.detail);let d=
|
|
1586
|
-
account: portta tunnel setup --zone <domain>";case"disconnected":return"portta tunnel logs (the connector dials out on 7844/udp and 443/tcp)";case"starting":case"connected":return null}}i(
|
|
1585
|
+
state==="connected"?r.progress(`carrying traffic for *.${c}`):o.state==="starting"||o.state==="not-configured"||o.state==="configured"?r.progress(o.detail):r.error(o.detail);let d=yte(o);d&&r.hint(d)}i(ev,"tunnelStatus");function yte(e){switch(e.state){case"not-configured":return"portta tunnel setup --zone <domain>";case"configured":return"portta tunnel enable";case"config-error":return"portta tunnel logs";case"auth-error":return"the tunnel may have been deleted, or the token belongs to another \
|
|
1586
|
+
account: portta tunnel setup --zone <domain>";case"disconnected":return"portta tunnel logs (the connector dials out on 7844/udp and 443/tcp)";case"starting":case"connected":return null}}i(yte,"cliHint");async function wte(){let e;try{e=dte("/dev/tty","r")}catch{throw new L("no terminal available to read the token","portta tunnel setup --zone <domain> --token-file <file>")}process.stderr.write("Tunnel token (input is hidden): ");let t=new mte(e),n=t.isTTY?()=>t.setRawMode(!1):()=>{};t.isTTY&&t.
|
|
1587
1587
|
setRawMode(!0);try{return await new Promise(r=>{let o="";t.on("data",s=>{for(let a of s){if(a===13||a===10){process.stderr.write(`
|
|
1588
1588
|
`),r(o.trim());return}if(a===3){process.stderr.write(`
|
|
1589
|
-
`),r("");return}a===127||a===8?o=o.slice(0,-1):o+=String.fromCharCode(a)}})})}finally{n(),t.destroy(),
|
|
1590
|
-
l, e.g. example.com");let o=O({profile:n.profile}),s;if(e.tokenFile){if(!fd(e.tokenFile))throw new C(`no such file: ${e.tokenFile}`);s=
|
|
1591
|
-
und it")}YM(a.credentials,XE(c),{mode:384}),KM(a.credentials,384);let u=e.origin||
|
|
1589
|
+
`),r("");return}a===127||a===8?o=o.slice(0,-1):o+=String.fromCharCode(a)}})})}finally{n(),t.destroy(),ute(e)}}i(wte,"promptForToken");async function e1(e,t){let n=vs(t),r=new T(n);if(e.token!==void 0)throw new C("a token must not be passed as an argument: it would be visible in `ps` and in your shell history",`portta tunnel setup --zone ${e.zone??"<domain>"} --token-file <file>, or omit it to be prompted`);if(!e.zone)throw new C("--zone is required","the domain whose wildcard points at the tunne\
|
|
1590
|
+
l, e.g. example.com");let o=O({profile:n.profile}),s;if(e.tokenFile){if(!fd(e.tokenFile))throw new C(`no such file: ${e.tokenFile}`);s=fte(e.tokenFile,"utf8").replace(/\s+/g,"")}else s=await wte();if(!s)throw new C("no token was given");let a=md(o.root);pte(a.directory,{recursive:!0}),KM(a.directory,448);let c;try{c=YE(s)}catch(f){throw new C(`the token was refused: ${f instanceof Error?f.message:String(f)}`,"copy the whole eyJ... string from the Cloudflare dashboard, not the install command aro\
|
|
1591
|
+
und it")}YM(a.credentials,XE(c),{mode:384}),KM(a.credentials,384);let u=e.origin||hte(o),p={id:c.TunnelID,zone:e.zone,origin:u,credentialsFile:"/etc/cloudflared/credentials.json",includeApex:e.apex??!1};YM(a.config,JE(p));let d=ws(o.root,".env");if(je(d,{CLOUDFLARE_TUNNEL_ZONE:e.zone,CLOUDFLARE_TUNNEL_ID:c.TunnelID}),r.json){r.data({zone:e.zone,tunnel:c.TunnelID,origin:u,routes:eh(p),dns:{type:"CNAME",name:`*.${e.zone}`,target:th(c.TunnelID),proxied:!0}});return}r.progress("the connector is conf\
|
|
1592
1592
|
igured"),r.line(""),r.line(` zone ${e.zone}`),r.line(` tunnel ${c.TunnelID}`),r.line(` origin ${u}`);for(let f of eh(p))r.line(` routes ${f}`);r.line(""),r.line("One DNS record makes every project hostname work, now and in future:"),r.line(""),r.line(" Type CNAME"),r.line(` Name *.${e.zone}`),r.line(` Target ${th(c.TunnelID)}`),r.line(" Proxy on (orange cloud)"),r.line(""),r.line("Then: portta tunnel enable")}i(e1,"tunnelSetup");async function t1(e){let t=vs(e),
|
|
1593
1593
|
n=new T(t),r=O({profile:t.profile});if(!QM(r.root))throw new L("the connector is not configured","portta tunnel setup --zone <domain>");let o=ws(r.root,".env");if(je(o,{CLOUDFLARE_TUNNEL_ENABLED:"true"}),n.progress("Cloudflare Tunnel enabled"),n.progress("starting the connector"),r=O({profile:t.profile,overrides:{CLOUDFLARE_TUNNEL_ENABLED:"true"}}),(await _("docker",["compose",...we(r),"up","-d","--remove-orphans"],{cwd:r.root,env:r.env,stdio:"inherit",reject:!1})).failed)throw new L("the connec\
|
|
1594
1594
|
tor did not start","portta tunnel logs");await ev(e)}i(t1,"tunnelEnable");async function n1(e,t){let n=vs(t),r=new T(n);r.progress("stopping the connector");let o=O({profile:n.profile,overrides:{CLOUDFLARE_TUNNEL_ENABLED:"true"}});await _("docker",["compose",...we(o),"rm","-sf","cloudflared"],{cwd:o.root,env:o.env,reject:!1});let s=ws(o.root,".env"),a={CLOUDFLARE_TUNNEL_ENABLED:"false"};if(e.forget){let c=md(o.root);JM(c.config,{force:!0}),JM(c.credentials,{force:!0}),a.CLOUDFLARE_TUNNEL_ID=""}je(
|
|
1595
1595
|
s,a),r.progress(e.forget?"the connector is stopped and its configuration removed":"the connector is stopped; its configuration is kept for re-enabling"),r.line(""),r.line("nothing was changed in your Cloudflare account"),r.line(" The tunnel, the DNS record and any Access policy are still there."),r.line(" Remove them yourself if you want them gone.")}i(n1,"tunnelDisable");async function r1(e,t){let n=vs(t),r=O({profile:n.profile});if((await _("docker",["logs","--tail",e.lines??"50",XM(r.env)],
|
|
1596
|
-
{stdio:"inherit",reject:!1})).failed)throw new L("the connector container does not exist","portta tunnel enable")}i(r1,"tunnelLogs");function
|
|
1597
|
-
Cloudflare has no connector for this tunnel (530)",hint:"portta tunnel status"}:e===502||e===504?{ok:!1,detail:`the connector answered but could not reach the gateway (${e})`,hint:"portta status (is Traefik running?)"}:e===0?{ok:!1,detail:"no answer at all",hint:"check that the wildcard resolves"}:{ok:!1,detail:`unexpected response: ${e}`,hint:null}}i(
|
|
1598
|
-
n is configured","portta tunnel setup --zone <domain>");let s=`portta-tunnel-check.${o}`;n.progress(`asking Cloudflare for https://${s}`);let a=0,c=new AbortController,u=setTimeout(()=>c.abort(),2e4);try{a=(await fetch(`https://${s}/`,{signal:c.signal,redirect:"manual"})).status}catch{a=0}finally{clearTimeout(u)}let p=
|
|
1599
|
-
nnel is not carrying traffic (${a})`,p.hint??"portta tunnel status")}i(o1,"tunnelTest");import{randomBytes as
|
|
1600
|
-
client:n,output:r}=de(t),o=await n.request("GET","/users");if(r.json)return r.data(o);if(o.users.length===0)return r.line("no users");Ap(r,[["EMAIL","ROLE","STATE","PROJECTS","ID"],...o.users.map(
|
|
1596
|
+
{stdio:"inherit",reject:!1})).failed)throw new L("the connector container does not exist","portta tunnel enable")}i(r1,"tunnelLogs");function vte(e){return e===404?{ok:!0,detail:"the tunnel is carrying traffic (404 from the gateway). Traefik answered, which means Cloudflare -> tunnel -> connector -> Traefik all work; 404 is correct here, because nothing is routed at that name.",hint:null}:e===200||e>=300&&e<400?{ok:!0,detail:`the tunnel is carrying traffic (${e})`,hint:null}:e===530?{ok:!1,detail:"\
|
|
1597
|
+
Cloudflare has no connector for this tunnel (530)",hint:"portta tunnel status"}:e===502||e===504?{ok:!1,detail:`the connector answered but could not reach the gateway (${e})`,hint:"portta status (is Traefik running?)"}:e===0?{ok:!1,detail:"no answer at all",hint:"check that the wildcard resolves"}:{ok:!1,detail:`unexpected response: ${e}`,hint:null}}i(vte,"describeProbe");async function o1(e){let t=vs(e),n=new T(t),o=O({profile:t.profile}).env.CLOUDFLARE_TUNNEL_ZONE;if(!o)throw new L("no domai\
|
|
1598
|
+
n is configured","portta tunnel setup --zone <domain>");let s=`portta-tunnel-check.${o}`;n.progress(`asking Cloudflare for https://${s}`);let a=0,c=new AbortController,u=setTimeout(()=>c.abort(),2e4);try{a=(await fetch(`https://${s}/`,{signal:c.signal,redirect:"manual"})).status}catch{a=0}finally{clearTimeout(u)}let p=vte(a);if(n.json){n.data({host:s,code:a,ok:p.ok,detail:p.detail,hint:p.hint});return}if(p.ok?n.progress(p.detail):n.error(p.detail),p.hint&&n.hint(p.hint),!p.ok)throw new L(`the tu\
|
|
1599
|
+
nnel is not carrying traffic (${a})`,p.hint??"portta tunnel status")}i(o1,"tunnelTest");import{randomBytes as Ste}from"node:crypto";import{readFileSync as xte}from"node:fs";function tv(e){if(e.passwordStdin){let n=xte(0,"utf8").trim();if(!n)throw new C("no password on stdin");if(n.length<10)throw new C("the password must be at least 10 characters");return{password:n,generated:!1}}return{password:Ste(20).toString("base64url").slice(0,20).match(/.{1,5}/g).join("-"),generated:!0}}i(tv,"passwordFrom");function kte(e){return[e.email,e.role,e.banned?"banned":"active",e.projects.length?e.projects.map(t=>t.slug).join(","):"all",e.id]}i(kte,"line");async function s1(e,t){let{
|
|
1600
|
+
client:n,output:r}=de(t),o=await n.request("GET","/users");if(r.json)return r.data(o);if(o.users.length===0)return r.line("no users");Ap(r,[["EMAIL","ROLE","STATE","PROJECTS","ID"],...o.users.map(kte)])}i(s1,"usersList");async function i1(e,t){if(!e.name||!e.email)throw new C("--name and --email are required");let n=e.role??"viewer";if(!Xm(n))throw new C(`--role must be one of: ${wo.join(", ")}`);let{password:r,generated:o}=tv(e),{client:s,output:a}=de(t),c=await s.request("POST","/users",{name:e.
|
|
1601
1601
|
name,email:e.email,password:r,role:n,...e.projects?{projects:(tD(e.projects)??[]).map(Number)}:{}});if(a.json)return a.data({...c,password:o?r:void 0});a.line(`${c.email} ${c.role}`),o&&(a.line(`password: ${r}`),a.warning("this is the only time the generated password is shown"))}i(i1,"usersCreate");async function a1(e,t,n,r){if(!Xm(t))throw new C(`role must be one of: ${wo.join(", ")}`);let{client:o,output:s}=de(r),a=await hd(o,e),c=await o.request("PATCH",`/users/${encodeURIComponent(a.id)}/ro\
|
|
1602
1602
|
le`,{role:t});if(s.json)return s.data(c);s.progress(`${c.email} is now ${c.role}`)}i(a1,"usersSetRole");async function c1(e,t,n){let{password:r,generated:o}=tv(t),{client:s,output:a}=de(n),c=await hd(s,e);if(await s.request("PATCH",`/users/${encodeURIComponent(c.id)}/password`,{password:r}),a.json)return a.data({email:c.email,password:o?r:void 0});a.progress(`password set for ${c.email}; every session of that account was ended`),o&&(a.line(`password: ${r}`),a.warning("this is the only time the g\
|
|
1603
1603
|
enerated password is shown"))}i(c1,"usersSetPassword");async function l1(e,t,n,r){let{client:o,output:s}=de(n),a=await hd(o,e),u=(await o.request("GET","/projects")).projects.find(m=>m.slug===t);if(!u)throw new C(`no project '${t}'`,"list them with `portta projects list`");let p=a.projects.map(m=>m.id),d=await o.request("PUT",`/users/${encodeURIComponent(a.id)}/projects`,{projects:r(p,u.id).map(Number)});if(s.json)return s.data(d);let f=d.projects.map(m=>m.slug);s.progress(`${d.email} reaches ${f.
|
|
@@ -1611,7 +1611,7 @@ ateway components").option("--local-release","use the locally built image for th
|
|
|
1611
1611
|
t portta-demo-* projects from PORTTA_PROJECTS_HOME").action((e,t,n)=>Bw(e,t,n));S(G.command("down"),"Stop the current Compose runtime, or gateway components; keep projects and data").option("--demo","also stop portta-demo-* projects from PORTTA_PROJECTS_HOME and drop their volumes").action((e,t)=>Yo()?rt("down",{},t):UL(e,t));S(G.command("reset"),"Stop every Portta-managed stack, drop their volumes, and restart this checkout as if it were new").option("--demo","also recreate portta-demo-* projec\
|
|
1612
1612
|
ts from PORTTA_PROJECTS_HOME").action((e,t)=>qL(e,t));S(G.command("restart"),"Restart the current Compose runtime, or recreate gateway components").action((e,t)=>Yo()?rt("restart",{},t):HL(t));S(G.command("status"),"Show the current Compose runtime, or gateway status").action((e,t)=>Yo()?rt("status",{},t):VL(t));S(G.command("doctor"),"Run read-only host and gateway diagnostics").action((e,t)=>Uw(t));S(G.command("urls"),"List routed HTTP hostnames").option("--project <name>").action(Ca);S(G.command(
|
|
1613
1613
|
"logs [service]"),"Follow current Compose runtime or gateway component logs").option("--no-follow").option("--tail <lines>","line count","200").action((e,t,n)=>Yo()?rt("logs",{service:e,follow:t.follow,tail:t.tail},n):ZL(e,t,n));S(G.command("inspect"),"Print resolved configuration without secrets").action((e,t)=>WL(t));S(G.command("update"),"Pull pinned images and recreate after confirmation").action((e,t)=>GL(t));S(G.command("services"),"List services in the current Compose runtime").action((e,t)=>rt(
|
|
1614
|
-
"status",{},t));var
|
|
1614
|
+
"status",{},t));var _te=S(G.command("compose"),"Inspect the effective Compose model for the current runtime");S(_te.command("config [path]"),"Print the effective model from the persisted Runtime Plan").action((e,t,n)=>rt("config",{path:e},n));var Nt=S(G.command("envs"),"Inspect and operate Compose environments on this host").alias("env").alias("environment");S(Nt.command("list"),"List running Compose environments").action((e,t)=>iN(e,t));S(Nt.command("show <name>"),"Show one environment, its ser\
|
|
1615
1615
|
vices and URLs").action((e,t,n)=>aN(e,n));S(Nt.command("services"),"List services across running environments").option("--project <name>").action(cN);S(Nt.command("report"),"Collect host environment readiness into state/environment").action((e,t)=>EN(t));S(Nt.command("analyze <path>"),"Read-only adoption report").option("--file <path>","the Compose file, relative to <path> or absolute; default: compose.yaml and its variants in <path>").action(uN);S(G.command("adopt <path>"),"Analyze and prepare \
|
|
1616
1616
|
an isolated Compose Runtime Plan without changing the project").option("--dry-run","print the plan and pending decisions without writing state").option("--service <name:port>","HTTP service to expose; repeatable",(e,t)=>t.concat(e),[]).option("--project <name>","explicit Compose project namespace").option("--manual","record manual integration instead of generated runtime mutations").option("--remove-container-name <service>","explicitly remove this fixed container name; repeatable",(e,t)=>t.concat(
|
|
1617
1617
|
e),[]).option("--allow-shared-networks","confirm that fixed or external networks may be shared").option("--allow-shared-volumes","confirm that fixed or external volumes may be shared").option("--protect <service>","public host: ask for a generated credential to open this service; repeatable",(e,t)=>t.concat(e),[]).option("--public <service>","public host: let everybody open this service, with no login; repeatable",(e,t)=>t.concat(e),[]).action(async(e,t,n)=>{await PI({path:e,service:t.service,project:t.
|
|
@@ -1622,7 +1622,7 @@ ependents first").action((e,t,n)=>Up(e,"stop",n));S(Nt.command("restart <name>")
|
|
|
1622
1622
|
ed: list, create, resolve, resources");S(Ae(Na.command("list")),"List Projects").action(dM);S(Ae(Na.command("show <slug>")),"One Project with its environments").action((e,t,n)=>fM(e,n));S(Ae(Na.command("create")),"Create a Project").option("--slug <slug>").option("--name <name>").option("--description <text>").option("--path <dir>","directory under Projects Home, such as group/project").action(mM);S(Ae(Na.command("resolve")),"Which Project a directory belongs to: its root, a subdirectory or a wo\
|
|
1623
1623
|
rktree").option("--path <abs>","the directory to resolve; defaults to the current one").action(AM);S(Ae(Na.command("resources <slug>")),"A Project's resource usage, attributed through its environments").action((e,t,n)=>hM(e,n));var La=S(G.command("access"),"Open short-lived loopback bridges");S(Qt(m1(La.command("open"))),"Open a bridge").option("--port <number>").option("--local-port <number>").option("--ttl <duration>").option("--network <name>").option("--bind <ip>","bind address","127.0.0.1").
|
|
1624
1624
|
action(Pi);S(La.command("list").alias("ls"),"List bridges").action((e,t)=>hC(t));S(La.command("close [id]"),"Close only gateway-owned bridges").option("--project <name>").option("--all").action(ru);S(La.command("inspect <id>"),"Inspect one bridge").action((e,t,n)=>gC(e,n));S(La.command("gc"),"Remove expired and orphaned bridges").action((e,t)=>bC(t));var nv=S(G.command("service"),"Manage persistent private TCP forwarders");S(Qt(m1(nv.command("publish"))),"Publish a service privately").option("--\
|
|
1625
|
-
private").option("--public").option("--port <number>").option("--alias <name>").action(yC);S(nv.command("list"),"List private forwarders").action((e,t)=>wC(t));S(nv.command("unpublish [alias]"),"Remove gateway-owned forwarders").option("--project <name>").action(vC);var
|
|
1625
|
+
private").option("--public").option("--port <number>").option("--alias <name>").action(yC);S(nv.command("list"),"List private forwarders").action((e,t)=>wC(t));S(nv.command("unpublish [alias]"),"Remove gateway-owned forwarders").option("--project <name>").action(vC);var Pte=S(G.command("network"),"Inspect host network exposure");S(Pte.command("status"),"List published bindings").option("--public-ip","make one outbound public-IP lookup").action(sM);var gd=S(G.command("public"),"Control deliberate\
|
|
1626
1626
|
public HTTP exposure");S(gd.command("status"),"Show current public exposure").action((e,t)=>iM(t));S(gd.command("enable"),"Enable public HTTP after confirmation").action((e,t)=>aM(t));S(gd.command("init"),"Configure this host as a public server: domain, TLS and panel, without starting anything").requiredOption("--domain <domain>","the base domain, such as example.com").requiredOption("--email <address>","the ACME contact").option("--panel-host <host>","where the panel answers; the domain or one\
|
|
1627
1627
|
label under it (default: the domain)").option("--ip <address>","the server's public IP, used only to print the DNS records").option("--cloudflare-token-stdin","read the Cloudflare DNS token from one line of standard input").option("--dry-run","print the plan and the DNS records; write nothing").action(kM);S(gd.command("disable"),"Disable public HTTP").action((e,t)=>cM(t));var rv=S(G.command("dns"),"Inspect or configure wildcard DNS");S(rv.command("check"),"Resolve a wildcard probe").action((e,t)=>lM(
|
|
1628
1628
|
t));S(rv.command("status"),"Show DNS configuration without secrets").action((e,t)=>uM(t));S(rv.command("setup"),"Plan or apply a Cloudflare wildcard record").option("--target <ip>").option("--dry-run").action(pM);var xn=S(G.command("web"),"Run the optional administration panel").option("--local-release","use the locally built image for this checkout");S(xn.command("up"),"Enable and start the panel").option("--expose <scope>","local, tailscale, vpn, public or domain").option("--port <number>").option(
|
|
@@ -1633,7 +1633,7 @@ h"),"Keep collecting host and Docker metrics").option("--loop","run in the foreg
|
|
|
1633
1633
|
ares").action((e,t)=>zM(t));var Fr=S(G.command("auth"),"Who this terminal is, to a panel");S(Ae(Fr.command("status",{isDefault:!0}),!1),"Whether this panel asks who you are, and who it thinks you are").action(iD);S(Ae(Fr.command("login"),!1),"Save a token for a panel, after checking it").option("--token <token>","the token; omitted, it is read from the terminal without echoing").action(sD);S(Ae(Fr.command("logout"),!1),"Forget the saved credential for a panel").action(aD);S(Fr.command("whoami"),
|
|
1634
1634
|
"Every panel this host has a credential for").action(cD);S(Ae(Fr.command("bootstrap"),!1),"Create the panel owner, once, from this host").requiredOption("--name <name>").requiredOption("--email <email>").option("--password-stdin").action(oD);S(Fr.command("reset-password <email>"),"Reset a password from the host, when nobody can sign in to do it").option("--password-stdin","read the password from stdin instead of generating one").action(f1);var iv=S(Fr.command("token"),"Personal API tokens for th\
|
|
1635
1635
|
is panel");S(Ae(iv.command("list",{isDefault:!0})),"Your tokens, without their secrets").option("--all","every account's tokens; needs user:list").action(lD);S(Ae(iv.command("create"),!1),"Create a token; its secret is shown once").requiredOption("--name <name>").option("--human","a person's token, holding their whole role").option("--scopes <a,b>","permissions this token holds, inside your role").option("--expires-in-days <days>","1 to 365; omitted, it is valid until revoked").action(uD);S(Ae(iv.
|
|
1636
|
-
command("revoke <id>")),"Revoke a token").action(pD);var
|
|
1636
|
+
command("revoke <id>")),"Revoke a token").action(pD);var Ete=S(G.command("agent"),"What an AI agent needs to know about this host and directory");S(Ete.command("context"),"Where a directory stands on a Portta host, for the start of an agent session; always exits 0").option("--path <dir>","the directory to describe; defaults to the current one").option("--home <dir>","the home directory, where scope.yaml is read from; defaults to $HOME").option("--format <format>","text, or hook for the short tex\
|
|
1637
1637
|
t an agent hook injects","text").action(DI);var av=S(G.command("agents"),"Install the Portta layer into AI coding agents on this machine");S(av.command("install [agents...]"),"Write the instruction, hook and skills for the agents found here (claude, codex, opencode, pi)").option("--home <dir>","use this directory as the home; wins over CLAUDE_CONFIG_DIR and CODEX_HOME").option("--dry-run","print what would change without writing anything").action(WI);S(av.command("status [agents...]"),"Compare w\
|
|
1638
1638
|
hat is installed with what should be").option("--home <dir>","use this directory as the home; wins over CLAUDE_CONFIG_DIR and CODEX_HOME").action(VI);S(av.command("uninstall [agents...]"),"Remove only what the installer wrote: marker blocks, its hook entries and its files").option("--home <dir>","use this directory as the home; wins over CLAUDE_CONFIG_DIR and CODEX_HOME").option("--dry-run","print what would be removed without removing anything").action(KI);var yd=S(G.command("protect"),"Who may\
|
|
1639
1639
|
open a project hostname: a credential, everybody, or nobody");S(yd.command("status [host]",{isDefault:!0}),"List host decisions without credentials").action((e,t,n)=>SM(e,n));S(yd.command("host <host>"),"Create or rotate a hostname credential").option("--user <name>").option("--password-only","ask for the password alone, with no username").option("--password-stdin").option("--entrypoint <name>").option("--label <text>").option("--project <name>").option("--service <name>").action(yM);S(yd.command(
|
|
@@ -1650,5 +1650,5 @@ Actor (PORTTA_ACTOR)"):n}i(Ae,"panelOptions");var lv=S(G.command("docs"),"Read t
|
|
|
1650
1650
|
(e,t)=>ev(t));S(xs.command("setup"),"Write the connector configuration from a tunnel token").requiredOption("--zone <domain>","the domain whose wildcard points at the tunnel").option("--token-file <path>","read the tunnel token from a file").option("--origin <url>","where the connector reaches the proxy").option("--apex","serve the zone apex as well as the wildcard").option("--token <value>","refused; use --token-file or the prompt").action(e1);S(xs.command("enable"),"Start the connector").action(
|
|
1651
1651
|
(e,t)=>t1(t));S(xs.command("disable"),"Stop the connector, keeping the configuration").option("--forget","delete the configuration and credentials too").action(n1);S(xs.command("test"),"Check that the tunnel is carrying traffic").action((e,t)=>o1(t));S(xs.command("logs"),"Show the connector's own output").option("-n, --lines <count>","line count","50").action(r1);var wd=S(G.command("tls"),"Drive local certificates with openssl");S(wd.command("status",{isDefault:!0}),"Show certificate and TLS con\
|
|
1652
1652
|
figuration").action((e,t)=>UM(t));S(wd.command("init"),"Create a local CA and a wildcard certificate for the domain").action((e,t)=>qM(t));S(wd.command("trust"),"Print the command to trust the CA on this machine").action((e,t)=>ZM(t));S(wd.command("untrust"),"Print the command to remove it again").action((e,t)=>GM(t));var h1=S(G.command("toolbox"),"Run pinned operational tools in Docker");S(h1.command("build"),"Build the toolbox image").action((e,t)=>WM(t));S(h1.command("run [args...]"),"Run a c\
|
|
1653
|
-
ommand in an ephemeral toolbox container").allowUnknownOption(!0).allowExcessArguments(!0).action((e,t,n)=>VM(e,n));function
|
|
1654
|
-
Fe.usage;return}let t=new T(G.opts());if(e instanceof _e){t.error(e.message),e.hint&&t.hint(e.hint),process.exitCode=e.exitCode;return}t.error(e instanceof Error?e.message:String(e)),process.exitCode=Fe.failure}}i(
|
|
1653
|
+
ommand in an ephemeral toolbox container").allowUnknownOption(!0).allowExcessArguments(!0).action((e,t,n)=>VM(e,n));function Ate(){for(let e of[process.stdout,process.stderr])e.on("error",t=>{throw t.code==="EPIPE"&&process.exit(0),t})}i(Ate,"tolerateClosedOutput");async function Ote(){Ate();try{if(process.argv.length===2){G.outputHelp();return}await G.parseAsync(process.argv)}catch(e){if(e instanceof _v){if(e.code==="commander.helpDisplayed"||e.code==="commander.version")return;process.exitCode=
|
|
1654
|
+
Fe.usage;return}let t=new T(G.opts());if(e instanceof _e){t.error(e.message),e.hint&&t.hint(e.hint),process.exitCode=e.exitCode;return}t.error(e instanceof Error?e.message:String(e)),process.exitCode=Fe.failure}}i(Ote,"main");await Ote();
|