@ebowwa/pkg-ops 0.1.14 → 0.1.15
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/index.d.ts +1 -1
- package/dist/index.js +16 -15
- package/dist/index.js.map +7 -5
- package/package.json +1 -1
- package/src/index.ts +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
2
|
-
var LJ=Object.create;var{getPrototypeOf:OJ,defineProperty:l,getOwnPropertyNames:wJ}=Object;var IJ=Object.prototype.hasOwnProperty;var RJ=(J,W,X)=>{X=J!=null?LJ(OJ(J)):{};let Z=W||!J||!J.__esModule?l(X,"default",{value:J,enumerable:!0}):X;for(let K of wJ(J))if(!IJ.call(Z,K))l(Z,K,{get:()=>J[K],enumerable:!0});return Z};var MJ=(J,W)=>()=>(W||J((W={exports:{}}).exports,W),W.exports);var o=MJ((T)=>{var I=T&&T.__assign||function(){return I=Object.assign||function(J){for(var W,X=1,Z=arguments.length;X<Z;X++){W=arguments[X];for(var K in W)if(Object.prototype.hasOwnProperty.call(W,K))J[K]=W[K]}return J},I.apply(this,arguments)},B=T&&T.__awaiter||function(J,W,X,Z){function K($){return $ instanceof X?$:new X(function(Q){Q($)})}return new(X||(X=Promise))(function($,Q){function z(H){try{Y(Z.next(H))}catch(q){Q(q)}}function G(H){try{Y(Z.throw(H))}catch(q){Q(q)}}function Y(H){H.done?$(H.value):K(H.value).then(z,G)}Y((Z=Z.apply(J,W||[])).next())})},A=T&&T.__generator||function(J,W){var X={label:0,sent:function(){if($[0]&1)throw $[1];return $[1]},trys:[],ops:[]},Z,K,$,Q=Object.create((typeof Iterator==="function"?Iterator:Object).prototype);return Q.next=z(0),Q.throw=z(1),Q.return=z(2),typeof Symbol==="function"&&(Q[Symbol.iterator]=function(){return this}),Q;function z(Y){return function(H){return G([Y,H])}}function G(Y){if(Z)throw TypeError("Generator is already executing.");while(Q&&(Q=0,Y[0]&&(X=0)),X)try{if(Z=1,K&&($=Y[0]&2?K.return:Y[0]?K.throw||(($=K.return)&&$.call(K),0):K.next)&&!($=$.call(K,Y[1])).done)return $;if(K=0,$)Y=[Y[0]&2,$.value];switch(Y[0]){case 0:case 1:$=Y;break;case 4:return X.label++,{value:Y[1],done:!1};case 5:X.label++,K=Y[1],Y=[0];continue;case 7:Y=X.ops.pop(),X.trys.pop();continue;default:if(($=X.trys,!($=$.length>0&&$[$.length-1]))&&(Y[0]===6||Y[0]===2)){X=0;continue}if(Y[0]===3&&(!$||Y[1]>$[0]&&Y[1]<$[3])){X.label=Y[1];break}if(Y[0]===6&&X.label<$[1]){X.label=$[1],$=Y;break}if($&&X.label<$[2]){X.label=$[2],X.ops.push(Y);break}if($[2])X.ops.pop();X.trys.pop();continue}Y=W.call(J,X)}catch(H){Y=[6,H],K=0}finally{Z=$=0}if(Y[0]&5)throw Y[1];return{value:Y[0]?Y[1]:void 0,done:!0}}},R=T&&T.__spreadArray||function(J,W,X){if(X||arguments.length===2){for(var Z=0,K=W.length,$;Z<K;Z++)if($||!(Z in W)){if(!$)$=Array.prototype.slice.call(W,0,Z);$[Z]=W[Z]}}return J.concat($||Array.prototype.slice.call(W))};Object.defineProperty(T,"__esModule",{value:!0});T.sudo=j;T.pkgInstall=kJ;T.writeFile=fJ;T.service=hJ;T.serviceEnable=_J;T.exec=p;function j(J,W){return B(this,void 0,void 0,function(){var X,Z,K;return A(this,function($){return X=Array.isArray(J)?J:J.split(/\s+/),Z=W.env?Object.entries(W.env).map(function(Q){var z=Q[0],G=Q[1];return"".concat(z,"=").concat(v(G))}):[],K=R(R(["sudo"],Z,!0),X,!0),[2,p(K,W)]})})}var xJ={apt:["apt-get","install","-y"],dnf:["dnf","install","-y"],apk:["apk","add","--no-cache"]},NJ={apt:["apt-get","update","-qq"],dnf:["dnf","check-update"],apk:["apk","update"]};function kJ(J,W){return B(this,void 0,void 0,function(){var X,Z,K;return A(this,function($){switch($.label){case 0:return X=(K=W.pm)!==null&&K!==void 0?K:"apt",Z=I(I({},W.env),W.nonInteractive!==!1?{DEBIAN_FRONTEND:"noninteractive"}:{}),[4,j(NJ[X],I(I({},W),{env:Z,quiet:!0}))];case 1:return $.sent(),[2,j(R(R([],xJ[X],!0),J,!0),I(I({},W),{env:Z}))]}})})}function fJ(J,W,X){return B(this,void 0,void 0,function(){var Z,K,$;return A(this,function(Q){switch(Q.label){case 0:return Z=X.append?"-a":"",K="tee ".concat(Z," ").concat(v(J)).trim(),[4,vJ(W,["sudo",K],X)];case 1:if($=Q.sent(),!($.ok&&X.mode))return[3,3];return[4,j(["chmod",X.mode,J],X)];case 2:Q.sent(),Q.label=3;case 3:if(!($.ok&&X.owner))return[3,5];return[4,j(["chown",X.owner,J],X)];case 4:Q.sent(),Q.label=5;case 5:return[2,$]}})})}function hJ(J,W,X){return B(this,void 0,void 0,function(){return A(this,function(Z){return[2,j(["systemctl",W,J],X)]})})}function _J(J,W){return B(this,void 0,void 0,function(){return A(this,function(X){return[2,j(["systemctl","enable","--now",J],W)]})})}function n(J){var W,X=["ssh","-F","/dev/null","-o","StrictHostKeyChecking=no","-o","UserKnownHostsFile=/dev/null"];if(J.keyPath)X.push("-i",J.keyPath);else if(J.key)X.push("-i",J.key);if(J.port)X.push("-p",String(J.port));return X.push("".concat((W=J.user)!==null&&W!==void 0?W:"root","@").concat(J.host)),X}function p(J,W){return B(this,void 0,void 0,function(){var X,Z,K,$,Q,z,G,Y,H;return A(this,function(q){switch(q.label){case 0:return X=(Y=W.context)!==null&&Y!==void 0?Y:{type:"local"},Z=X.type==="ssh"?R(R([],n(X),!0),[J.map(v).join(" ")],!1):J,K=Bun.spawn(Z,{stdout:"pipe",stderr:"pipe",timeout:(H=W.timeout)!==null&&H!==void 0?H:30000}),[4,K.exited];case 1:if($=q.sent(),!W.quiet)return[3,2];return z="",[3,4];case 2:return[4,new Response(K.stdout).text()];case 3:z=q.sent(),q.label=4;case 4:return Q=z,[4,new Response(K.stderr).text()];case 5:return G=q.sent(),[2,{stdout:Q,stderr:G,exitCode:$,ok:$===0}]}})})}function vJ(J,W,X){return B(this,void 0,void 0,function(){var Z,K,$,Q,z,G,Y,H,q,O,D,E,x,m,N,k,f;return A(this,function(L){switch(L.label){case 0:if(Z=(N=X.context)!==null&&N!==void 0?N:{type:"local"},Z.type!=="ssh")return[3,6];return K=n(Z),$=W.join(" "),Q=R(R([],K,!0),[$],!1),z=Bun.spawn(Q,{stdin:new TextEncoder().encode(J),stdout:"pipe",stderr:"pipe",timeout:(k=X.timeout)!==null&&k!==void 0?k:30000}),[4,z.exited];case 1:if(G=L.sent(),!X.quiet)return[3,2];return H="",[3,4];case 2:return[4,new Response(z.stdout).text()];case 3:H=L.sent(),L.label=4;case 4:return Y=H,[4,new Response(z.stderr).text()];case 5:return q=L.sent(),[2,{stdout:Y,stderr:q,exitCode:G,ok:G===0}];case 6:return O=Bun.spawn(["sh","-c",W.join(" ")],{stdin:new TextEncoder().encode(J),stdout:"pipe",stderr:"pipe",timeout:(f=X.timeout)!==null&&f!==void 0?f:30000}),[4,O.exited];case 7:if(D=L.sent(),!X.quiet)return[3,8];return x="",[3,10];case 8:return[4,new Response(O.stdout).text()];case 9:x=L.sent(),L.label=10;case 10:return E=x,[4,new Response(O.stderr).text()];case 11:return m=L.sent(),[2,{stdout:E,stderr:m,exitCode:D,ok:D===0}]}})})}function v(J){if(/^[a-zA-Z0-9._\-\/=:@]+$/.test(J))return J;return"'".concat(J.replace(/'/g,"'\\''"),"'")}});import{readFileSync as pJ,existsSync as oJ}from"node:fs";import{constants as b,mkdirSync as jJ,readFileSync as BJ,writeFileSync as AJ,existsSync as g}from"node:fs";import{dirname as bJ}from"node:path";var h={packages:{},healthPort:8914,workDir:"/root",logLevel:"info"},PJ="/etc/pkg-ops",yJ=`${PJ}/config.json`;function _(){return process.env.PKG_OPS_CONFIG??yJ}function CJ(){let J=bJ(_());if(!g(J))jJ(J,{recursive:!0,mode:b.S_IRWXU|b.S_IRGRP|b.S_IXGRP})}function w(){let J=_();try{if(!g(J))return{...h};let W=BJ(J,"utf-8"),X=JSON.parse(W);return{...h,...X}}catch(W){return console.error(`Failed to load config from ${J}:`,W),{...h}}}function SJ(J){let W=_();CJ();let X=JSON.stringify(J,null,2);AJ(W,X,{encoding:"utf-8",mode:b.S_IRUSR|b.S_IWUSR|b.S_IRGRP})}function S(J,W){let X=w();return X.packages[J]=W,SJ(X),X}function y(J){return w().packages[J]}function c(){let J=w();return Object.entries(J.packages).map(([W,X])=>({name:W,config:X}))}function C(J){return J.startsWith("@ebowwa/")}function i(J){let W=J.lastIndexOf("@");if(W<=0)return{name:J,version:"latest"};let X=J.slice(0,W),Z=J.slice(W+1);if(!Z)return{name:X,version:"latest"};return{name:X,version:Z}}async function M(J,W){let{sudo:X}=await Promise.resolve().then(() => RJ(o(),1));return X(J,W)}async function r(J,W){return M(["systemctl","enable",J],W)}async function t(J,W){return M(["systemctl","disable",J],W)}async function a(J,W){return M(["systemctl","start",J],W)}async function s(J,W){return M(["systemctl","stop",J],W)}async function e(J,W){return M(["systemctl","restart",J],W)}async function JJ(J,W){let X=await M(["systemctl","show",J,"--property=LoadState,ActiveState,SubState,MainPID,Description"],{...W});if(!X.ok)return{loaded:!1,active:!1,subState:"unknown",mainPid:0,description:""};let Z=(K)=>{return X.stdout.match(new RegExp(`^${K}=(.+)$`,"m"))?.[1]?.trim()??""};return{loaded:Z("LoadState")==="loaded",active:Z("ActiveState")==="active",subState:Z("SubState"),mainPid:parseInt(Z("MainPID")||"0",10),description:Z("Description")}}async function WJ(J,W){let X=await M(["systemctl","list-unit-files",J+".service"],{...W,quiet:!0});return X.ok&&X.stdout.includes(J)}async function XJ(J,W={}){let X=["journalctl","-u",J,"-n",String(W.lines??100)];if(W.since)X.push("--since",W.since);if(!W.follow)X.push("-n",String(W.lines??100));return(await M(X,W)).stdout}class ZJ{sudoOptions;constructor(J){this.sudoOptions=J??{context:{type:"local"}}}async start(J){let W=await a(J,this.sudoOptions);return{success:W.ok,message:W.ok?`Service ${J} started`:W.stderr||W.stdout}}async stop(J){let W=await s(J,this.sudoOptions);return{success:W.ok,message:W.ok?`Service ${J} stopped`:W.stderr||W.stdout}}async restart(J){let W=await e(J,this.sudoOptions);return{success:W.ok,message:W.ok?`Service ${J} restarted`:W.stderr||W.stdout}}async status(J){return JJ(J,this.sudoOptions)}async enable(J){let W=await r(J,this.sudoOptions);return{success:W.ok,message:W.ok?`Service ${J} enabled`:W.stderr||W.stdout}}async disable(J){let W=await t(J,this.sudoOptions);return{success:W.ok,message:W.ok?`Service ${J} disabled`:W.stderr||W.stdout}}async exists(J){return WJ(J,this.sudoOptions)}async logs(J,W){return XJ(J,{...this.sudoOptions,lines:W?.lines??100,since:W?.since})}async info(J){let[W,X]=await Promise.all([this.exists(J),this.status(J)]);return{name:J,exists:W,status:X}}async isHealthy(J){let W=await this.status(J);return W.active&&W.subState==="running"}async waitForHealthy(J,W){let X=W?.timeout??30000,Z=W?.interval??1000,K=Date.now();while(Date.now()-K<X){if(await this.isHealthy(J))return!0;await new Promise((Q)=>setTimeout(Q,Z))}return!1}}var u=null;function U(){if(!u)u=new ZJ;return u}import{spawn as uJ}from"child_process";import{accessSync as $J,constants as KJ}from"fs";import{join as d,dirname as dJ}from"path";import{fileURLToPath as mJ}from"url";var lJ=30000;class QJ{process=null;pendingRequests=new Map;requestId=0;buffer="";async start(){if(this.process)return;let J=this.getBinaryPath();try{$J(J,KJ.X_OK)}catch{throw Error(`Rust binary not found at ${J}. Run 'bun run build:rust' in the pkg-ops package.`)}if(this.process=uJ(J,[],{stdio:["pipe","pipe","pipe"]}),!this.process.stdin||!this.process.stdout)throw Error("Failed to create stdin/stdout pipes");this.process.stdout.on("data",(W)=>{this.buffer+=W.toString("utf-8"),this.processBuffer()}),this.process.stderr?.on("data",(W)=>{console.error("[rust-worker]",W.toString("utf-8").trim())}),this.process.on("exit",(W)=>{console.error(`Rust worker exited with code ${W}`),this.process=null})}async stop(){if(!this.process)return;try{await this.sendRequest("shutdown",{})}catch{}if(await new Promise((J)=>setTimeout(J,1000)),this.process)this.process.kill("SIGTERM"),this.process=null;for(let[J,W]of this.pendingRequests)clearTimeout(W.timeout),W.reject(Error("Bridge shutdown"));this.pendingRequests.clear()}async install(J,W){return this.sendRequest("install",{packageName:J,version:W})}async update(J){return this.sendRequest("update",{packageName:J})}async updateAll(){return this.sendRequest("updateAll",{})}async list(){return this.sendRequest("list",{})}async rollback(J){return this.sendRequest("rollback",{packageName:J})}async health(){return this.sendRequest("health",{})}async verify(J){return this.sendRequest("verify",{packageName:J})}async audit(){return this.sendRequest("audit",{})}async getBundleSizes(){return this.sendRequest("sizes",{})}async getInstalledInfo(){return this.sendRequest("installedInfo",{})}getBinaryPath(){let J=dJ(mJ(import.meta.url)),W=[d(J,"..","rust","target","release","pkg-ops-core"),d(J,"..","rust","pkg-ops-core"),d(J,"..","rust","target","x86_64-unknown-linux-gnu","release","pkg-ops-core")];for(let X of W)try{return $J(X,KJ.X_OK),X}catch{}throw Error(`Rust binary not found. Tried:
|
|
3
|
-
${W.map((X)=>` - ${X}`).join(`
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
var RJ=Object.create;var{getPrototypeOf:MJ,defineProperty:e,getOwnPropertyNames:IJ}=Object;var AJ=Object.prototype.hasOwnProperty;var bJ=(W,J,X)=>{X=W!=null?RJ(MJ(W)):{};let Z=J||!W||!W.__esModule?e(X,"default",{value:W,enumerable:!0}):X;for(let $ of IJ(W))if(!AJ.call(Z,$))e(Z,$,{get:()=>W[$],enumerable:!0});return Z};var PJ=(W,J)=>()=>(J||W((J={exports:{}}).exports,J),J.exports);var KJ=PJ((U)=>{var j=U&&U.__assign||function(){return j=Object.assign||function(W){for(var J,X=1,Z=arguments.length;X<Z;X++){J=arguments[X];for(var $ in J)if(Object.prototype.hasOwnProperty.call(J,$))W[$]=J[$]}return W},j.apply(this,arguments)},M=U&&U.__awaiter||function(W,J,X,Z){function $(K){return K instanceof X?K:new X(function(Q){Q(K)})}return new(X||(X=Promise))(function(K,Q){function z(G){try{Y(Z.next(G))}catch(H){Q(H)}}function q(G){try{Y(Z.throw(G))}catch(H){Q(H)}}function Y(G){G.done?K(G.value):$(G.value).then(z,q)}Y((Z=Z.apply(W,J||[])).next())})},I=U&&U.__generator||function(W,J){var X={label:0,sent:function(){if(K[0]&1)throw K[1];return K[1]},trys:[],ops:[]},Z,$,K,Q=Object.create((typeof Iterator==="function"?Iterator:Object).prototype);return Q.next=z(0),Q.throw=z(1),Q.return=z(2),typeof Symbol==="function"&&(Q[Symbol.iterator]=function(){return this}),Q;function z(Y){return function(G){return q([Y,G])}}function q(Y){if(Z)throw TypeError("Generator is already executing.");while(Q&&(Q=0,Y[0]&&(X=0)),X)try{if(Z=1,$&&(K=Y[0]&2?$.return:Y[0]?$.throw||((K=$.return)&&K.call($),0):$.next)&&!(K=K.call($,Y[1])).done)return K;if($=0,K)Y=[Y[0]&2,K.value];switch(Y[0]){case 0:case 1:K=Y;break;case 4:return X.label++,{value:Y[1],done:!1};case 5:X.label++,$=Y[1],Y=[0];continue;case 7:Y=X.ops.pop(),X.trys.pop();continue;default:if((K=X.trys,!(K=K.length>0&&K[K.length-1]))&&(Y[0]===6||Y[0]===2)){X=0;continue}if(Y[0]===3&&(!K||Y[1]>K[0]&&Y[1]<K[3])){X.label=Y[1];break}if(Y[0]===6&&X.label<K[1]){X.label=K[1],K=Y;break}if(K&&X.label<K[2]){X.label=K[2],X.ops.push(Y);break}if(K[2])X.ops.pop();X.trys.pop();continue}Y=J.call(W,X)}catch(G){Y=[6,G],$=0}finally{Z=K=0}if(Y[0]&5)throw Y[1];return{value:Y[0]?Y[1]:void 0,done:!0}}},w=U&&U.__spreadArray||function(W,J,X){if(X||arguments.length===2){for(var Z=0,$=J.length,K;Z<$;Z++)if(K||!(Z in J)){if(!K)K=Array.prototype.slice.call(J,0,Z);K[Z]=J[Z]}}return W.concat(K||Array.prototype.slice.call(J))};Object.defineProperty(U,"__esModule",{value:!0});U.sudo=R;U.pkgInstall=uJ;U.writeFile=dJ;U.service=mJ;U.serviceEnable=lJ;U.exec=$J;function R(W,J){return M(this,void 0,void 0,function(){var X,Z,$;return I(this,function(K){return X=Array.isArray(W)?W:W.split(/\s+/),Z=J.env?Object.entries(J.env).map(function(Q){var z=Q[0],q=Q[1];return"".concat(z,"=").concat(p(q))}):[],$=w(w(["sudo"],Z,!0),X,!0),[2,$J($,J)]})})}var fJ={apt:["apt-get","install","-y"],dnf:["dnf","install","-y"],apk:["apk","add","--no-cache"]},vJ={apt:["apt-get","update","-qq"],dnf:["dnf","check-update"],apk:["apk","update"]};function uJ(W,J){return M(this,void 0,void 0,function(){var X,Z,$;return I(this,function(K){switch(K.label){case 0:return X=($=J.pm)!==null&&$!==void 0?$:"apt",Z=j(j({},J.env),J.nonInteractive!==!1?{DEBIAN_FRONTEND:"noninteractive"}:{}),[4,R(vJ[X],j(j({},J),{env:Z,quiet:!0}))];case 1:return K.sent(),[2,R(w(w([],fJ[X],!0),W,!0),j(j({},J),{env:Z}))]}})})}function dJ(W,J,X){return M(this,void 0,void 0,function(){var Z,$,K;return I(this,function(Q){switch(Q.label){case 0:return Z=X.append?"-a":"",$="tee ".concat(Z," ").concat(p(W)).trim(),[4,gJ(J,["sudo",$],X)];case 1:if(K=Q.sent(),!(K.ok&&X.mode))return[3,3];return[4,R(["chmod",X.mode,W],X)];case 2:Q.sent(),Q.label=3;case 3:if(!(K.ok&&X.owner))return[3,5];return[4,R(["chown",X.owner,W],X)];case 4:Q.sent(),Q.label=5;case 5:return[2,K]}})})}function mJ(W,J,X){return M(this,void 0,void 0,function(){return I(this,function(Z){return[2,R(["systemctl",J,W],X)]})})}function lJ(W,J){return M(this,void 0,void 0,function(){return I(this,function(X){return[2,R(["systemctl","enable","--now",W],J)]})})}function ZJ(W){var J,X=["ssh","-F","/dev/null","-o","StrictHostKeyChecking=no","-o","UserKnownHostsFile=/dev/null"];if(W.keyPath)X.push("-i",W.keyPath);else if(W.key)X.push("-i",W.key);if(W.port)X.push("-p",String(W.port));return X.push("".concat((J=W.user)!==null&&J!==void 0?J:"root","@").concat(W.host)),X}function $J(W,J){return M(this,void 0,void 0,function(){var X,Z,$,K,Q,z,q,Y,G;return I(this,function(H){switch(H.label){case 0:return X=(Y=J.context)!==null&&Y!==void 0?Y:{type:"local"},Z=X.type==="ssh"?w(w([],ZJ(X),!0),[W.map(p).join(" ")],!1):W,$=Bun.spawn(Z,{stdout:"pipe",stderr:"pipe",timeout:(G=J.timeout)!==null&&G!==void 0?G:30000}),[4,$.exited];case 1:if(K=H.sent(),!J.quiet)return[3,2];return z="",[3,4];case 2:return[4,new Response($.stdout).text()];case 3:z=H.sent(),H.label=4;case 4:return Q=z,[4,new Response($.stderr).text()];case 5:return q=H.sent(),[2,{stdout:Q,stderr:q,exitCode:K,ok:K===0}]}})})}function gJ(W,J,X){return M(this,void 0,void 0,function(){var Z,$,K,Q,z,q,Y,G,H,O,T,L,d,s,m,l,g;return I(this,function(F){switch(F.label){case 0:if(Z=(m=X.context)!==null&&m!==void 0?m:{type:"local"},Z.type!=="ssh")return[3,6];return $=ZJ(Z),K=J.join(" "),Q=w(w([],$,!0),[K],!1),z=Bun.spawn(Q,{stdin:new TextEncoder().encode(W),stdout:"pipe",stderr:"pipe",timeout:(l=X.timeout)!==null&&l!==void 0?l:30000}),[4,z.exited];case 1:if(q=F.sent(),!X.quiet)return[3,2];return G="",[3,4];case 2:return[4,new Response(z.stdout).text()];case 3:G=F.sent(),F.label=4;case 4:return Y=G,[4,new Response(z.stderr).text()];case 5:return H=F.sent(),[2,{stdout:Y,stderr:H,exitCode:q,ok:q===0}];case 6:return O=Bun.spawn(["sh","-c",J.join(" ")],{stdin:new TextEncoder().encode(W),stdout:"pipe",stderr:"pipe",timeout:(g=X.timeout)!==null&&g!==void 0?g:30000}),[4,O.exited];case 7:if(T=F.sent(),!X.quiet)return[3,8];return d="",[3,10];case 8:return[4,new Response(O.stdout).text()];case 9:d=F.sent(),F.label=10;case 10:return L=d,[4,new Response(O.stderr).text()];case 11:return s=F.sent(),[2,{stdout:L,stderr:s,exitCode:T,ok:T===0}]}})})}function p(W){if(/^[a-zA-Z0-9._\-\/=:@]+$/.test(W))return W;return"'".concat(W.replace(/'/g,"'\\''"),"'")}});import{readFileSync as ZW,existsSync as $W}from"fs";import{constants as A,mkdirSync as yJ,readFileSync as xJ,writeFileSync as CJ,existsSync as JJ}from"node:fs";import{dirname as NJ}from"node:path";var c={packages:{},healthPort:8914,workDir:"/root",logLevel:"info"},SJ="/etc/pkg-ops",kJ=`${SJ}/config.json`;function i(){return process.env.PKG_OPS_CONFIG??kJ}function _J(){let W=NJ(i());if(!JJ(W))yJ(W,{recursive:!0,mode:A.S_IRWXU|A.S_IRGRP|A.S_IXGRP})}function b(){let W=i();try{if(!JJ(W))return{...c};let J=xJ(W,"utf-8"),X=JSON.parse(J);return{...c,...X}}catch(J){return console.error(`Failed to load config from ${W}:`,J),{...c}}}function hJ(W){let J=i();_J();let X=JSON.stringify(W,null,2);CJ(J,X,{encoding:"utf-8",mode:A.S_IRUSR|A.S_IWUSR|A.S_IRGRP})}function C(W,J){let X=b();return X.packages[W]=J,hJ(X),X}function y(W){return b().packages[W]}function WJ(){let W=b();return Object.entries(W.packages).map(([J,X])=>({name:J,config:X}))}function x(W){return W.startsWith("@ebowwa/")}function XJ(W){let J=W.lastIndexOf("@");if(J<=0)return{name:W,version:"latest"};let X=W.slice(0,J),Z=W.slice(J+1);if(!Z)return{name:X,version:"latest"};return{name:X,version:Z}}async function B(W,J){let{sudo:X}=await Promise.resolve().then(() => bJ(KJ(),1));return X(W,J)}async function N(W,J){return B(["systemctl","enable",W],J)}async function S(W,J){return B(["systemctl","disable",W],J)}async function k(W,J){return B(["systemctl","start",W],J)}async function _(W,J){return B(["systemctl","stop",W],J)}async function h(W,J){return B(["systemctl","restart",W],J)}async function f(W,J){let X=await B(["systemctl","show",W,"--property=LoadState,ActiveState,SubState,MainPID,Description"],{...J});if(!X.ok)return{loaded:!1,active:!1,subState:"unknown",mainPid:0,description:""};let Z=($)=>{return X.stdout.match(new RegExp(`^${$}=(.+)$`,"m"))?.[1]?.trim()??""};return{loaded:Z("LoadState")==="loaded",active:Z("ActiveState")==="active",subState:Z("SubState"),mainPid:parseInt(Z("MainPID")||"0",10),description:Z("Description")}}async function v(W,J){let X=await B(["systemctl","list-unit-files",W+".service"],{...J,quiet:!0});return X.ok&&X.stdout.includes(W)}async function u(W,J={}){let X=["journalctl","-u",W,"-n",String(J.lines??100)];if(J.since)X.push("--since",J.since);if(!J.follow)X.push("-n",String(J.lines??100));return(await B(X,J)).stdout}class QJ{sudoOptions;constructor(W){this.sudoOptions=W??{context:{type:"local"}}}async start(W){let J=await k(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} started`:J.stderr||J.stdout}}async stop(W){let J=await _(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} stopped`:J.stderr||J.stdout}}async restart(W){let J=await h(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} restarted`:J.stderr||J.stdout}}async status(W){return f(W,this.sudoOptions)}async enable(W){let J=await N(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} enabled`:J.stderr||J.stdout}}async disable(W){let J=await S(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} disabled`:J.stderr||J.stdout}}async exists(W){return v(W,this.sudoOptions)}async logs(W,J){return u(W,{...this.sudoOptions,lines:J?.lines??100,since:J?.since})}async info(W){let[J,X]=await Promise.all([this.exists(W),this.status(W)]);return{name:W,exists:J,status:X}}async isHealthy(W){let J=await this.status(W);return J.active&&J.subState==="running"}async waitForHealthy(W,J){let X=J?.timeout??30000,Z=J?.interval??1000,$=Date.now();while(Date.now()-$<X){if(await this.isHealthy(W))return!0;await new Promise((Q)=>setTimeout(Q,Z))}return!1}}var n=null;function V(){if(!n)n=new QJ;return n}import{spawn as cJ}from"child_process";import{accessSync as YJ,constants as zJ}from"fs";import{join as o,dirname as iJ}from"path";import{fileURLToPath as pJ}from"url";var nJ=30000;class qJ{process=null;pendingRequests=new Map;requestId=0;buffer="";async start(){if(this.process)return;let W=this.getBinaryPath();try{YJ(W,zJ.X_OK)}catch{throw Error(`Rust binary not found at ${W}. Run 'bun run build:rust' in the pkg-ops package.`)}if(this.process=cJ(W,[],{stdio:["pipe","pipe","pipe"]}),!this.process.stdin||!this.process.stdout)throw Error("Failed to create stdin/stdout pipes");this.process.stdout.on("data",(J)=>{this.buffer+=J.toString("utf-8"),this.processBuffer()}),this.process.stderr?.on("data",(J)=>{console.error("[rust-worker]",J.toString("utf-8").trim())}),this.process.on("exit",(J)=>{console.error(`Rust worker exited with code ${J}`),this.process=null})}async stop(){if(!this.process)return;try{await this.sendRequest("shutdown",{})}catch{}if(await new Promise((W)=>setTimeout(W,1000)),this.process)this.process.kill("SIGTERM"),this.process=null;for(let[W,J]of this.pendingRequests)clearTimeout(J.timeout),J.reject(Error("Bridge shutdown"));this.pendingRequests.clear()}async install(W,J){return this.sendRequest("install",{packageName:W,version:J})}async update(W){return this.sendRequest("update",{packageName:W})}async updateAll(){return this.sendRequest("updateAll",{})}async list(){return this.sendRequest("list",{})}async rollback(W){return this.sendRequest("rollback",{packageName:W})}async health(){return this.sendRequest("health",{})}async verify(W){return this.sendRequest("verify",{packageName:W})}async audit(){return this.sendRequest("audit",{})}async getBundleSizes(){return this.sendRequest("sizes",{})}async getInstalledInfo(){return this.sendRequest("installedInfo",{})}getBinaryPath(){let W=iJ(pJ(import.meta.url)),J=[o(W,"..","rust","target","release","pkg-ops-core"),o(W,"..","rust","pkg-ops-core"),o(W,"..","rust","target","x86_64-unknown-linux-gnu","release","pkg-ops-core")];for(let X of J)try{return YJ(X,zJ.X_OK),X}catch{}throw Error(`Rust binary not found. Tried:
|
|
4
|
+
${J.map((X)=>` - ${X}`).join(`
|
|
4
5
|
`)}
|
|
5
|
-
Run 'bun run build:rust' or 'cargo build --release' in the pkg-ops package.`)}sendRequest(J
|
|
6
|
-
`;this.process.stdin.write(z,"utf-8",(
|
|
7
|
-
`);this.buffer=
|
|
8
|
-
`);try{let X=await(await
|
|
9
|
-
Packages:`);let X=
|
|
10
|
-
Package: ${Z.packageName}@${Z.version}`),console.log(` Status: ${Z.success?"VALID":"INVALID"}`),console.log(` Dist exists: ${Z.distExists?"Yes":"No"}`),Z.checksum)console.log(` Checksum: ${Z.checksum}`);console.log(` Message: ${Z.message}`)}catch(X){console.error("Verification failed:",X),process.exit(1)}finally{await
|
|
11
|
-
`)
|
|
12
|
-
`);try{let X=await(await
|
|
13
|
-
`);for(let Z of X)console.log(`[${Z.severity.toUpperCase()}] ${Z.packageName}`),console.log(` Vulnerability: ${Z.vulnerability}`),console.log(` Description: ${Z.description}`),console.log("")}catch(
|
|
14
|
-
`);try{let X=await(await
|
|
6
|
+
Run 'bun run build:rust' or 'cargo build --release' in the pkg-ops package.`)}sendRequest(W,J){return new Promise((X,Z)=>{if(!this.process?.stdin){Z(Error("Rust worker not started"));return}let $=String(++this.requestId),K={jsonrpc:"2.0",id:$,method:W,params:J},Q=setTimeout(()=>{this.pendingRequests.delete($),Z(Error(`Request timeout: ${W}`))},nJ);this.pendingRequests.set($,{resolve:X,reject:Z,timeout:Q});let z=JSON.stringify(K)+`
|
|
7
|
+
`;this.process.stdin.write(z,"utf-8",(q)=>{if(q)this.pendingRequests.delete($),clearTimeout(Q),Z(q)})})}processBuffer(){let W=this.buffer.split(`
|
|
8
|
+
`);this.buffer=W.pop()??"";for(let J of W){if(!J.trim())continue;try{let X=JSON.parse(J),Z=this.pendingRequests.get(X.id);if(Z)if(clearTimeout(Z.timeout),this.pendingRequests.delete(X.id),X.error)Z.reject(Error(X.error.message));else Z.resolve(X.result)}catch(X){console.error("Failed to parse response:",J,X)}}}}var P=null;function oJ(){if(!P)P=new qJ;return P}async function D(){let W=oJ();return await W.start(),W}async function E(){if(P)await P.stop(),P=null}import{createServer as JW}from"http";class HJ{sudoOptions;constructor(W){this.sudoOptions=W??{context:{type:"local"}}}async start(W){let J=await k(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} started`:J.stderr||J.stdout}}async stop(W){let J=await _(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} stopped`:J.stderr||J.stdout}}async restart(W){let J=await h(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} restarted`:J.stderr||J.stdout}}async status(W){return f(W,this.sudoOptions)}async enable(W){let J=await N(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} enabled`:J.stderr||J.stdout}}async disable(W){let J=await S(W,this.sudoOptions);return{success:J.ok,message:J.ok?`Service ${W} disabled`:J.stderr||J.stdout}}async exists(W){return v(W,this.sudoOptions)}async logs(W,J){return u(W,{...this.sudoOptions,lines:J?.lines??100,since:J?.since})}async info(W){let[J,X]=await Promise.all([this.exists(W),this.status(W)]);return{name:W,exists:J,status:X}}async isHealthy(W){let J=await this.status(W);return J.active&&J.subState==="running"}async waitForHealthy(W,J){let X=J?.timeout??30000,Z=J?.interval??1000,$=Date.now();while(Date.now()-$<X){if(await this.isHealthy(W))return!0;await new Promise((Q)=>setTimeout(Q,Z))}return!1}}var r=null;function t(){if(!r)r=new HJ;return r}import{constants as vW,mkdirSync as uW,readFileSync as rJ,writeFileSync as dW,existsSync as tJ}from"node:fs";var a={packages:{},healthPort:8914,workDir:"/root",logLevel:"info"},aJ="/etc/pkg-ops",sJ=`${aJ}/config.json`;function eJ(){return process.env.PKG_OPS_CONFIG??sJ}function GJ(){let W=eJ();try{if(!tJ(W))return{...a};let J=rJ(W,"utf-8"),X=JSON.parse(J);return{...a,...X}}catch(J){return console.error(`Failed to load config from ${W}:`,J),{...a}}}class WW{server=null;checks=new Map;startTime=Date.now();port;constructor(W=8914){this.port=W}async start(){if(this.server)return;return new Promise((W,J)=>{this.server=JW((X,Z)=>this.handleRequest(X,Z)),this.server.on("error",J),this.server.listen(this.port,()=>{console.log(`Health server listening on port ${this.port}`),this.server?.off("error",J),W()})})}async stop(){if(!this.server)return;return new Promise((W)=>{this.server?.close(()=>{this.server=null,W()})})}addCheck(W,J){this.checks.set(W,J)}removeCheck(W){this.checks.delete(W)}async checkHealth(W){if(W)return this.getServiceHealth(W);return this.getSystemHealth()}async handleRequest(W,J){let X=W.url??"/",Z=W.method??"GET";try{if(Z==="GET"&&X==="/health"){let $=await this.getSystemHealth();this.sendJson(J,200,$)}else if(Z==="GET"&&X.startsWith("/health/")){let $=X.slice(8).replace(".service",""),K=await this.getServiceHealth($);this.sendJson(J,K?200:404,K??{error:"Service not found"})}else if(Z==="GET"&&X==="/ready"){let $=await this.getSystemHealth();this.sendJson(J,$.healthy?200:503,{ready:$.healthy})}else if(Z==="GET"&&X==="/live")this.sendJson(J,200,{alive:!0});else this.sendJson(J,404,{error:"Not found"})}catch($){console.error("Health check error:",$),this.sendJson(J,500,{error:"Internal server error"})}}async getSystemHealth(){let W=GJ(),J=t(),X=[];for(let[K,Q]of Object.entries(W.packages)){if(!Q.service)continue;let z=await J.status(Q.service),q=z.active&&z.subState==="running";X.push({name:Q.service,healthy:q,status:z,checkedAt:new Date().toISOString()})}let Z={};for(let[K,Q]of this.checks)try{Z[K]=await Q()}catch(z){Z[K]={healthy:!1,message:z instanceof Error?z.message:"Unknown error"}}return{healthy:X.every((K)=>K.healthy)&&Object.values(Z).every((K)=>K.healthy),services:X,uptime:Math.floor((Date.now()-this.startTime)/1000),timestamp:new Date().toISOString()}}async getServiceHealth(W){let J=t();if(!await J.exists(W))return null;let Z=await J.status(W),$=Z.active&&Z.subState==="running";return{name:W,healthy:$,status:Z,checkedAt:new Date().toISOString()}}sendJson(W,J,X){W.statusCode=J,W.setHeader("Content-Type","application/json"),W.end(JSON.stringify(X,null,2))}}var XW=null;function UJ(){return XW}async function KW(W){if(W.length===0)console.error("Usage: pkg-ops install <package>[@version]"),process.exit(1);let J=W[0],{name:X,version:Z}=XJ(J);if(!x(X))console.error("Invalid package name. Only @ebowwa/* packages are supported."),process.exit(1);console.log(`Installing ${X}@${Z}...`);try{let K=await(await D()).install(X,Z);if(K.success){if(console.log(`Successfully installed ${X}@${K.version}`),K.previousVersion)console.log(` Previous version: ${K.previousVersion}`);C(X,{version:K.version,service:X.replace("@ebowwa/","")});let Q=y(X);if(Q?.service&&Q.autoStart!==!1){let q=await V().start(Q.service);if(q.success)console.log(` Service ${Q.service} started`);else console.warn(` Failed to start service: ${q.message}`)}}else console.error(`Failed to install ${X}: ${K.message}`),process.exit(1)}catch($){console.error("Install failed:",$),process.exit(1)}finally{await E()}}async function QW(W){if(W.length===0)console.error("Usage: pkg-ops update <package>"),process.exit(1);let J=W[0];if(!x(J))console.error("Invalid package name. Only @ebowwa/* packages are supported."),process.exit(1);console.log(`Updating ${J}...`);try{let Z=await(await D()).update(J);if(Z.success){if(console.log(`Successfully updated ${J} to ${Z.version}`),Z.previousVersion)console.log(` Previous version: ${Z.previousVersion}`);C(J,{version:Z.version,service:J.replace("@ebowwa/","")});let $=V(),K=y(J);if(K?.service){if((await $.status(K.service)).active)await $.restart(K.service),console.log(` Service ${K.service} restarted`)}}else console.error(`Failed to update ${J}: ${Z.message}`),process.exit(1)}catch(X){console.error("Update failed:",X),process.exit(1)}finally{await E()}}async function YW(W){console.log("Updating all managed packages...");try{let X=await(await D()).updateAll();for(let Z of X)if(Z.success)console.log(`Updated ${Z.version}`);else console.error(`Failed to update: ${Z.message}`)}catch(J){console.error("Update all failed:",J),process.exit(1)}finally{await E()}}async function zW(W){console.log(`Installed packages:
|
|
9
|
+
`);try{let X=await(await D()).list();if(X.length===0){console.log(" No packages installed");return}for(let Z of X){let $=Z.installed?"installed":"not installed",K=Z.service?` (service: ${Z.service})`:"";console.log(` ${Z.name}@${Z.version} [${$}]${K}`)}}catch(J){console.error("Failed to list packages:",J),process.exit(1)}finally{await E()}}async function qW(W){if(W.length===0)console.error("Usage: pkg-ops rollback <package>"),process.exit(1);let J=W[0];console.log(`Rolling back ${J}...`);try{let Z=await(await D()).rollback(J);if(Z.success){console.log(`Rolled back ${J} from ${Z.currentVersion} to ${Z.previousVersion}`);let $=V(),K=y(J);if(K?.service){if((await $.status(K.service)).active)await $.restart(K.service),console.log(` Service ${K.service} restarted`)}}else console.error(`Rollback failed: ${Z.message}`),process.exit(1)}catch(X){console.error("Rollback failed:",X),process.exit(1)}finally{await E()}}async function VJ(W){if(W.length===0)console.error("Usage: pkg-ops service start <name>"),process.exit(1);let J=W[0],X=V();console.log(`Starting ${J}...`);let Z=await X.start(J);if(Z.success)console.log(`Service ${J} started`);else console.error(`Failed to start ${J}: ${Z.message}`),process.exit(1)}async function TJ(W){if(W.length===0)console.error("Usage: pkg-ops service stop <name>"),process.exit(1);let J=W[0],X=V();console.log(`Stopping ${J}...`);let Z=await X.stop(J);if(Z.success)console.log(`Service ${J} stopped`);else console.error(`Failed to stop ${J}: ${Z.message}`),process.exit(1)}async function DJ(W){if(W.length===0)console.error("Usage: pkg-ops service restart <name>"),process.exit(1);let J=W[0],X=V();console.log(`Restarting ${J}...`);let Z=await X.restart(J);if(Z.success)console.log(`Service ${J} restarted`);else console.error(`Failed to restart ${J}: ${Z.message}`),process.exit(1)}async function EJ(W){if(W.length===0)console.error("Usage: pkg-ops service status <name>"),process.exit(1);let J=W[0],Z=await V().info(J);if(!Z.exists){console.log(`Service ${J} not found`);return}console.log(`Service: ${J}`),console.log(` Loaded: ${Z.status.loaded}`),console.log(` Active: ${Z.status.active}`),console.log(` State: ${Z.status.subState}`),console.log(` PID: ${Z.status.mainPid||"N/A"}`),console.log(` Description: ${Z.status.description||"N/A"}`)}async function LJ(W){if(W.length===0)console.error("Usage: pkg-ops service logs <name> [--lines N]"),process.exit(1);let J=W[0],X=W.indexOf("--lines"),Z=X>=0&&W[X+1]?parseInt(W[X+1],10):100,K=await V().logs(J,{lines:Z});console.log(K)}async function FJ(W){if(W.length===0)console.error("Usage: pkg-ops service enable <name>"),process.exit(1);let J=W[0],X=V();console.log(`Enabling ${J}...`);let Z=await X.enable(J);if(Z.success)console.log(`Service ${J} enabled on boot`);else console.error(`Failed to enable ${J}: ${Z.message}`),process.exit(1)}async function OJ(W){if(W.length===0)console.error("Usage: pkg-ops service disable <name>"),process.exit(1);let J=W[0],X=V();console.log(`Disabling ${J}...`);let Z=await X.disable(J);if(Z.success)console.log(`Service ${J} disabled from boot`);else console.error(`Failed to disable ${J}: ${Z.message}`),process.exit(1)}async function HW(W){let J=W[0],X=UJ();if(!X)console.error("Health server not initialized"),process.exit(1);let Z=await X.checkHealth(J);if(!Z){console.log("Service not found");return}if("services"in Z){if(Z.healthy)console.log("All services healthy");else console.log("Some services unhealthy");for(let $ of Z.services){let K=$.healthy?"OK":"FAIL";console.log(` [${K}] ${$.name}: ${$.status.subState}`)}}else{let $=Z.healthy?"OK":"FAIL";console.log(`[${$}] ${Z.name}: ${Z.status.subState}`)}}async function jJ(W){let J=b();console.log("PkgOps Configuration"),console.log("Config path: /etc/pkg-ops/config.json"),console.log(`Health port: ${J.healthPort}`),console.log(`Work dir: ${J.workDir}`),console.log(`Log level: ${J.logLevel}`),console.log(`
|
|
10
|
+
Packages:`);let X=WJ();if(X.length===0){console.log(" No packages configured");return}for(let{name:Z,config:$}of X){if(console.log(` ${Z}:`),console.log(` Version: ${$.version}`),$.service)console.log(` Service: ${$.service}`);if($.autoStart!==void 0)console.log(` Auto-start: ${$.autoStart}`)}}async function wJ(W){if(W.length<3)console.error("Usage: pkg-ops config set <package> <key> <value>"),process.exit(1);let J=W[0],X=W[1],Z=W[2];if(!x(J))console.error("Invalid package name. Only @ebowwa/* packages are supported."),process.exit(1);let $=y(J)??{version:"latest"};switch(X){case"version":$.version=Z;break;case"service":$.service=Z;break;case"autoStart":$.autoStart=Z==="true";break;default:console.error(`Unknown config key: ${X}`),console.error("Valid keys: version, service, autoStart"),process.exit(1)}C(J,$),console.log(`Updated ${J}.${X} = ${Z}`)}async function GW(W){if(W.length===0)console.error("Usage: pkg-ops verify <package>"),process.exit(1);let J=W[0];if(!x(J))console.error("Invalid package name. Only @ebowwa/* packages are supported."),process.exit(1);console.log(`Verifying ${J}...`);try{let Z=await(await D()).verify(J);if(console.log(`
|
|
11
|
+
Package: ${Z.packageName}@${Z.version}`),console.log(` Status: ${Z.success?"VALID":"INVALID"}`),console.log(` Dist exists: ${Z.distExists?"Yes":"No"}`),Z.checksum)console.log(` Checksum: ${Z.checksum}`);console.log(` Message: ${Z.message}`)}catch(X){console.error("Verification failed:",X),process.exit(1)}finally{await E()}}async function UW(W){let J=W.indexOf("--local"),X=W.indexOf("--local-path"),Z="./package.json";if(X>=0&&W[X+1])Z=W[X+1];let $=J>=0||X>=0;try{let Q=await(await D()).getInstalledInfo();if(console.log(`Sync Status: Local vs VPS
|
|
12
|
+
`),$&&$W(Z)){let z=ZW(Z,"utf-8"),q=JSON.parse(z),Y={...q.dependencies,...q.devDependencies},G=new Map;for(let H of Q)G.set(H.packageName,H.version);for(let[H,O]of Object.entries(Y)){if(!H.startsWith("@ebowwa/"))continue;let T=G.get(H),L=O.replace(/^[\^~]/,"");if(T){if(L===T)console.log(` ${H}: local=${L}, vps=${T} (in sync)`);else if(L>T)console.log(` ${H}: local=${L}, vps=${T} (VPS behind)`);else console.log(` ${H}: local=${L}, vps=${T} (local behind)`);G.delete(H)}else console.log(` ${H}: local=${L}, vps=not installed`)}for(let[H,O]of G)console.log(` ${H}: local=not in package.json, vps=${O}`)}else if(Q.length===0)console.log(" No packages installed on VPS");else for(let z of Q){let q=z.distSizeBytes?` (${(z.distSizeBytes/1024).toFixed(1)} KB)`:"";console.log(` ${z.packageName}@${z.version}${q}`)}}catch(K){console.error("Failed to get sync status:",K),process.exit(1)}finally{await E()}}async function BJ(W){console.log(`Running vulnerability scan...
|
|
13
|
+
`);try{let X=await(await D()).audit();if(X.length===0){console.log("No vulnerabilities found.");return}console.log(`Found ${X.length} vulnerability(es):
|
|
14
|
+
`);for(let Z of X)console.log(`[${Z.severity.toUpperCase()}] ${Z.packageName}`),console.log(` Vulnerability: ${Z.vulnerability}`),console.log(` Description: ${Z.description}`),console.log("")}catch(J){console.error("Audit failed:",J),process.exit(1)}finally{await E()}}async function VW(W){await BJ(W)}async function TW(W){console.log(`Bundle sizes:
|
|
15
|
+
`);try{let X=await(await D()).getBundleSizes();if(X.length===0){console.log(" No packages installed");return}console.log(" Package | Version | Dist Size"),console.log(" --------------------------------|----------|-----------");for(let Z of X){let $=Z.packageName.padEnd(32),K=Z.version.padEnd(9),Q=(Z.distSizeBytes/1024).toFixed(1)+" KB",z=Z.fileCount?` (${Z.fileCount} files)`:"";console.log(` ${$} | ${K} | ${Q}${z}`)}}catch(J){console.error("Failed to get bundle sizes:",J),process.exit(1)}finally{await E()}}var DW=[{name:"install",description:"Install an @ebowwa/* package",usage:"pkg-ops install <package>[@version]",handler:KW},{name:"update",description:"Update a package to latest version",usage:"pkg-ops update <package>",handler:QW},{name:"update-all",description:"Update all managed packages",usage:"pkg-ops update-all",handler:YW},{name:"list",description:"List installed packages",usage:"pkg-ops list",handler:zW},{name:"rollback",description:"Rollback a package to previous version",usage:"pkg-ops rollback <package>",handler:qW},{name:"start",description:"Start a systemd service",usage:"pkg-ops service start <name>",handler:VJ},{name:"stop",description:"Stop a systemd service",usage:"pkg-ops service stop <name>",handler:TJ},{name:"restart",description:"Restart a systemd service",usage:"pkg-ops service restart <name>",handler:DJ},{name:"status",description:"Get service status",usage:"pkg-ops service status <name>",handler:EJ},{name:"logs",description:"View service logs",usage:"pkg-ops service logs <name> [--lines N]",handler:LJ},{name:"enable",description:"Enable service on boot",usage:"pkg-ops service enable <name>",handler:FJ},{name:"disable",description:"Disable service from boot",usage:"pkg-ops service disable <name>",handler:OJ},{name:"health",description:"Check health of all services",usage:"pkg-ops health [service]",handler:HW},{name:"config",description:"Show configuration",usage:"pkg-ops config show",handler:jJ},{name:"set-config",description:"Set a config value",usage:"pkg-ops config set <package> <key> <value>",handler:wJ},{name:"verify",description:"Verify package integrity",usage:"pkg-ops verify <package>",handler:GW},{name:"sync-status",description:"Show local vs VPS version sync",usage:"pkg-ops sync-status [--local-path path]",handler:UW},{name:"audit",description:"Check for vulnerabilities",usage:"pkg-ops audit",handler:BJ},{name:"scan",description:"Alias for audit",usage:"pkg-ops scan",handler:VW},{name:"sizes",description:"Show bundle sizes",usage:"pkg-ops sizes",handler:TW}],EW=[{name:"start",description:"Start a systemd service",usage:"pkg-ops service start <name>",handler:VJ},{name:"stop",description:"Stop a systemd service",usage:"pkg-ops service stop <name>",handler:TJ},{name:"restart",description:"Restart a systemd service",usage:"pkg-ops service restart <name>",handler:DJ},{name:"status",description:"Get service status",usage:"pkg-ops service status <name>",handler:EJ},{name:"logs",description:"View service logs",usage:"pkg-ops service logs <name> [--lines N]",handler:LJ},{name:"enable",description:"Enable service on boot",usage:"pkg-ops service enable <name>",handler:FJ},{name:"disable",description:"Disable service from boot",usage:"pkg-ops service disable <name>",handler:OJ}],LW=[{name:"show",description:"Show configuration",usage:"pkg-ops config show",handler:jJ},{name:"set",description:"Set a config value",usage:"pkg-ops config set <package> <key> <value>",handler:wJ}];function FW(){console.log(`
|
|
15
16
|
PkgOps - Package operations CLI for VPS
|
|
16
17
|
|
|
17
18
|
Usage:
|
|
@@ -58,7 +59,7 @@ Examples:
|
|
|
58
59
|
pkg-ops sync-status --local-path ./package.json
|
|
59
60
|
pkg-ops verify @ebowwa/stack
|
|
60
61
|
pkg-ops audit
|
|
61
|
-
`)}async function
|
|
62
|
+
`)}async function OW(){let W=process.argv.slice(2);if(W.length===0||W[0]==="--help"||W[0]==="-h")FW(),process.exit(0);if(W[0]==="--version"||W[0]==="-v"){let $=b();console.log(`pkg-ops ${$.packages?.["@ebowwa/pkg-ops"]?.version??"0.1.0"}`),process.exit(0)}let J=W[0],X=W.slice(1);if(J==="service"){if(X.length===0)console.error("Missing service subcommand"),console.error("Usage: pkg-ops service <start|stop|restart|status|logs|enable|disable> <name>"),process.exit(1);let $=X[0],K=EW.find((Q)=>Q.name===$);if(!K)console.error(`Unknown service subcommand: ${$}`),process.exit(1);await K.handler(X.slice(1));return}if(J==="config"){if(X.length===0)console.error("Missing config subcommand"),console.error("Usage: pkg-ops config <show|set> [args...]"),process.exit(1);let $=X[0],K=LW.find((Q)=>Q.name===$);if(!K)console.error(`Unknown config subcommand: ${$}`),process.exit(1);await K.handler(X.slice(1));return}let Z=DW.find(($)=>$.name===J);if(!Z)console.error(`Unknown command: ${J}`),console.error("Run 'pkg-ops --help' for usage"),process.exit(1);await Z.handler(X)}OW().catch((W)=>{console.error("Fatal error:",W),process.exit(1)});
|
|
62
63
|
|
|
63
|
-
//# debugId=
|
|
64
|
+
//# debugId=F69AE2C07BD29FEC64756E2164756E21
|
|
64
65
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../node_modules/@ebowwa/installations/sudo.js", "../src/index.ts", "../src/config.ts", "../node_modules/@ebowwa/installations/systemd.ts", "../src/service-manager.ts", "../src/bridge.ts", "../src/health-server.ts"],
|
|
3
|
+
"sources": ["../node_modules/@ebowwa/installations/sudo.js", "../src/index.ts", "../src/config.ts", "../node_modules/@ebowwa/installations/systemd.ts", "../src/service-manager.ts", "../src/bridge.ts", "../src/health-server.ts", "../src/service-manager.ts", "../src/config.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
5
|
"\"use strict\";\n/**\n * Composable sudo command runner for local and remote (SSH) contexts.\n * Supports arbitrary commands, package installs, file writes, and service management.\n */\nvar __assign = (this && this.__assign) || function () {\n __assign = Object.assign || function(t) {\n for (var s, i = 1, n = arguments.length; i < n; i++) {\n s = arguments[i];\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))\n t[p] = s[p];\n }\n return t;\n };\n return __assign.apply(this, arguments);\n};\nvar __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {\n function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }\n return new (P || (P = Promise))(function (resolve, reject) {\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\n function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }\n step((generator = generator.apply(thisArg, _arguments || [])).next());\n });\n};\nvar __generator = (this && this.__generator) || function (thisArg, body) {\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === \"function\" ? Iterator : Object).prototype);\n return g.next = verb(0), g[\"throw\"] = verb(1), g[\"return\"] = verb(2), typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\n function verb(n) { return function (v) { return step([n, v]); }; }\n function step(op) {\n if (f) throw new TypeError(\"Generator is already executing.\");\n while (g && (g = 0, op[0] && (_ = 0)), _) try {\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\n if (y = 0, t) op = [op[0] & 2, t.value];\n switch (op[0]) {\n case 0: case 1: t = op; break;\n case 4: _.label++; return { value: op[1], done: false };\n case 5: _.label++; y = op[1]; op = [0]; continue;\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\n default:\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\n if (t[2]) _.ops.pop();\n _.trys.pop(); continue;\n }\n op = body.call(thisArg, _);\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\n }\n};\nvar __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {\n if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {\n if (ar || !(i in from)) {\n if (!ar) ar = Array.prototype.slice.call(from, 0, i);\n ar[i] = from[i];\n }\n }\n return to.concat(ar || Array.prototype.slice.call(from));\n};\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.sudo = sudo;\nexports.pkgInstall = pkgInstall;\nexports.writeFile = writeFile;\nexports.service = service;\nexports.serviceEnable = serviceEnable;\nexports.exec = exec;\n// ---------------------------------------------------------------------------\n// Core: run a command with sudo\n// ---------------------------------------------------------------------------\n/** Run an arbitrary command with sudo. */\nfunction sudo(cmd, opts) {\n return __awaiter(this, void 0, void 0, function () {\n var parts, envPrefix, sudoCmd;\n return __generator(this, function (_a) {\n parts = Array.isArray(cmd) ? cmd : cmd.split(/\\s+/);\n envPrefix = opts.env\n ? Object.entries(opts.env).map(function (_a) {\n var k = _a[0], v = _a[1];\n return \"\".concat(k, \"=\").concat(shellEscape(v));\n })\n : [];\n sudoCmd = __spreadArray(__spreadArray([\"sudo\"], envPrefix, true), parts, true);\n return [2 /*return*/, exec(sudoCmd, opts)];\n });\n });\n}\nvar installCmd = {\n apt: [\"apt-get\", \"install\", \"-y\"],\n dnf: [\"dnf\", \"install\", \"-y\"],\n apk: [\"apk\", \"add\", \"--no-cache\"],\n};\nvar updateCmd = {\n apt: [\"apt-get\", \"update\", \"-qq\"],\n dnf: [\"dnf\", \"check-update\"],\n apk: [\"apk\", \"update\"],\n};\n/** Install one or more system packages. */\nfunction pkgInstall(packages, opts) {\n return __awaiter(this, void 0, void 0, function () {\n var pm, envOverride;\n var _a;\n return __generator(this, function (_b) {\n switch (_b.label) {\n case 0:\n pm = (_a = opts.pm) !== null && _a !== void 0 ? _a : \"apt\";\n envOverride = __assign(__assign({}, opts.env), (opts.nonInteractive !== false ? { DEBIAN_FRONTEND: \"noninteractive\" } : {}));\n // Update package index first\n return [4 /*yield*/, sudo(updateCmd[pm], __assign(__assign({}, opts), { env: envOverride, quiet: true }))];\n case 1:\n // Update package index first\n _b.sent();\n return [2 /*return*/, sudo(__spreadArray(__spreadArray([], installCmd[pm], true), packages, true), __assign(__assign({}, opts), { env: envOverride }))];\n }\n });\n });\n}\n/** Write content to a privileged file path using tee. */\nfunction writeFile(path, content, opts) {\n return __awaiter(this, void 0, void 0, function () {\n var op, teeCmd, result;\n return __generator(this, function (_a) {\n switch (_a.label) {\n case 0:\n op = opts.append ? \"-a\" : \"\";\n teeCmd = \"tee \".concat(op, \" \").concat(shellEscape(path)).trim();\n return [4 /*yield*/, execPipe(content, [\"sudo\", teeCmd], opts)];\n case 1:\n result = _a.sent();\n if (!(result.ok && opts.mode)) return [3 /*break*/, 3];\n return [4 /*yield*/, sudo([\"chmod\", opts.mode, path], opts)];\n case 2:\n _a.sent();\n _a.label = 3;\n case 3:\n if (!(result.ok && opts.owner)) return [3 /*break*/, 5];\n return [4 /*yield*/, sudo([\"chown\", opts.owner, path], opts)];\n case 4:\n _a.sent();\n _a.label = 5;\n case 5: return [2 /*return*/, result];\n }\n });\n });\n}\n/** Manage a systemd service. */\nfunction service(name, action, opts) {\n return __awaiter(this, void 0, void 0, function () {\n return __generator(this, function (_a) {\n return [2 /*return*/, sudo([\"systemctl\", action, name], opts)];\n });\n });\n}\n/** Enable and start a service in one call. */\nfunction serviceEnable(name, opts) {\n return __awaiter(this, void 0, void 0, function () {\n return __generator(this, function (_a) {\n return [2 /*return*/, sudo([\"systemctl\", \"enable\", \"--now\", name], opts)];\n });\n });\n}\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\nfunction buildSshPrefix(ctx) {\n var _a;\n var parts = [\"ssh\", \"-F\", \"/dev/null\", \"-o\", \"StrictHostKeyChecking=no\", \"-o\", \"UserKnownHostsFile=/dev/null\"];\n if (ctx.keyPath)\n parts.push(\"-i\", ctx.keyPath);\n else if (ctx.key)\n parts.push(\"-i\", ctx.key);\n if (ctx.port)\n parts.push(\"-p\", String(ctx.port));\n parts.push(\"\".concat((_a = ctx.user) !== null && _a !== void 0 ? _a : \"root\", \"@\").concat(ctx.host));\n return parts;\n}\nfunction exec(args, opts) {\n return __awaiter(this, void 0, void 0, function () {\n var ctx, finalArgs, proc, exitCode, stdout, _a, stderr;\n var _b, _c;\n return __generator(this, function (_d) {\n switch (_d.label) {\n case 0:\n ctx = (_b = opts.context) !== null && _b !== void 0 ? _b : { type: \"local\" };\n finalArgs = ctx.type === \"ssh\"\n ? __spreadArray(__spreadArray([], buildSshPrefix(ctx), true), [args.map(shellEscape).join(\" \")], false) : args;\n proc = Bun.spawn(finalArgs, {\n stdout: \"pipe\",\n stderr: \"pipe\",\n timeout: (_c = opts.timeout) !== null && _c !== void 0 ? _c : 30000,\n });\n return [4 /*yield*/, proc.exited];\n case 1:\n exitCode = _d.sent();\n if (!opts.quiet) return [3 /*break*/, 2];\n _a = \"\";\n return [3 /*break*/, 4];\n case 2: return [4 /*yield*/, new Response(proc.stdout).text()];\n case 3:\n _a = _d.sent();\n _d.label = 4;\n case 4:\n stdout = _a;\n return [4 /*yield*/, new Response(proc.stderr).text()];\n case 5:\n stderr = _d.sent();\n return [2 /*return*/, { stdout: stdout, stderr: stderr, exitCode: exitCode, ok: exitCode === 0 }];\n }\n });\n });\n}\nfunction execPipe(input, args, opts) {\n return __awaiter(this, void 0, void 0, function () {\n var ctx, sshPrefix, remoteCmd, fullArgs, proc_1, exitCode_1, stdout_1, _a, stderr_1, proc, exitCode, stdout, _b, stderr;\n var _c, _d, _e;\n return __generator(this, function (_f) {\n switch (_f.label) {\n case 0:\n ctx = (_c = opts.context) !== null && _c !== void 0 ? _c : { type: \"local\" };\n if (!(ctx.type === \"ssh\")) return [3 /*break*/, 6];\n sshPrefix = buildSshPrefix(ctx);\n remoteCmd = args.join(\" \");\n fullArgs = __spreadArray(__spreadArray([], sshPrefix, true), [remoteCmd], false);\n proc_1 = Bun.spawn(fullArgs, {\n stdin: new TextEncoder().encode(input),\n stdout: \"pipe\",\n stderr: \"pipe\",\n timeout: (_d = opts.timeout) !== null && _d !== void 0 ? _d : 30000,\n });\n return [4 /*yield*/, proc_1.exited];\n case 1:\n exitCode_1 = _f.sent();\n if (!opts.quiet) return [3 /*break*/, 2];\n _a = \"\";\n return [3 /*break*/, 4];\n case 2: return [4 /*yield*/, new Response(proc_1.stdout).text()];\n case 3:\n _a = _f.sent();\n _f.label = 4;\n case 4:\n stdout_1 = _a;\n return [4 /*yield*/, new Response(proc_1.stderr).text()];\n case 5:\n stderr_1 = _f.sent();\n return [2 /*return*/, { stdout: stdout_1, stderr: stderr_1, exitCode: exitCode_1, ok: exitCode_1 === 0 }];\n case 6:\n proc = Bun.spawn([\"sh\", \"-c\", args.join(\" \")], {\n stdin: new TextEncoder().encode(input),\n stdout: \"pipe\",\n stderr: \"pipe\",\n timeout: (_e = opts.timeout) !== null && _e !== void 0 ? _e : 30000,\n });\n return [4 /*yield*/, proc.exited];\n case 7:\n exitCode = _f.sent();\n if (!opts.quiet) return [3 /*break*/, 8];\n _b = \"\";\n return [3 /*break*/, 10];\n case 8: return [4 /*yield*/, new Response(proc.stdout).text()];\n case 9:\n _b = _f.sent();\n _f.label = 10;\n case 10:\n stdout = _b;\n return [4 /*yield*/, new Response(proc.stderr).text()];\n case 11:\n stderr = _f.sent();\n return [2 /*return*/, { stdout: stdout, stderr: stderr, exitCode: exitCode, ok: exitCode === 0 }];\n }\n });\n });\n}\nfunction shellEscape(s) {\n if (/^[a-zA-Z0-9._\\-\\/=:@]+$/.test(s))\n return s;\n return \"'\".concat(s.replace(/'/g, \"'\\\\''\"), \"'\");\n}\n",
|
|
6
|
-
"#!/usr/bin/env node\n/**\n * PkgOps CLI\n *\n * Package operations CLI that installs @ebowwa/* npm packages\n * and manages systemd services.\n *\n * @example\n * ```bash\n * # Install a package\n * pkg-ops install @ebowwa/stack@0.7.12\n *\n * # Service management\n * pkg-ops service start stack\n * pkg-ops service status stack\n *\n * # Health check\n * pkg-ops health\n *\n * # List packages\n * pkg-ops list\n * ```\n */\n\nimport { readFileSync, existsSync } from \"node:fs\";\nimport {\n loadConfig,\n parsePackageSpec,\n isValidPackageName,\n getPackageConfig,\n updatePackageConfig,\n removePackageConfig,\n listManagedPackages,\n} from \"./config.js\";\nimport { ServiceManager, getServiceManager } from \"./service-manager.js\";\nimport { RustBridge, startBridge, stopBridge } from \"./bridge.js\";\nimport { startHealthServer, stopHealthServer, getHealthServer } from \"./health-server.js\";\nimport type { VerifyResult, AuditResult, BundleSize, InstalledPackageInfo } from \"./bridge.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface Command {\n name: string;\n description: string;\n usage: string;\n handler: (args: string[]) => Promise<void> | void;\n}\n\ninterface Subcommand {\n name: string;\n description: string;\n usage: string;\n handler: (args: string[]) => Promise<void> | void;\n}\n\n// ---------------------------------------------------------------------------\n// Package Management Commands\n// ---------------------------------------------------------------------------\n\nasync function handleInstall(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops install <package>[@version]\");\n process.exit(1);\n }\n\n const spec = args[0];\n const { name, version } = parsePackageSpec(spec);\n\n if (!isValidPackageName(name)) {\n console.error(`Invalid package name. Only @ebowwa/* packages are supported.`);\n process.exit(1);\n }\n\n console.log(`Installing ${name}@${version}...`);\n\n try {\n const bridge = await startBridge();\n const result = await bridge.install(name, version);\n\n if (result.success) {\n console.log(`Successfully installed ${name}@${result.version}`);\n if (result.previousVersion) {\n console.log(` Previous version: ${result.previousVersion}`);\n }\n\n // Update config\n updatePackageConfig(name, {\n version: result.version,\n service: name.replace(\"@ebowwa/\", \"\"),\n });\n\n // Start service if configured\n const config = getPackageConfig(name);\n if (config?.service && config.autoStart !== false) {\n const sm = getServiceManager();\n const startResult = await sm.start(config.service);\n if (startResult.success) {\n console.log(` Service ${config.service} started`);\n } else {\n console.warn(` Failed to start service: ${startResult.message}`);\n }\n }\n } else {\n console.error(`Failed to install ${name}: ${result.message}`);\n process.exit(1);\n }\n } catch (error) {\n console.error(`Install failed:`, error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleUpdate(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops update <package>\");\n process.exit(1);\n }\n\n const packageName = args[0];\n\n if (!isValidPackageName(packageName)) {\n console.error(`Invalid package name. Only @ebowwa/* packages are supported.`);\n process.exit(1);\n }\n\n console.log(`Updating ${packageName}...`);\n\n try {\n const bridge = await startBridge();\n const result = await bridge.update(packageName);\n\n if (result.success) {\n console.log(`Successfully updated ${packageName} to ${result.version}`);\n if (result.previousVersion) {\n console.log(` Previous version: ${result.previousVersion}`);\n }\n\n // Update config\n updatePackageConfig(packageName, {\n version: result.version,\n service: packageName.replace(\"@ebowwa/\", \"\"),\n });\n\n // Restart service if running\n const sm = getServiceManager();\n const config = getPackageConfig(packageName);\n if (config?.service) {\n const status = await sm.status(config.service);\n if (status.active) {\n await sm.restart(config.service);\n console.log(` Service ${config.service} restarted`);\n }\n }\n } else {\n console.error(`Failed to update ${packageName}: ${result.message}`);\n process.exit(1);\n }\n } catch (error) {\n console.error(`Update failed:`, error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleUpdateAll(_args: string[]): Promise<void> {\n console.log(\"Updating all managed packages...\");\n\n try {\n const bridge = await startBridge();\n const results = await bridge.updateAll();\n\n for (const result of results) {\n if (result.success) {\n console.log(`Updated ${result.version}`);\n } else {\n console.error(`Failed to update: ${result.message}`);\n }\n }\n } catch (error) {\n console.error(\"Update all failed:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleList(_args: string[]): Promise<void> {\n console.log(\"Installed packages:\\n\");\n\n try {\n const bridge = await startBridge();\n const packages = await bridge.list();\n\n if (packages.length === 0) {\n console.log(\" No packages installed\");\n return;\n }\n\n for (const pkg of packages) {\n const status = pkg.installed ? \"installed\" : \"not installed\";\n const service = pkg.service ? ` (service: ${pkg.service})` : \"\";\n console.log(` ${pkg.name}@${pkg.version} [${status}]${service}`);\n }\n } catch (error) {\n console.error(\"Failed to list packages:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleRollback(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops rollback <package>\");\n process.exit(1);\n }\n\n const packageName = args[0];\n\n console.log(`Rolling back ${packageName}...`);\n\n try {\n const bridge = await startBridge();\n const result = await bridge.rollback(packageName);\n\n if (result.success) {\n console.log(`Rolled back ${packageName} from ${result.currentVersion} to ${result.previousVersion}`);\n\n // Restart service if running\n const sm = getServiceManager();\n const config = getPackageConfig(packageName);\n if (config?.service) {\n const status = await sm.status(config.service);\n if (status.active) {\n await sm.restart(config.service);\n console.log(` Service ${config.service} restarted`);\n }\n }\n } else {\n console.error(`Rollback failed: ${result.message}`);\n process.exit(1);\n }\n } catch (error) {\n console.error(\"Rollback failed:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Service Management Commands\n// ---------------------------------------------------------------------------\n\nasync function handleServiceStart(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service start <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Starting ${serviceName}...`);\n const result = await sm.start(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} started`);\n } else {\n console.error(`Failed to start ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\nasync function handleServiceStop(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service stop <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Stopping ${serviceName}...`);\n const result = await sm.stop(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} stopped`);\n } else {\n console.error(`Failed to stop ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\nasync function handleServiceRestart(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service restart <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Restarting ${serviceName}...`);\n const result = await sm.restart(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} restarted`);\n } else {\n console.error(`Failed to restart ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\nasync function handleServiceStatus(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service status <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n const info = await sm.info(serviceName);\n\n if (!info.exists) {\n console.log(`Service ${serviceName} not found`);\n return;\n }\n\n console.log(`Service: ${serviceName}`);\n console.log(` Loaded: ${info.status.loaded}`);\n console.log(` Active: ${info.status.active}`);\n console.log(` State: ${info.status.subState}`);\n console.log(` PID: ${info.status.mainPid || \"N/A\"}`);\n console.log(` Description: ${info.status.description || \"N/A\"}`);\n}\n\nasync function handleServiceLogs(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service logs <name> [--lines N]\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const linesIndex = args.indexOf(\"--lines\");\n const lines = linesIndex >= 0 && args[linesIndex + 1]\n ? parseInt(args[linesIndex + 1], 10)\n : 100;\n\n const sm = getServiceManager();\n const logs = await sm.logs(serviceName, { lines });\n\n console.log(logs);\n}\n\nasync function handleServiceEnable(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service enable <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Enabling ${serviceName}...`);\n const result = await sm.enable(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} enabled on boot`);\n } else {\n console.error(`Failed to enable ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\nasync function handleServiceDisable(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service disable <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Disabling ${serviceName}...`);\n const result = await sm.disable(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} disabled from boot`);\n } else {\n console.error(`Failed to disable ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Health Commands\n// ---------------------------------------------------------------------------\n\nasync function handleHealth(args: string[]): Promise<void> {\n const serviceName = args[0];\n\n const healthServer = getHealthServer();\n if (!healthServer) {\n console.error(\"Health server not initialized\");\n process.exit(1);\n }\n\n const health = await healthServer.checkHealth(serviceName);\n\n if (!health) {\n console.log(\"Service not found\");\n return;\n }\n\n if (\"services\" in health) {\n // SystemHealth\n if (health.healthy) {\n console.log(\"All services healthy\");\n } else {\n console.log(\"Some services unhealthy\");\n }\n\n for (const service of health.services) {\n const icon = service.healthy ? \"OK\" : \"FAIL\";\n console.log(` [${icon}] ${service.name}: ${service.status.subState}`);\n }\n } else {\n // ServiceHealth\n const icon = health.healthy ? \"OK\" : \"FAIL\";\n console.log(`[${icon}] ${health.name}: ${health.status.subState}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Config Commands\n// ---------------------------------------------------------------------------\n\nasync function handleConfigShow(_args: string[]): Promise<void> {\n const config = loadConfig();\n\n console.log(\"PkgOps Configuration\");\n console.log(`Config path: /etc/pkg-ops/config.json`);\n console.log(`Health port: ${config.healthPort}`);\n console.log(`Work dir: ${config.workDir}`);\n console.log(`Log level: ${config.logLevel}`);\n console.log(\"\\nPackages:\");\n\n const packages = listManagedPackages();\n if (packages.length === 0) {\n console.log(\" No packages configured\");\n return;\n }\n\n for (const { name, config: pkgConfig } of packages) {\n console.log(` ${name}:`);\n console.log(` Version: ${pkgConfig.version}`);\n if (pkgConfig.service) {\n console.log(` Service: ${pkgConfig.service}`);\n }\n if (pkgConfig.autoStart !== undefined) {\n console.log(` Auto-start: ${pkgConfig.autoStart}`);\n }\n }\n}\n\nasync function handleConfigSet(args: string[]): Promise<void> {\n if (args.length < 3) {\n console.error(\"Usage: pkg-ops config set <package> <key> <value>\");\n process.exit(1);\n }\n\n const packageName = args[0];\n const key = args[1];\n const value = args[2];\n\n if (!isValidPackageName(packageName)) {\n console.error(`Invalid package name. Only @ebowwa/* packages are supported.`);\n process.exit(1);\n }\n\n const config = getPackageConfig(packageName) ?? {\n version: \"latest\",\n };\n\n // Handle different value types\n switch (key) {\n case \"version\":\n config.version = value;\n break;\n case \"service\":\n config.service = value;\n break;\n case \"autoStart\":\n config.autoStart = value === \"true\";\n break;\n default:\n console.error(`Unknown config key: ${key}`);\n console.error(\"Valid keys: version, service, autoStart\");\n process.exit(1);\n }\n\n updatePackageConfig(packageName, config);\n console.log(`Updated ${packageName}.${key} = ${value}`);\n}\n\n// ---------------------------------------------------------------------------\n// Verification & Audit Commands\n// ---------------------------------------------------------------------------\n\nasync function handleVerify(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops verify <package>\");\n process.exit(1);\n }\n\n const packageName = args[0];\n\n if (!isValidPackageName(packageName)) {\n console.error(`Invalid package name. Only @ebowwa/* packages are supported.`);\n process.exit(1);\n }\n\n console.log(`Verifying ${packageName}...`);\n\n try {\n const bridge = await startBridge();\n const result = await bridge.verify(packageName);\n\n console.log(`\\nPackage: ${result.packageName}@${result.version}`);\n console.log(` Status: ${result.success ? \"VALID\" : \"INVALID\"}`);\n console.log(` Dist exists: ${result.distExists ? \"Yes\" : \"No\"}`);\n if (result.checksum) {\n console.log(` Checksum: ${result.checksum}`);\n }\n console.log(` Message: ${result.message}`);\n } catch (error) {\n console.error(\"Verification failed:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleSyncStatus(args: string[]): Promise<void> {\n const localIndex = args.indexOf(\"--local\");\n const localPathIndex = args.indexOf(\"--local-path\");\n\n let localPath = \"./package.json\";\n if (localPathIndex >= 0 && args[localPathIndex + 1]) {\n localPath = args[localPathIndex + 1];\n }\n\n const showLocal = localIndex >= 0 || localPathIndex >= 0;\n\n try {\n const bridge = await startBridge();\n const vpsPackages = await bridge.getInstalledInfo();\n\n console.log(\"Sync Status: Local vs VPS\\n\");\n\n if (showLocal && existsSync(localPath)) {\n const localContent = readFileSync(localPath, \"utf-8\");\n const localPkg = JSON.parse(localContent);\n const deps = { ...localPkg.dependencies, ...localPkg.devDependencies };\n\n // Build a map of VPS packages\n const vpsMap = new Map<string, string>();\n for (const pkg of vpsPackages) {\n vpsMap.set(pkg.packageName, pkg.version);\n }\n\n // Compare local vs VPS\n for (const [name, localVersion] of Object.entries(deps)) {\n if (!name.startsWith(\"@ebowwa/\")) continue;\n\n const vpsVersion = vpsMap.get(name);\n const cleanLocal = (localVersion as string).replace(/^[\\^~]/, \"\");\n\n if (vpsVersion) {\n if (cleanLocal === vpsVersion) {\n console.log(` ${name}: local=${cleanLocal}, vps=${vpsVersion} (in sync)`);\n } else if (cleanLocal > vpsVersion) {\n console.log(` ${name}: local=${cleanLocal}, vps=${vpsVersion} (VPS behind)`);\n } else {\n console.log(` ${name}: local=${cleanLocal}, vps=${vpsVersion} (local behind)`);\n }\n vpsMap.delete(name);\n } else {\n console.log(` ${name}: local=${cleanLocal}, vps=not installed`);\n }\n }\n\n // Show VPS-only packages\n for (const [name, version] of vpsMap) {\n console.log(` ${name}: local=not in package.json, vps=${version}`);\n }\n } else {\n // Just show VPS installed versions\n if (vpsPackages.length === 0) {\n console.log(\" No packages installed on VPS\");\n } else {\n for (const pkg of vpsPackages) {\n const sizeInfo = pkg.distSizeBytes\n ? ` (${(pkg.distSizeBytes / 1024).toFixed(1)} KB)`\n : \"\";\n console.log(` ${pkg.packageName}@${pkg.version}${sizeInfo}`);\n }\n }\n }\n } catch (error) {\n console.error(\"Failed to get sync status:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleAudit(_args: string[]): Promise<void> {\n console.log(\"Running vulnerability scan...\\n\");\n\n try {\n const bridge = await startBridge();\n const results = await bridge.audit();\n\n if (results.length === 0) {\n console.log(\"No vulnerabilities found.\");\n return;\n }\n\n console.log(`Found ${results.length} vulnerability(es):\\n`);\n\n for (const vuln of results) {\n console.log(`[${vuln.severity.toUpperCase()}] ${vuln.packageName}`);\n console.log(` Vulnerability: ${vuln.vulnerability}`);\n console.log(` Description: ${vuln.description}`);\n console.log(\"\");\n }\n } catch (error) {\n console.error(\"Audit failed:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleScan(args: string[]): Promise<void> {\n // Alias for audit\n await handleAudit(args);\n}\n\nasync function handleSizes(_args: string[]): Promise<void> {\n console.log(\"Bundle sizes:\\n\");\n\n try {\n const bridge = await startBridge();\n const sizes = await bridge.getBundleSizes();\n\n if (sizes.length === 0) {\n console.log(\" No packages installed\");\n return;\n }\n\n // Print table header\n console.log(\" Package | Version | Dist Size\");\n console.log(\" --------------------------------|----------|-----------\");\n\n for (const pkg of sizes) {\n const name = pkg.packageName.padEnd(32);\n const version = pkg.version.padEnd(9);\n const sizeKB = (pkg.distSizeBytes / 1024).toFixed(1) + \" KB\";\n const files = pkg.fileCount ? ` (${pkg.fileCount} files)` : \"\";\n console.log(` ${name} | ${version} | ${sizeKB}${files}`);\n }\n } catch (error) {\n console.error(\"Failed to get bundle sizes:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\n// ---------------------------------------------------------------------------\n// CLI Entry Point\n// ---------------------------------------------------------------------------\n\nconst commands: Command[] = [\n // Package management\n { name: \"install\", description: \"Install an @ebowwa/* package\", usage: \"pkg-ops install <package>[@version]\", handler: handleInstall },\n { name: \"update\", description: \"Update a package to latest version\", usage: \"pkg-ops update <package>\", handler: handleUpdate },\n { name: \"update-all\", description: \"Update all managed packages\", usage: \"pkg-ops update-all\", handler: handleUpdateAll },\n { name: \"list\", description: \"List installed packages\", usage: \"pkg-ops list\", handler: handleList },\n { name: \"rollback\", description: \"Rollback a package to previous version\", usage: \"pkg-ops rollback <package>\", handler: handleRollback },\n // Service management\n { name: \"start\", description: \"Start a systemd service\", usage: \"pkg-ops service start <name>\", handler: handleServiceStart },\n { name: \"stop\", description: \"Stop a systemd service\", usage: \"pkg-ops service stop <name>\", handler: handleServiceStop },\n { name: \"restart\", description: \"Restart a systemd service\", usage: \"pkg-ops service restart <name>\", handler: handleServiceRestart },\n { name: \"status\", description: \"Get service status\", usage: \"pkg-ops service status <name>\", handler: handleServiceStatus },\n { name: \"logs\", description: \"View service logs\", usage: \"pkg-ops service logs <name> [--lines N]\", handler: handleServiceLogs },\n { name: \"enable\", description: \"Enable service on boot\", usage: \"pkg-ops service enable <name>\", handler: handleServiceEnable },\n { name: \"disable\", description: \"Disable service from boot\", usage: \"pkg-ops service disable <name>\", handler: handleServiceDisable },\n // Health\n { name: \"health\", description: \"Check health of all services\", usage: \"pkg-ops health [service]\", handler: handleHealth },\n // Config\n { name: \"config\", description: \"Show configuration\", usage: \"pkg-ops config show\", handler: handleConfigShow },\n { name: \"set-config\", description: \"Set a config value\", usage: \"pkg-ops config set <package> <key> <value>\", handler: handleConfigSet },\n // Verification & Audit\n { name: \"verify\", description: \"Verify package integrity\", usage: \"pkg-ops verify <package>\", handler: handleVerify },\n { name: \"sync-status\", description: \"Show local vs VPS version sync\", usage: \"pkg-ops sync-status [--local-path path]\", handler: handleSyncStatus },\n { name: \"audit\", description: \"Check for vulnerabilities\", usage: \"pkg-ops audit\", handler: handleAudit },\n { name: \"scan\", description: \"Alias for audit\", usage: \"pkg-ops scan\", handler: handleScan },\n { name: \"sizes\", description: \"Show bundle sizes\", usage: \"pkg-ops sizes\", handler: handleSizes },\n];\n\nconst serviceCommands: Subcommand[] = [\n { name: \"start\", description: \"Start a systemd service\", usage: \"pkg-ops service start <name>\", handler: handleServiceStart },\n { name: \"stop\", description: \"Stop a systemd service\", usage: \"pkg-ops service stop <name>\", handler: handleServiceStop },\n { name: \"restart\", description: \"Restart a systemd service\", usage: \"pkg-ops service restart <name>\", handler: handleServiceRestart },\n { name: \"status\", description: \"Get service status\", usage: \"pkg-ops service status <name>\", handler: handleServiceStatus },\n { name: \"logs\", description: \"View service logs\", usage: \"pkg-ops service logs <name> [--lines N]\", handler: handleServiceLogs },\n { name: \"enable\", description: \"Enable service on boot\", usage: \"pkg-ops service enable <name>\", handler: handleServiceEnable },\n { name: \"disable\", description: \"Disable service from boot\", usage: \"pkg-ops service disable <name>\", handler: handleServiceDisable },\n];\n\nconst configCommands: Subcommand[] = [\n { name: \"show\", description: \"Show configuration\", usage: \"pkg-ops config show\", handler: handleConfigShow },\n { name: \"set\", description: \"Set a config value\", usage: \"pkg-ops config set <package> <key> <value>\", handler: handleConfigSet },\n];\n\nfunction printHelp(): void {\n console.log(`\nPkgOps - Package operations CLI for VPS\n\nUsage:\n pkg-ops <command> [arguments]\n\nPackage Management:\n install <package>[@version] Install an @ebowwa/* package\n update <package> Update a package to latest version\n update-all Update all managed packages\n list List installed packages\n rollback <package> Rollback a package to previous version\n\nService Management:\n service start <name> Start a systemd service\n service stop <name> Stop a systemd service\n service restart <name> Restart a systemd service\n service status <name> Get service status\n service logs <name> [--lines N] View service logs\n service enable <name> Enable service on boot\n service disable <name> Disable service from boot\n\nHealth:\n health [service] Check health of all services or specific one\n\nVerification & Audit:\n verify <package> Verify package integrity\n sync-status [--local-path p] Show local vs VPS version sync\n audit Check for vulnerabilities\n scan Alias for audit\n sizes Show bundle sizes\n\nConfig:\n config show Show configuration\n config set <pkg> <key> <val> Set a config value\n\nOptions:\n --help, -h Show this help message\n --version, -v Show version\n\nExamples:\n pkg-ops install @ebowwa/stack@0.7.12\n pkg-ops service start stack\n pkg-ops health\n pkg-ops sync-status --local-path ./package.json\n pkg-ops verify @ebowwa/stack\n pkg-ops audit\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || args[0] === \"--help\" || args[0] === \"-h\") {\n printHelp();\n process.exit(0);\n }\n\n if (args[0] === \"--version\" || args[0] === \"-v\") {\n const config = loadConfig();\n console.log(`pkg-ops ${config.packages?.[\"@ebowwa/pkg-ops\"]?.version ?? \"0.1.0\"}`);\n process.exit(0);\n }\n\n const commandName = args[0];\n const commandArgs = args.slice(1);\n\n // Handle service subcommands\n if (commandName === \"service\") {\n if (commandArgs.length === 0) {\n console.error(\"Missing service subcommand\");\n console.error(\"Usage: pkg-ops service <start|stop|restart|status|logs|enable|disable> <name>\");\n process.exit(1);\n }\n\n const subcommandName = commandArgs[0];\n const subcommand = serviceCommands.find((c) => c.name === subcommandName);\n\n if (!subcommand) {\n console.error(`Unknown service subcommand: ${subcommandName}`);\n process.exit(1);\n }\n\n await subcommand.handler(commandArgs.slice(1));\n return;\n }\n\n // Handle config subcommands\n if (commandName === \"config\") {\n if (commandArgs.length === 0) {\n console.error(\"Missing config subcommand\");\n console.error(\"Usage: pkg-ops config <show|set> [args...]\");\n process.exit(1);\n }\n\n const subcommandName = commandArgs[0];\n const subcommand = configCommands.find((c) => c.name === subcommandName);\n\n if (!subcommand) {\n console.error(`Unknown config subcommand: ${subcommandName}`);\n process.exit(1);\n }\n\n await subcommand.handler(commandArgs.slice(1));\n return;\n }\n\n // Handle regular commands\n const command = commands.find((c) => c.name === commandName);\n\n if (!command) {\n console.error(`Unknown command: ${commandName}`);\n console.error(\"Run 'pkg-ops --help' for usage\");\n process.exit(1);\n }\n\n await command.handler(commandArgs);\n}\n\n// Run CLI\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});\n",
|
|
6
|
+
"#!/usr/bin/env bun\n/**\n * PkgOps CLI\n *\n * Package operations CLI that installs @ebowwa/* npm packages\n * and manages systemd services.\n *\n * @example\n * ```bash\n * # Install a package\n * pkg-ops install @ebowwa/stack@0.7.12\n *\n * # Service management\n * pkg-ops service start stack\n * pkg-ops service status stack\n *\n * # Health check\n * pkg-ops health\n *\n * # List packages\n * pkg-ops list\n * ```\n */\n\nimport { readFileSync, existsSync } from \"node:fs\";\nimport {\n loadConfig,\n parsePackageSpec,\n isValidPackageName,\n getPackageConfig,\n updatePackageConfig,\n removePackageConfig,\n listManagedPackages,\n} from \"./config.js\";\nimport { ServiceManager, getServiceManager } from \"./service-manager.js\";\nimport { RustBridge, startBridge, stopBridge } from \"./bridge.js\";\nimport { startHealthServer, stopHealthServer, getHealthServer } from \"./health-server.js\";\nimport type { VerifyResult, AuditResult, BundleSize, InstalledPackageInfo } from \"./bridge.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface Command {\n name: string;\n description: string;\n usage: string;\n handler: (args: string[]) => Promise<void> | void;\n}\n\ninterface Subcommand {\n name: string;\n description: string;\n usage: string;\n handler: (args: string[]) => Promise<void> | void;\n}\n\n// ---------------------------------------------------------------------------\n// Package Management Commands\n// ---------------------------------------------------------------------------\n\nasync function handleInstall(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops install <package>[@version]\");\n process.exit(1);\n }\n\n const spec = args[0];\n const { name, version } = parsePackageSpec(spec);\n\n if (!isValidPackageName(name)) {\n console.error(`Invalid package name. Only @ebowwa/* packages are supported.`);\n process.exit(1);\n }\n\n console.log(`Installing ${name}@${version}...`);\n\n try {\n const bridge = await startBridge();\n const result = await bridge.install(name, version);\n\n if (result.success) {\n console.log(`Successfully installed ${name}@${result.version}`);\n if (result.previousVersion) {\n console.log(` Previous version: ${result.previousVersion}`);\n }\n\n // Update config\n updatePackageConfig(name, {\n version: result.version,\n service: name.replace(\"@ebowwa/\", \"\"),\n });\n\n // Start service if configured\n const config = getPackageConfig(name);\n if (config?.service && config.autoStart !== false) {\n const sm = getServiceManager();\n const startResult = await sm.start(config.service);\n if (startResult.success) {\n console.log(` Service ${config.service} started`);\n } else {\n console.warn(` Failed to start service: ${startResult.message}`);\n }\n }\n } else {\n console.error(`Failed to install ${name}: ${result.message}`);\n process.exit(1);\n }\n } catch (error) {\n console.error(`Install failed:`, error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleUpdate(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops update <package>\");\n process.exit(1);\n }\n\n const packageName = args[0];\n\n if (!isValidPackageName(packageName)) {\n console.error(`Invalid package name. Only @ebowwa/* packages are supported.`);\n process.exit(1);\n }\n\n console.log(`Updating ${packageName}...`);\n\n try {\n const bridge = await startBridge();\n const result = await bridge.update(packageName);\n\n if (result.success) {\n console.log(`Successfully updated ${packageName} to ${result.version}`);\n if (result.previousVersion) {\n console.log(` Previous version: ${result.previousVersion}`);\n }\n\n // Update config\n updatePackageConfig(packageName, {\n version: result.version,\n service: packageName.replace(\"@ebowwa/\", \"\"),\n });\n\n // Restart service if running\n const sm = getServiceManager();\n const config = getPackageConfig(packageName);\n if (config?.service) {\n const status = await sm.status(config.service);\n if (status.active) {\n await sm.restart(config.service);\n console.log(` Service ${config.service} restarted`);\n }\n }\n } else {\n console.error(`Failed to update ${packageName}: ${result.message}`);\n process.exit(1);\n }\n } catch (error) {\n console.error(`Update failed:`, error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleUpdateAll(_args: string[]): Promise<void> {\n console.log(\"Updating all managed packages...\");\n\n try {\n const bridge = await startBridge();\n const results = await bridge.updateAll();\n\n for (const result of results) {\n if (result.success) {\n console.log(`Updated ${result.version}`);\n } else {\n console.error(`Failed to update: ${result.message}`);\n }\n }\n } catch (error) {\n console.error(\"Update all failed:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleList(_args: string[]): Promise<void> {\n console.log(\"Installed packages:\\n\");\n\n try {\n const bridge = await startBridge();\n const packages = await bridge.list();\n\n if (packages.length === 0) {\n console.log(\" No packages installed\");\n return;\n }\n\n for (const pkg of packages) {\n const status = pkg.installed ? \"installed\" : \"not installed\";\n const service = pkg.service ? ` (service: ${pkg.service})` : \"\";\n console.log(` ${pkg.name}@${pkg.version} [${status}]${service}`);\n }\n } catch (error) {\n console.error(\"Failed to list packages:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleRollback(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops rollback <package>\");\n process.exit(1);\n }\n\n const packageName = args[0];\n\n console.log(`Rolling back ${packageName}...`);\n\n try {\n const bridge = await startBridge();\n const result = await bridge.rollback(packageName);\n\n if (result.success) {\n console.log(`Rolled back ${packageName} from ${result.currentVersion} to ${result.previousVersion}`);\n\n // Restart service if running\n const sm = getServiceManager();\n const config = getPackageConfig(packageName);\n if (config?.service) {\n const status = await sm.status(config.service);\n if (status.active) {\n await sm.restart(config.service);\n console.log(` Service ${config.service} restarted`);\n }\n }\n } else {\n console.error(`Rollback failed: ${result.message}`);\n process.exit(1);\n }\n } catch (error) {\n console.error(\"Rollback failed:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\n// ---------------------------------------------------------------------------\n// Service Management Commands\n// ---------------------------------------------------------------------------\n\nasync function handleServiceStart(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service start <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Starting ${serviceName}...`);\n const result = await sm.start(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} started`);\n } else {\n console.error(`Failed to start ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\nasync function handleServiceStop(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service stop <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Stopping ${serviceName}...`);\n const result = await sm.stop(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} stopped`);\n } else {\n console.error(`Failed to stop ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\nasync function handleServiceRestart(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service restart <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Restarting ${serviceName}...`);\n const result = await sm.restart(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} restarted`);\n } else {\n console.error(`Failed to restart ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\nasync function handleServiceStatus(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service status <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n const info = await sm.info(serviceName);\n\n if (!info.exists) {\n console.log(`Service ${serviceName} not found`);\n return;\n }\n\n console.log(`Service: ${serviceName}`);\n console.log(` Loaded: ${info.status.loaded}`);\n console.log(` Active: ${info.status.active}`);\n console.log(` State: ${info.status.subState}`);\n console.log(` PID: ${info.status.mainPid || \"N/A\"}`);\n console.log(` Description: ${info.status.description || \"N/A\"}`);\n}\n\nasync function handleServiceLogs(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service logs <name> [--lines N]\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const linesIndex = args.indexOf(\"--lines\");\n const lines = linesIndex >= 0 && args[linesIndex + 1]\n ? parseInt(args[linesIndex + 1], 10)\n : 100;\n\n const sm = getServiceManager();\n const logs = await sm.logs(serviceName, { lines });\n\n console.log(logs);\n}\n\nasync function handleServiceEnable(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service enable <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Enabling ${serviceName}...`);\n const result = await sm.enable(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} enabled on boot`);\n } else {\n console.error(`Failed to enable ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\nasync function handleServiceDisable(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops service disable <name>\");\n process.exit(1);\n }\n\n const serviceName = args[0];\n const sm = getServiceManager();\n\n console.log(`Disabling ${serviceName}...`);\n const result = await sm.disable(serviceName);\n\n if (result.success) {\n console.log(`Service ${serviceName} disabled from boot`);\n } else {\n console.error(`Failed to disable ${serviceName}: ${result.message}`);\n process.exit(1);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Health Commands\n// ---------------------------------------------------------------------------\n\nasync function handleHealth(args: string[]): Promise<void> {\n const serviceName = args[0];\n\n const healthServer = getHealthServer();\n if (!healthServer) {\n console.error(\"Health server not initialized\");\n process.exit(1);\n }\n\n const health = await healthServer.checkHealth(serviceName);\n\n if (!health) {\n console.log(\"Service not found\");\n return;\n }\n\n if (\"services\" in health) {\n // SystemHealth\n if (health.healthy) {\n console.log(\"All services healthy\");\n } else {\n console.log(\"Some services unhealthy\");\n }\n\n for (const service of health.services) {\n const icon = service.healthy ? \"OK\" : \"FAIL\";\n console.log(` [${icon}] ${service.name}: ${service.status.subState}`);\n }\n } else {\n // ServiceHealth\n const icon = health.healthy ? \"OK\" : \"FAIL\";\n console.log(`[${icon}] ${health.name}: ${health.status.subState}`);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Config Commands\n// ---------------------------------------------------------------------------\n\nasync function handleConfigShow(_args: string[]): Promise<void> {\n const config = loadConfig();\n\n console.log(\"PkgOps Configuration\");\n console.log(`Config path: /etc/pkg-ops/config.json`);\n console.log(`Health port: ${config.healthPort}`);\n console.log(`Work dir: ${config.workDir}`);\n console.log(`Log level: ${config.logLevel}`);\n console.log(\"\\nPackages:\");\n\n const packages = listManagedPackages();\n if (packages.length === 0) {\n console.log(\" No packages configured\");\n return;\n }\n\n for (const { name, config: pkgConfig } of packages) {\n console.log(` ${name}:`);\n console.log(` Version: ${pkgConfig.version}`);\n if (pkgConfig.service) {\n console.log(` Service: ${pkgConfig.service}`);\n }\n if (pkgConfig.autoStart !== undefined) {\n console.log(` Auto-start: ${pkgConfig.autoStart}`);\n }\n }\n}\n\nasync function handleConfigSet(args: string[]): Promise<void> {\n if (args.length < 3) {\n console.error(\"Usage: pkg-ops config set <package> <key> <value>\");\n process.exit(1);\n }\n\n const packageName = args[0];\n const key = args[1];\n const value = args[2];\n\n if (!isValidPackageName(packageName)) {\n console.error(`Invalid package name. Only @ebowwa/* packages are supported.`);\n process.exit(1);\n }\n\n const config = getPackageConfig(packageName) ?? {\n version: \"latest\",\n };\n\n // Handle different value types\n switch (key) {\n case \"version\":\n config.version = value;\n break;\n case \"service\":\n config.service = value;\n break;\n case \"autoStart\":\n config.autoStart = value === \"true\";\n break;\n default:\n console.error(`Unknown config key: ${key}`);\n console.error(\"Valid keys: version, service, autoStart\");\n process.exit(1);\n }\n\n updatePackageConfig(packageName, config);\n console.log(`Updated ${packageName}.${key} = ${value}`);\n}\n\n// ---------------------------------------------------------------------------\n// Verification & Audit Commands\n// ---------------------------------------------------------------------------\n\nasync function handleVerify(args: string[]): Promise<void> {\n if (args.length === 0) {\n console.error(\"Usage: pkg-ops verify <package>\");\n process.exit(1);\n }\n\n const packageName = args[0];\n\n if (!isValidPackageName(packageName)) {\n console.error(`Invalid package name. Only @ebowwa/* packages are supported.`);\n process.exit(1);\n }\n\n console.log(`Verifying ${packageName}...`);\n\n try {\n const bridge = await startBridge();\n const result = await bridge.verify(packageName);\n\n console.log(`\\nPackage: ${result.packageName}@${result.version}`);\n console.log(` Status: ${result.success ? \"VALID\" : \"INVALID\"}`);\n console.log(` Dist exists: ${result.distExists ? \"Yes\" : \"No\"}`);\n if (result.checksum) {\n console.log(` Checksum: ${result.checksum}`);\n }\n console.log(` Message: ${result.message}`);\n } catch (error) {\n console.error(\"Verification failed:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleSyncStatus(args: string[]): Promise<void> {\n const localIndex = args.indexOf(\"--local\");\n const localPathIndex = args.indexOf(\"--local-path\");\n\n let localPath = \"./package.json\";\n if (localPathIndex >= 0 && args[localPathIndex + 1]) {\n localPath = args[localPathIndex + 1];\n }\n\n const showLocal = localIndex >= 0 || localPathIndex >= 0;\n\n try {\n const bridge = await startBridge();\n const vpsPackages = await bridge.getInstalledInfo();\n\n console.log(\"Sync Status: Local vs VPS\\n\");\n\n if (showLocal && existsSync(localPath)) {\n const localContent = readFileSync(localPath, \"utf-8\");\n const localPkg = JSON.parse(localContent);\n const deps = { ...localPkg.dependencies, ...localPkg.devDependencies };\n\n // Build a map of VPS packages\n const vpsMap = new Map<string, string>();\n for (const pkg of vpsPackages) {\n vpsMap.set(pkg.packageName, pkg.version);\n }\n\n // Compare local vs VPS\n for (const [name, localVersion] of Object.entries(deps)) {\n if (!name.startsWith(\"@ebowwa/\")) continue;\n\n const vpsVersion = vpsMap.get(name);\n const cleanLocal = (localVersion as string).replace(/^[\\^~]/, \"\");\n\n if (vpsVersion) {\n if (cleanLocal === vpsVersion) {\n console.log(` ${name}: local=${cleanLocal}, vps=${vpsVersion} (in sync)`);\n } else if (cleanLocal > vpsVersion) {\n console.log(` ${name}: local=${cleanLocal}, vps=${vpsVersion} (VPS behind)`);\n } else {\n console.log(` ${name}: local=${cleanLocal}, vps=${vpsVersion} (local behind)`);\n }\n vpsMap.delete(name);\n } else {\n console.log(` ${name}: local=${cleanLocal}, vps=not installed`);\n }\n }\n\n // Show VPS-only packages\n for (const [name, version] of vpsMap) {\n console.log(` ${name}: local=not in package.json, vps=${version}`);\n }\n } else {\n // Just show VPS installed versions\n if (vpsPackages.length === 0) {\n console.log(\" No packages installed on VPS\");\n } else {\n for (const pkg of vpsPackages) {\n const sizeInfo = pkg.distSizeBytes\n ? ` (${(pkg.distSizeBytes / 1024).toFixed(1)} KB)`\n : \"\";\n console.log(` ${pkg.packageName}@${pkg.version}${sizeInfo}`);\n }\n }\n }\n } catch (error) {\n console.error(\"Failed to get sync status:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleAudit(_args: string[]): Promise<void> {\n console.log(\"Running vulnerability scan...\\n\");\n\n try {\n const bridge = await startBridge();\n const results = await bridge.audit();\n\n if (results.length === 0) {\n console.log(\"No vulnerabilities found.\");\n return;\n }\n\n console.log(`Found ${results.length} vulnerability(es):\\n`);\n\n for (const vuln of results) {\n console.log(`[${vuln.severity.toUpperCase()}] ${vuln.packageName}`);\n console.log(` Vulnerability: ${vuln.vulnerability}`);\n console.log(` Description: ${vuln.description}`);\n console.log(\"\");\n }\n } catch (error) {\n console.error(\"Audit failed:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\nasync function handleScan(args: string[]): Promise<void> {\n // Alias for audit\n await handleAudit(args);\n}\n\nasync function handleSizes(_args: string[]): Promise<void> {\n console.log(\"Bundle sizes:\\n\");\n\n try {\n const bridge = await startBridge();\n const sizes = await bridge.getBundleSizes();\n\n if (sizes.length === 0) {\n console.log(\" No packages installed\");\n return;\n }\n\n // Print table header\n console.log(\" Package | Version | Dist Size\");\n console.log(\" --------------------------------|----------|-----------\");\n\n for (const pkg of sizes) {\n const name = pkg.packageName.padEnd(32);\n const version = pkg.version.padEnd(9);\n const sizeKB = (pkg.distSizeBytes / 1024).toFixed(1) + \" KB\";\n const files = pkg.fileCount ? ` (${pkg.fileCount} files)` : \"\";\n console.log(` ${name} | ${version} | ${sizeKB}${files}`);\n }\n } catch (error) {\n console.error(\"Failed to get bundle sizes:\", error);\n process.exit(1);\n } finally {\n await stopBridge();\n }\n}\n\n// ---------------------------------------------------------------------------\n// CLI Entry Point\n// ---------------------------------------------------------------------------\n\nconst commands: Command[] = [\n // Package management\n { name: \"install\", description: \"Install an @ebowwa/* package\", usage: \"pkg-ops install <package>[@version]\", handler: handleInstall },\n { name: \"update\", description: \"Update a package to latest version\", usage: \"pkg-ops update <package>\", handler: handleUpdate },\n { name: \"update-all\", description: \"Update all managed packages\", usage: \"pkg-ops update-all\", handler: handleUpdateAll },\n { name: \"list\", description: \"List installed packages\", usage: \"pkg-ops list\", handler: handleList },\n { name: \"rollback\", description: \"Rollback a package to previous version\", usage: \"pkg-ops rollback <package>\", handler: handleRollback },\n // Service management\n { name: \"start\", description: \"Start a systemd service\", usage: \"pkg-ops service start <name>\", handler: handleServiceStart },\n { name: \"stop\", description: \"Stop a systemd service\", usage: \"pkg-ops service stop <name>\", handler: handleServiceStop },\n { name: \"restart\", description: \"Restart a systemd service\", usage: \"pkg-ops service restart <name>\", handler: handleServiceRestart },\n { name: \"status\", description: \"Get service status\", usage: \"pkg-ops service status <name>\", handler: handleServiceStatus },\n { name: \"logs\", description: \"View service logs\", usage: \"pkg-ops service logs <name> [--lines N]\", handler: handleServiceLogs },\n { name: \"enable\", description: \"Enable service on boot\", usage: \"pkg-ops service enable <name>\", handler: handleServiceEnable },\n { name: \"disable\", description: \"Disable service from boot\", usage: \"pkg-ops service disable <name>\", handler: handleServiceDisable },\n // Health\n { name: \"health\", description: \"Check health of all services\", usage: \"pkg-ops health [service]\", handler: handleHealth },\n // Config\n { name: \"config\", description: \"Show configuration\", usage: \"pkg-ops config show\", handler: handleConfigShow },\n { name: \"set-config\", description: \"Set a config value\", usage: \"pkg-ops config set <package> <key> <value>\", handler: handleConfigSet },\n // Verification & Audit\n { name: \"verify\", description: \"Verify package integrity\", usage: \"pkg-ops verify <package>\", handler: handleVerify },\n { name: \"sync-status\", description: \"Show local vs VPS version sync\", usage: \"pkg-ops sync-status [--local-path path]\", handler: handleSyncStatus },\n { name: \"audit\", description: \"Check for vulnerabilities\", usage: \"pkg-ops audit\", handler: handleAudit },\n { name: \"scan\", description: \"Alias for audit\", usage: \"pkg-ops scan\", handler: handleScan },\n { name: \"sizes\", description: \"Show bundle sizes\", usage: \"pkg-ops sizes\", handler: handleSizes },\n];\n\nconst serviceCommands: Subcommand[] = [\n { name: \"start\", description: \"Start a systemd service\", usage: \"pkg-ops service start <name>\", handler: handleServiceStart },\n { name: \"stop\", description: \"Stop a systemd service\", usage: \"pkg-ops service stop <name>\", handler: handleServiceStop },\n { name: \"restart\", description: \"Restart a systemd service\", usage: \"pkg-ops service restart <name>\", handler: handleServiceRestart },\n { name: \"status\", description: \"Get service status\", usage: \"pkg-ops service status <name>\", handler: handleServiceStatus },\n { name: \"logs\", description: \"View service logs\", usage: \"pkg-ops service logs <name> [--lines N]\", handler: handleServiceLogs },\n { name: \"enable\", description: \"Enable service on boot\", usage: \"pkg-ops service enable <name>\", handler: handleServiceEnable },\n { name: \"disable\", description: \"Disable service from boot\", usage: \"pkg-ops service disable <name>\", handler: handleServiceDisable },\n];\n\nconst configCommands: Subcommand[] = [\n { name: \"show\", description: \"Show configuration\", usage: \"pkg-ops config show\", handler: handleConfigShow },\n { name: \"set\", description: \"Set a config value\", usage: \"pkg-ops config set <package> <key> <value>\", handler: handleConfigSet },\n];\n\nfunction printHelp(): void {\n console.log(`\nPkgOps - Package operations CLI for VPS\n\nUsage:\n pkg-ops <command> [arguments]\n\nPackage Management:\n install <package>[@version] Install an @ebowwa/* package\n update <package> Update a package to latest version\n update-all Update all managed packages\n list List installed packages\n rollback <package> Rollback a package to previous version\n\nService Management:\n service start <name> Start a systemd service\n service stop <name> Stop a systemd service\n service restart <name> Restart a systemd service\n service status <name> Get service status\n service logs <name> [--lines N] View service logs\n service enable <name> Enable service on boot\n service disable <name> Disable service from boot\n\nHealth:\n health [service] Check health of all services or specific one\n\nVerification & Audit:\n verify <package> Verify package integrity\n sync-status [--local-path p] Show local vs VPS version sync\n audit Check for vulnerabilities\n scan Alias for audit\n sizes Show bundle sizes\n\nConfig:\n config show Show configuration\n config set <pkg> <key> <val> Set a config value\n\nOptions:\n --help, -h Show this help message\n --version, -v Show version\n\nExamples:\n pkg-ops install @ebowwa/stack@0.7.12\n pkg-ops service start stack\n pkg-ops health\n pkg-ops sync-status --local-path ./package.json\n pkg-ops verify @ebowwa/stack\n pkg-ops audit\n`);\n}\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2);\n\n if (args.length === 0 || args[0] === \"--help\" || args[0] === \"-h\") {\n printHelp();\n process.exit(0);\n }\n\n if (args[0] === \"--version\" || args[0] === \"-v\") {\n const config = loadConfig();\n console.log(`pkg-ops ${config.packages?.[\"@ebowwa/pkg-ops\"]?.version ?? \"0.1.0\"}`);\n process.exit(0);\n }\n\n const commandName = args[0];\n const commandArgs = args.slice(1);\n\n // Handle service subcommands\n if (commandName === \"service\") {\n if (commandArgs.length === 0) {\n console.error(\"Missing service subcommand\");\n console.error(\"Usage: pkg-ops service <start|stop|restart|status|logs|enable|disable> <name>\");\n process.exit(1);\n }\n\n const subcommandName = commandArgs[0];\n const subcommand = serviceCommands.find((c) => c.name === subcommandName);\n\n if (!subcommand) {\n console.error(`Unknown service subcommand: ${subcommandName}`);\n process.exit(1);\n }\n\n await subcommand.handler(commandArgs.slice(1));\n return;\n }\n\n // Handle config subcommands\n if (commandName === \"config\") {\n if (commandArgs.length === 0) {\n console.error(\"Missing config subcommand\");\n console.error(\"Usage: pkg-ops config <show|set> [args...]\");\n process.exit(1);\n }\n\n const subcommandName = commandArgs[0];\n const subcommand = configCommands.find((c) => c.name === subcommandName);\n\n if (!subcommand) {\n console.error(`Unknown config subcommand: ${subcommandName}`);\n process.exit(1);\n }\n\n await subcommand.handler(commandArgs.slice(1));\n return;\n }\n\n // Handle regular commands\n const command = commands.find((c) => c.name === commandName);\n\n if (!command) {\n console.error(`Unknown command: ${commandName}`);\n console.error(\"Run 'pkg-ops --help' for usage\");\n process.exit(1);\n }\n\n await command.handler(commandArgs);\n}\n\n// Run CLI\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});\n",
|
|
7
7
|
"/**\n * Configuration management for PkgOps.\n *\n * Handles reading/writing config file at /etc/pkg-ops/config.json\n *\n * @example\n * ```typescript\n * import { loadConfig, saveConfig, getConfigPath } from \"@ebowwa/pkg-ops/config\";\n *\n * const config = await loadConfig();\n * console.log(config.packages);\n *\n * config.packages[\"@ebowwa/stack\"] = { version: \"0.7.13\", service: \"stack.service\" };\n * await saveConfig(config);\n * ```\n */\n\nimport { accessSync, constants, mkdirSync, readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PackageConfig {\n /** Package version (semver or \"latest\") */\n version: string;\n /** Associated systemd service name (without .service suffix) */\n service?: string;\n /** Whether to auto-start the service after install */\n autoStart?: boolean;\n /** Custom environment variables for the service */\n environment?: Record<string, string>;\n}\n\nexport interface PkgOpsConfig {\n /** Managed packages */\n packages: Record<string, PackageConfig>;\n /** Health check HTTP port (default: 8914) */\n healthPort?: number;\n /** Working directory for installations (default: /root) */\n workDir?: string;\n /** Log level (default: \"info\") */\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nexport const DEFAULT_CONFIG: PkgOpsConfig = {\n packages: {},\n healthPort: 8914,\n workDir: \"/root\",\n logLevel: \"info\",\n};\n\nexport const CONFIG_DIR = \"/etc/pkg-ops\";\nexport const CONFIG_PATH = `${CONFIG_DIR}/config.json`;\n\n// ---------------------------------------------------------------------------\n// Functions\n// ---------------------------------------------------------------------------\n\n/**\n * Get the config file path.\n * Respects PKG_OPS_CONFIG env override.\n */\nexport function getConfigPath(): string {\n return process.env.PKG_OPS_CONFIG ?? CONFIG_PATH;\n}\n\n/**\n * Ensure config directory exists (requires sudo on most systems).\n */\nexport function ensureConfigDir(): void {\n const configDir = dirname(getConfigPath());\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true, mode: constants.S_IRWXU | constants.S_IRGRP | constants.S_IXGRP });\n }\n}\n\n/**\n * Load configuration from file.\n * Returns default config if file doesn't exist.\n */\nexport function loadConfig(): PkgOpsConfig {\n const configPath = getConfigPath();\n\n try {\n if (!existsSync(configPath)) {\n return { ...DEFAULT_CONFIG };\n }\n\n const content = readFileSync(configPath, \"utf-8\");\n const parsed = JSON.parse(content);\n\n // Merge with defaults\n return {\n ...DEFAULT_CONFIG,\n ...parsed,\n };\n } catch (error) {\n console.error(`Failed to load config from ${configPath}:`, error);\n return { ...DEFAULT_CONFIG };\n }\n}\n\n/**\n * Save configuration to file.\n * Creates directory if it doesn't exist.\n */\nexport function saveConfig(config: PkgOpsConfig): void {\n const configPath = getConfigPath();\n ensureConfigDir();\n\n const content = JSON.stringify(config, null, 2);\n writeFileSync(configPath, content, {\n encoding: \"utf-8\",\n mode: constants.S_IRUSR | constants.S_IWUSR | constants.S_IRGRP,\n });\n}\n\n/**\n * Update a package in the config.\n */\nexport function updatePackageConfig(\n packageName: string,\n packageConfig: PackageConfig\n): PkgOpsConfig {\n const config = loadConfig();\n config.packages[packageName] = packageConfig;\n saveConfig(config);\n return config;\n}\n\n/**\n * Remove a package from the config.\n */\nexport function removePackageConfig(packageName: string): PkgOpsConfig {\n const config = loadConfig();\n delete config.packages[packageName];\n saveConfig(config);\n return config;\n}\n\n/**\n * Get a specific package config.\n */\nexport function getPackageConfig(packageName: string): PackageConfig | undefined {\n const config = loadConfig();\n return config.packages[packageName];\n}\n\n/**\n * List all managed packages.\n */\nexport function listManagedPackages(): Array<{ name: string; config: PackageConfig }> {\n const config = loadConfig();\n return Object.entries(config.packages).map(([name, cfg]) => ({ name, config: cfg }));\n}\n\n/**\n * Validate package name (must be @ebowwa/* scope).\n */\nexport function isValidPackageName(name: string): boolean {\n return name.startsWith(\"@ebowwa/\");\n}\n\n/**\n * Parse package specifier into name and version.\n * @example\n * parsePackageSpec(\"@ebowwa/stack@0.7.12\") => { name: \"@ebowwa/stack\", version: \"0.7.12\" }\n * parsePackageSpec(\"@ebowwa/stack\") => { name: \"@ebowwa/stack\", version: \"latest\" }\n */\nexport function parsePackageSpec(spec: string): { name: string; version: string } {\n const atIndex = spec.lastIndexOf(\"@\");\n if (atIndex <= 0) {\n // No version specified or scoped package without version\n return { name: spec, version: \"latest\" };\n }\n\n const name = spec.slice(0, atIndex);\n const version = spec.slice(atIndex + 1);\n\n if (!version) {\n return { name, version: \"latest\" };\n }\n\n return { name, version };\n}\n",
|
|
8
8
|
"/**\n * Systemd service unit creation and management with security hardening.\n *\n * @example Creating a secure web service\n * ```typescript\n * import { createServiceUnit, SECURITY_PRESETS, enableAndStartService } from \"@ebowwa/seedinstallation/systemd\";\n *\n * const webService = await createServiceUnit(\"my-api\", {\n * description: \"My API Service\",\n * workingDirectory: \"/opt/my-api\",\n * execStart: \"/usr/bin/node /opt/my-api/index.js\",\n * user: \"api-user\",\n * ...SECURITY_PRESETS.network,\n * readWritePaths: [\"/var/log/my-api\", \"/var/lib/my-api\"],\n * environment: {\n * NODE_ENV: \"production\",\n * PORT: \"8911\",\n * },\n * context: sudoContext,\n * });\n *\n * await enableAndStartService(\"my-api\", { context: sudoContext });\n * ```\n *\n * @example Creating a service with custom security\n * ```typescript\n * const customService = await createServiceUnit(\"custom-agent\", {\n * description: \"Custom Agent\",\n * workingDirectory: \"/opt/agent\",\n * execStart: \"/usr/bin/node /opt/agent/index.js\",\n * user: \"agent\",\n * // Apply strict security but relax some options\n * ...SECURITY_PRESETS.strict,\n * // Allow specific directory for agent data\n * readWritePaths: [\"/var/lib/agent\", \"/var/log/agent\"],\n * // Allow network communication\n * restrictAddressFamilies: [\"AF_UNIX\", \"AF_INET\", \"AF_INET6\"],\n * // Allow binding to privileged ports\n * capabilityBoundingSet: [\"CAP_NET_BIND_SERVICE\"],\n * ambientCapabilities: [\"CAP_NET_BIND_SERVICE\"],\n * context: sudoContext,\n * });\n * ```\n *\n * @example Creating a development service with minimal security\n * ```typescript\n * const devService = await createServiceUnit(\"dev-service\", {\n * description: \"Development Service\",\n * workingDirectory: \"/home/dev/project\",\n * execStart: \"npm run dev\",\n * user: \"dev\",\n * ...SECURITY_PRESETS.minimal,\n * // Allow full home directory access for development\n * readWritePaths: [\"/home/dev\"],\n * context: sudoContext,\n * });\n * ```\n *\n * Works with both local and SSH contexts via ExecContext from sudo.ts.\n */\n\nimport type { ExecContext, SudoOptions, ExecResult, WriteFileOptions } from \"./sudo\";\n\n// Re-export helpers\nasync function exec(args: string[], opts: SudoOptions): Promise<ExecResult> {\n const { sudo } = await import(\"./sudo\");\n return sudo(args, opts);\n}\n\nasync function writeFile(path: string, content: string, opts: SudoOptions): Promise<ExecResult> {\n const { writeFile: wf } = await import(\"./sudo\");\n return wf(path, content, opts);\n}\n\n// ---------------------------------------------------------------------------\n// Systemd Detection\n// ---------------------------------------------------------------------------\n\n/**\n * Result of systemd availability check\n */\nexport interface SystemdCheckResult {\n /** Whether systemd is available on this system */\n available: boolean;\n /** Reason why systemd is not available (undefined if available) */\n reason?: \"not_found\" | \"not_running\" | \"no_permission\" | \"unknown\";\n /** Human-readable message */\n message: string;\n}\n\n/**\n * Cache for systemd detection result\n */\nlet systemdCheckCache: SystemdCheckResult | null = null;\n\n/**\n * Check if systemd is available on the system.\n *\n * Detection methods (tried in order):\n * 1. Check if systemctl command exists\n * 2. Check if /run/systemd/system directory exists\n * 3. Try running systemctl --version\n *\n * Results are cached after first call.\n *\n * @param opts - Optional execution context (defaults to local if not provided)\n *\n * @example Skip systemd operations on non-systemd systems\n * ```typescript\n * import { hasSystemd, createServiceUnit } from \"@ebowwa/seedinstallation/systemd\";\n *\n * if (!(await hasSystemd()).available) {\n * console.log(\"Running in container/without systemd - skipping service creation\");\n * // Run process directly instead\n * } else {\n * await createServiceUnit(\"my-service\", { ... });\n * }\n * ```\n */\nexport async function hasSystemd(opts?: SudoOptions): Promise<SystemdCheckResult> {\n // Return cached result if available\n if (systemdCheckCache) {\n return systemdCheckCache;\n }\n\n // Default to local context if not provided\n const sudoOpts = opts ?? { context: { type: \"local\" as const } };\n\n // Method 1: Check for systemctl in PATH\n const whichResult = await exec([\"which\", \"systemctl\"], {\n ...sudoOpts,\n env: sudoOpts.env,\n });\n\n if (!whichResult.ok || !whichResult.stdout.trim()) {\n const result: SystemdCheckResult = {\n available: false,\n reason: \"not_found\",\n message: \"systemctl command not found - systemd is not installed or not in PATH\",\n };\n systemdCheckCache = result;\n return result;\n }\n\n // Method 2: Check if systemd is actually running\n const runningResult = await exec([\"systemctl\", \"is-system-running\"], {\n ...sudoOpts,\n env: sudoOpts.env,\n });\n\n if (runningResult.ok && runningResult.stdout.trim() !== \"\") {\n // systemd is running\n const result: SystemdCheckResult = {\n available: true,\n message: \"systemd is available and running\",\n };\n systemdCheckCache = result;\n return result;\n }\n\n // Method 3: Fallback - check for systemd directory\n const dirResult = await exec([\"test\", \"-d\", \"/run/systemd/system\"], {\n ...sudoOpts,\n env: sudoOpts.env,\n });\n\n if (dirResult.ok) {\n // systemd directory exists but systemctl might not work (container env)\n const result: SystemdCheckResult = {\n available: true,\n message: \"systemd detected via /run/systemd/system (container environment)\",\n };\n systemdCheckCache = result;\n return result;\n }\n\n // No systemd found\n const result: SystemdCheckResult = {\n available: false,\n reason: \"not_running\",\n message: \"systemd is not available on this system (container/initless environment)\",\n };\n systemdCheckCache = result;\n return result;\n}\n\n/**\n * Clear the systemd detection cache.\n * Useful for testing or when system state may have changed.\n */\nexport function clearSystemdCache(): void {\n systemdCheckCache = null;\n}\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ServiceUnitOptions {\n /** Service description */\n description: string;\n /** Services to start before this one */\n after?: string[];\n /** Services that this one wants */\n wants?: string[];\n /** Service type (default: \"simple\") */\n type?: \"simple\" | \"oneshot\" | \"exec\" | \"forking\" | \"notify\" | \"idle\";\n /** User to run as (default: \"root\") */\n user?: string;\n /** Group to run as */\n group?: string;\n /** Working directory */\n workingDirectory: string;\n /** Command to execute */\n execStart: string;\n /** Command to execute before start (oneshot type) */\n execStartPre?: string[];\n /** Command to execute after stop */\n execStopPost?: string[];\n /** Restart policy (default: \"always\") */\n restart?: \"no\" | \"always\" | \"on-success\" | \"on-failure\" | \"on-abnormal\" | \"on-abort\" | \"on-watchdog\";\n /** Seconds to wait before restart */\n restartSec?: number;\n /** Environment variables */\n environment?: Record<string, string>;\n /** Environment file to load */\n environmentFile?: string;\n /** Standard output mode (default: \"journal\") */\n standardOutput?: \"journal\" | \"syslog\" | \"null\" | \"append:path\";\n /** Standard error mode */\n standardError?: \"journal\" | \"syslog\" | \"null\" | \"inherit\";\n /** Nice level (-20 to 19) */\n nice?: number;\n /** Additional unit file sections (e.g. [Install], [Unit] extras) */\n extras?: string;\n\n // ---------------------------------------------------------------------------\n // Security Hardening Options (systemd 235+)\n // ---------------------------------------------------------------------------\n\n /** Prevent the process and its children from gaining new privileges via execve */\n noNewPrivileges?: boolean;\n /** Mount /tmp and /var/tmp as private, empty directories */\n privateTmp?: boolean;\n /** Make the file system hierarchy read-only (strict = full read-only except /var, /etc, /home) */\n protectSystem?: \"strict\" | \"full\" | \"yes\";\n /** Mount /home and /root read-only or as tmpfs (true = read-only) */\n protectHome?: boolean | \"read-only\" | \"tmpfs\";\n /** Paths that should be mounted read-only (default: all paths except readWritePaths) */\n readOnlyPaths?: string[];\n /** Paths that should be writable (whitelist approach for security) */\n readWritePaths?: string[];\n /** Restrict real-time scheduling access */\n restrictRealtime?: boolean;\n /** Deny writing to memory/execute permissions (prevents JIT compilation, W^X) */\n memoryDenyWriteExecute?: boolean;\n /** Make kernel tunables (sysctl, /proc/sys, /sys) read-only */\n protectKernelTunables?: boolean;\n /** Prevent kernel module loading/unloading */\n protectKernelModules?: boolean;\n /** Prevent access to cgroups filesystem */\n protectControlGroups?: boolean;\n /** Restrict address families (e.g., [\"AF_UNIX\", \"AF_INET\", \"AF_INET6\"]) */\n restrictAddressFamilies?: string[];\n /** Create device node whitelist (empty = no device access) */\n deviceAllow?: string[];\n /** Make device nodes read-only */\n devicePolicy?: \"auto\" | \"closed\" | \"strict\";\n /** Restrict system call access (systemd 241+) */\n systemCallFilter?: string[];\n /** Restrict filesystem namespaces */\n restrictNamespaces?: boolean | string[];\n /** Set personality (e.g., \"x86-64\") */\n personality?: string;\n /** Lock personality with syscalls */\n lockPersonality?: boolean;\n /** Remove CAP_SYS_* capabilities */\n removeCapability?: string[];\n /** Bounding set to drop capabilities */\n capabilityBoundingSet?: string[];\n /** Ambient capabilities to keep */\n ambientCapabilities?: string[];\n /** Private devices namespace (/dev whitelist) */\n privateDevices?: boolean;\n /** Mount /usr read-only */\n protectKernelLogs?: boolean;\n}\n\nexport interface ServiceResult extends ExecResult {\n /** Path to the unit file */\n unitPath?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Service creation\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a systemd unit file content from options.\n */\nexport function generateServiceUnit(\n name: string,\n opts: ServiceUnitOptions\n): string {\n const lines: string[] = [];\n\n // [Unit] section\n lines.push(\"[Unit]\");\n lines.push(`Description=${opts.description}`);\n if (opts.after?.length) {\n lines.push(`After=${opts.after.join(\" \")}`);\n }\n if (opts.wants?.length) {\n lines.push(`Wants=${opts.wants.join(\" \")}`);\n }\n lines.push(\"\");\n\n // [Service] section\n lines.push(\"[Service]\");\n if (opts.type) lines.push(`Type=${opts.type}`);\n lines.push(`User=${opts.user ?? \"root\"}`);\n if (opts.group) lines.push(`Group=${opts.group}`);\n lines.push(`WorkingDirectory=${opts.workingDirectory}`);\n lines.push(`ExecStart=${opts.execStart}`);\n\n if (opts.execStartPre?.length) {\n opts.execStartPre.forEach((cmd, i) => {\n lines.push(`ExecStartPre${i > 0 ? `=${i}` : \"\"}=${cmd}`);\n });\n }\n\n if (opts.execStopPost?.length) {\n opts.execStopPost.forEach((cmd, i) => {\n lines.push(`ExecStopPost${i > 0 ? `=${i}` : \"\"}=${cmd}`);\n });\n }\n\n if (opts.restart) lines.push(`Restart=${opts.restart}`);\n if (opts.restartSec) lines.push(`RestartSec=${opts.restartSec}`);\n\n if (opts.environment) {\n Object.entries(opts.environment).forEach(([k, v]) => {\n lines.push(`Environment=\"${k}=${v}\"`);\n });\n }\n\n if (opts.environmentFile) {\n lines.push(`EnvironmentFile=${opts.environmentFile}`);\n }\n\n if (opts.standardOutput) lines.push(`StandardOutput=${opts.standardOutput}`);\n if (opts.standardError) lines.push(`StandardError=${opts.standardError}`);\n if (opts.nice !== undefined) lines.push(`Nice=${opts.nice}`);\n\n // Security hardening options\n if (opts.noNewPrivileges) lines.push(\"NoNewPrivileges=true\");\n if (opts.privateTmp) lines.push(\"PrivateTmp=true\");\n if (opts.protectSystem) lines.push(`ProtectSystem=${opts.protectSystem}`);\n if (opts.protectHome === true) lines.push(\"ProtectHome=true\");\n else if (opts.protectHome) lines.push(`ProtectHome=${opts.protectHome}`);\n if (opts.readOnlyPaths?.length) lines.push(`ReadOnlyPaths=${opts.readOnlyPaths.join(\" \")}`);\n if (opts.readWritePaths?.length) lines.push(`ReadWritePaths=${opts.readWritePaths.join(\" \")}`);\n if (opts.restrictRealtime) lines.push(\"RestrictRealtime=true\");\n if (opts.memoryDenyWriteExecute) lines.push(\"MemoryDenyWriteExecute=true\");\n if (opts.protectKernelTunables) lines.push(\"ProtectKernelTunables=true\");\n if (opts.protectKernelModules) lines.push(\"ProtectKernelModules=true\");\n if (opts.protectControlGroups) lines.push(\"ProtectControlGroups=true\");\n if (opts.restrictAddressFamilies?.length) lines.push(`RestrictAddressFamilies=${opts.restrictAddressFamilies.join(\" \")}`);\n if (opts.deviceAllow?.length) lines.push(`DeviceAllow=${opts.deviceAllow.join(\" \")}`);\n if (opts.devicePolicy) lines.push(`DevicePolicy=${opts.devicePolicy}`);\n if (opts.systemCallFilter?.length) lines.push(`SystemCallFilter=${opts.systemCallFilter.join(\" \")}`);\n if (opts.restrictNamespaces === true) lines.push(\"RestrictNamespaces=true\");\n else if (Array.isArray(opts.restrictNamespaces) && opts.restrictNamespaces.length > 0) lines.push(`RestrictNamespaces=${opts.restrictNamespaces.join(\" \")}`);\n if (opts.personality) lines.push(`Personality=${opts.personality}`);\n if (opts.lockPersonality) lines.push(\"LockPersonality=true\");\n if (opts.removeCapability?.length) opts.removeCapability.forEach(cap => lines.push(`RemoveCapability=${cap}`));\n if (opts.capabilityBoundingSet?.length) lines.push(`CapabilityBoundingSet=${opts.capabilityBoundingSet.join(\" \")}`);\n if (opts.ambientCapabilities?.length) lines.push(`AmbientCapabilities=${opts.ambientCapabilities.join(\" \")}`);\n if (opts.privateDevices) lines.push(\"PrivateDevices=true\");\n if (opts.protectKernelLogs) lines.push(\"ProtectKernelLogs=true\");\n\n // Extras\n if (opts.extras) {\n lines.push(\"\");\n lines.push(opts.extras);\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Create and install a systemd service unit file.\n */\nexport async function createServiceUnit(\n name: string,\n opts: ServiceUnitOptions & SudoOptions\n): Promise<ServiceResult> {\n const unitPath = `/etc/systemd/system/${name}.service`;\n const content = generateServiceUnit(name, opts);\n\n // Write unit file\n const writeResult = await writeFile(unitPath, content, {\n context: opts.context,\n mode: \"644\",\n env: opts.env,\n timeout: opts.timeout,\n } as WriteFileOptions);\n\n if (!writeResult.ok) {\n return writeResult;\n }\n\n // Reload systemd\n await exec([\"systemctl\", \"daemon-reload\"], opts);\n\n return {\n ...writeResult,\n unitPath,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Service control\n// ---------------------------------------------------------------------------\n\n/**\n * Enable a service to start on boot.\n */\nexport async function enableService(\n name: string,\n opts: SudoOptions\n): Promise<ExecResult> {\n return exec([\"systemctl\", \"enable\", name], opts);\n}\n\n/**\n * Disable a service from starting on boot.\n */\nexport async function disableService(\n name: string,\n opts: SudoOptions\n): Promise<ExecResult> {\n return exec([\"systemctl\", \"disable\", name], opts);\n}\n\n/**\n * Start a service.\n */\nexport async function startService(\n name: string,\n opts: SudoOptions\n): Promise<ExecResult> {\n return exec([\"systemctl\", \"start\", name], opts);\n}\n\n/**\n * Stop a service.\n */\nexport async function stopService(\n name: string,\n opts: SudoOptions\n): Promise<ExecResult> {\n return exec([\"systemctl\", \"stop\", name], opts);\n}\n\n/**\n * Restart a service.\n */\nexport async function restartService(\n name: string,\n opts: SudoOptions\n): Promise<ExecResult> {\n return exec([\"systemctl\", \"restart\", name], opts);\n}\n\n/**\n * Reload a service (sends SIGHUP).\n */\nexport async function reloadService(\n name: string,\n opts: SudoOptions\n): Promise<ExecResult> {\n return exec([\"systemctl\", \"reload\", name], opts);\n}\n\n/**\n * Get service status.\n */\nexport async function getServiceStatus(\n name: string,\n opts: SudoOptions\n): Promise<ServiceStatus> {\n const result = await exec([\"systemctl\", \"show\", name, \"--property=LoadState,ActiveState,SubState,MainPID,Description\"], {\n ...opts,\n });\n\n if (!result.ok) {\n return { loaded: false, active: false, subState: \"unknown\", mainPid: 0, description: \"\" };\n }\n\n const parse = (key: string): string => {\n const match = result.stdout.match(new RegExp(`^${key}=(.+)$`, \"m\"));\n return match?.[1]?.trim() ?? \"\";\n };\n\n return {\n loaded: parse(\"LoadState\") === \"loaded\",\n active: parse(\"ActiveState\") === \"active\",\n subState: parse(\"SubState\"),\n mainPid: parseInt(parse(\"MainPID\") || \"0\", 10),\n description: parse(\"Description\"),\n };\n}\n\nexport interface ServiceStatus {\n /** Whether the unit file is loaded */\n loaded: boolean;\n /** Whether the service is active (running) */\n active: boolean;\n /** Sub-state (running, exited, failed, etc.) */\n subState: string;\n /** Main process PID */\n mainPid: number;\n /** Service description */\n description: string;\n}\n\n/**\n * Enable and start a service in one call.\n */\nexport async function enableAndStartService(\n name: string,\n opts: SudoOptions\n): Promise<ExecResult> {\n return exec([\"systemctl\", \"enable\", \"--now\", name], opts);\n}\n\n/**\n * Check if a service exists.\n */\nexport async function serviceExists(\n name: string,\n opts: SudoOptions\n): Promise<boolean> {\n const result = await exec([\"systemctl\", \"list-unit-files\", name + \".service\"], {\n ...opts,\n quiet: true,\n });\n return result.ok && result.stdout.includes(name);\n}\n\n/**\n * Get service logs via journalctl.\n */\nexport async function getServiceLogs(\n name: string,\n opts: SudoOptions & {\n /** Number of lines to show (default: 100) */\n lines?: number;\n /** Follow logs */\n follow?: boolean;\n /** Show logs since timestamp */\n since?: string;\n } = {}\n): Promise<string> {\n const args = [\"journalctl\", \"-u\", name, \"-n\", String(opts.lines ?? 100)];\n if (opts.since) args.push(\"--since\", opts.since);\n if (!opts.follow) args.push(\"-n\", String(opts.lines ?? 100));\n\n const result = await exec(args, opts);\n return result.stdout;\n}\n\n// ---------------------------------------------------------------------------\n// Security Presets\n// ---------------------------------------------------------------------------\n\n/**\n * Security hardening presets for systemd services.\n * Apply these using spread syntax: { ...SECURITY_PRESETS.strict, ...customOptions }\n */\nexport const SECURITY_PRESETS: Record<string, Partial<ServiceUnitOptions>> = {\n /**\n * Maximum security for critical services.\n * Enables all available hardening options.\n */\n strict: {\n noNewPrivileges: true,\n privateTmp: true,\n protectSystem: \"strict\",\n protectHome: true,\n readOnlyPaths: [\"/\"],\n readWritePaths: [],\n restrictRealtime: true,\n memoryDenyWriteExecute: true,\n protectKernelTunables: true,\n protectKernelModules: true,\n protectControlGroups: true,\n restrictAddressFamilies: [\"AF_UNIX\", \"AF_INET\", \"AF_INET6\"],\n devicePolicy: \"closed\",\n deviceAllow: [],\n restrictNamespaces: true,\n privateDevices: true,\n protectKernelLogs: true,\n lockPersonality: true,\n capabilityBoundingSet: [],\n },\n\n /**\n * Balanced security for typical network services.\n * Allows network operations and basic file I/O.\n */\n standard: {\n noNewPrivileges: true,\n privateTmp: true,\n protectSystem: \"full\",\n protectHome: true,\n restrictRealtime: true,\n memoryDenyWriteExecute: true,\n protectKernelTunables: true,\n protectKernelModules: true,\n protectControlGroups: true,\n restrictAddressFamilies: [\"AF_UNIX\", \"AF_INET\", \"AF_INET6\"],\n devicePolicy: \"auto\",\n restrictNamespaces: true,\n privateDevices: true,\n capabilityBoundingSet: [\"CAP_NET_BIND_SERVICE\"],\n },\n\n /**\n * Preset for network-facing services (APIs, web servers, etc).\n * Allows network operations with sensible restrictions.\n */\n network: {\n noNewPrivileges: true,\n privateTmp: true,\n protectSystem: \"full\",\n protectHome: true,\n restrictRealtime: true,\n protectKernelTunables: true,\n protectKernelModules: true,\n protectControlGroups: true,\n restrictAddressFamilies: [\"AF_UNIX\", \"AF_INET\", \"AF_INET6\"],\n devicePolicy: \"auto\",\n privateDevices: true,\n capabilityBoundingSet: [\"CAP_NET_BIND_SERVICE\"],\n ambientCapabilities: [\"CAP_NET_BIND_SERVICE\"],\n },\n\n /**\n * Basic security for development/testing environments.\n * Minimal restrictions to allow debugging.\n */\n minimal: {\n noNewPrivileges: true,\n privateTmp: true,\n protectSystem: \"yes\",\n restrictRealtime: true,\n },\n\n /**\n * Preset for services that need device access (e.g., hardware agents).\n */\n deviceAccess: {\n noNewPrivileges: true,\n privateTmp: true,\n protectSystem: \"full\",\n protectHome: true,\n restrictRealtime: true,\n memoryDenyWriteExecute: true,\n protectKernelTunables: true,\n protectKernelModules: true,\n protectControlGroups: true,\n devicePolicy: \"auto\",\n restrictNamespaces: true,\n privateDevices: false,\n },\n};\n\n/**\n * Helper to merge security preset with custom options.\n * Custom options override preset values.\n */\nexport function withSecurityPreset(\n preset: keyof typeof SECURITY_PRESETS,\n customOptions: ServiceUnitOptions\n): ServiceUnitOptions {\n return {\n ...SECURITY_PRESETS[preset],\n ...customOptions,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Safe Systemd Operations (with automatic detection)\n// ---------------------------------------------------------------------------\n\n/**\n * Options for safe systemd operations\n */\nexport interface SafeSystemdOptions {\n /** Whether to throw error if systemd is not available (default: true) */\n requireSystemd?: boolean;\n /** Callback to run when systemd is not available */\n onNoSystemd?: (check: SystemdCheckResult) => void | Promise<void>;\n /** Execution context (defaults to local if not provided) */\n context?: SudoOptions[\"context\"];\n /** Environment variables */\n env?: Record<string, string>;\n /** Timeout in ms */\n timeout?: number;\n /** Suppress output */\n quiet?: boolean;\n}\n\n/**\n * Safely execute a systemd operation with automatic detection.\n *\n * If systemd is not available, either:\n * - Throws an error (if requireSystemd = true, default)\n * - Calls onNoSystemd callback (if provided)\n * - Returns undefined gracefully\n *\n * @example\n * ```typescript\n * import { safeSystemd, createServiceUnit } from \"@ebowwa/seedinstallation/systemd\";\n *\n * // Will throw if no systemd\n * await safeSystemd(async () => {\n * await createServiceUnit(\"my-service\", { ... });\n * });\n *\n * // Will skip gracefully if no systemd\n * await safeSystemd(\n * async () => {\n * await createServiceUnit(\"my-service\", { ... });\n * },\n * {\n * requireSystemd: false,\n * onNoSystemd: async (check) => {\n * console.log(`No systemd: ${check.message}`);\n * // Run process directly instead\n * },\n * }\n * );\n * ```\n */\nexport async function safeSystemd<T>(\n operation: () => Promise<T>,\n options: SafeSystemdOptions = {}\n): Promise<T | undefined> {\n const { requireSystemd = true, onNoSystemd, context, env, timeout, quiet } = options;\n\n // Build SudoOptions for hasSystemd, defaulting to local context\n const sudoOpts: SudoOptions = context\n ? { context, env, timeout, quiet }\n : { context: { type: \"local\" as const }, env, timeout, quiet };\n\n const check = await hasSystemd(sudoOpts);\n\n if (!check.available) {\n if (onNoSystemd) {\n await onNoSystemd(check);\n }\n\n if (requireSystemd) {\n throw new Error(`Systemd required but not available: ${check.message}`);\n }\n\n return undefined;\n }\n\n // systemd is available, execute operation\n return operation();\n}\n\n",
|
|
9
9
|
"/**\n * Service management using @ebowwa/installations.\n *\n * Wraps systemd operations for package operations.\n *\n * @example\n * ```typescript\n * import { ServiceManager } from \"@ebowwa/pkg-ops/service-manager\";\n *\n * const manager = new ServiceManager();\n *\n * // Start a service\n * await manager.start(\"stack\");\n *\n * // Check status\n * const status = await manager.status(\"stack\");\n * console.log(status.active ? \"Running\" : \"Stopped\");\n *\n * // View logs\n * const logs = await manager.logs(\"stack\", { lines: 50 });\n * ```\n */\n\nimport {\n startService,\n stopService,\n restartService,\n getServiceStatus,\n enableService,\n disableService,\n serviceExists,\n getServiceLogs,\n type ServiceStatus,\n} from \"@ebowwa/installations/systemd\";\n\nimport type { SudoOptions } from \"@ebowwa/installations\";\n\n// Re-export ServiceStatus for other modules\nexport type { ServiceStatus } from \"@ebowwa/installations/systemd\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ServiceInfo {\n /** Service name (without .service suffix) */\n name: string;\n /** Whether the service exists */\n exists: boolean;\n /** Service status */\n status: ServiceStatus;\n /** Associated package (if known) */\n package?: string;\n}\n\nexport interface ServiceLogsOptions {\n /** Number of lines to show (default: 100) */\n lines?: number;\n /** Show logs since timestamp */\n since?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Service Manager Class\n// ---------------------------------------------------------------------------\n\n/**\n * Manages systemd services for packages.\n */\nexport class ServiceManager {\n private sudoOptions: SudoOptions;\n\n constructor(sudoOptions?: SudoOptions) {\n this.sudoOptions = sudoOptions ?? { context: { type: \"local\" } };\n }\n\n /**\n * Start a service.\n */\n async start(name: string): Promise<{ success: boolean; message: string }> {\n const result = await startService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} started` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Stop a service.\n */\n async stop(name: string): Promise<{ success: boolean; message: string }> {\n const result = await stopService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} stopped` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Restart a service.\n */\n async restart(name: string): Promise<{ success: boolean; message: string }> {\n const result = await restartService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} restarted` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Get service status.\n */\n async status(name: string): Promise<ServiceStatus> {\n return getServiceStatus(name, this.sudoOptions);\n }\n\n /**\n * Enable a service to start on boot.\n */\n async enable(name: string): Promise<{ success: boolean; message: string }> {\n const result = await enableService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} enabled` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Disable a service from starting on boot.\n */\n async disable(name: string): Promise<{ success: boolean; message: string }> {\n const result = await disableService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} disabled` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Check if a service exists.\n */\n async exists(name: string): Promise<boolean> {\n return serviceExists(name, this.sudoOptions);\n }\n\n /**\n * Get service logs.\n */\n async logs(name: string, options?: ServiceLogsOptions): Promise<string> {\n return getServiceLogs(name, {\n ...this.sudoOptions,\n lines: options?.lines ?? 100,\n since: options?.since,\n });\n }\n\n /**\n * Get comprehensive service info.\n */\n async info(name: string): Promise<ServiceInfo> {\n const [existsResult, statusResult] = await Promise.all([\n this.exists(name),\n this.status(name),\n ]);\n\n return {\n name,\n exists: existsResult,\n status: statusResult,\n };\n }\n\n /**\n * Check if a service is healthy (running and active).\n */\n async isHealthy(name: string): Promise<boolean> {\n const status = await this.status(name);\n return status.active && status.subState === \"running\";\n }\n\n /**\n * Wait for a service to become healthy.\n */\n async waitForHealthy(\n name: string,\n options?: { timeout?: number; interval?: number }\n ): Promise<boolean> {\n const timeout = options?.timeout ?? 30000;\n const interval = options?.interval ?? 1000;\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n const healthy = await this.isHealthy(name);\n if (healthy) return true;\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton Instance\n// ---------------------------------------------------------------------------\n\nlet defaultManager: ServiceManager | null = null;\n\n/**\n * Get the default service manager instance.\n */\nexport function getServiceManager(): ServiceManager {\n if (!defaultManager) {\n defaultManager = new ServiceManager();\n }\n return defaultManager;\n}\n",
|
|
10
10
|
"/**\n * Bridge to Rust worker for package operations.\n *\n * Communicates with the Rust core via JSON-RPC 2.0 over stdin/stdout.\n *\n * @example\n * ```typescript\n * import { RustBridge } from \"@ebowwa/pkg-ops/bridge\";\n *\n * const bridge = new RustBridge();\n * await bridge.start();\n *\n * // Install a package\n * const result = await bridge.install(\"@ebowwa/stack\", \"0.7.12\");\n * console.log(result);\n *\n * // List packages\n * const packages = await bridge.list();\n *\n * await bridge.stop();\n * ```\n */\n\nimport { spawn, type ChildProcess } from \"child_process\";\nimport { accessSync, constants as fsConstants } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface InstallResult {\n success: boolean;\n version: string;\n previousVersion?: string;\n message: string;\n}\n\nexport interface PackageInfo {\n name: string;\n version: string;\n installed: boolean;\n service?: string;\n}\n\nexport interface RollbackResult {\n success: boolean;\n previousVersion: string;\n currentVersion: string;\n message: string;\n}\n\nexport interface HealthCheckResult {\n healthy: boolean;\n services: Array<{\n name: string;\n status: string;\n pid: number;\n }>;\n}\n\nexport interface VerifyResult {\n packageName: string;\n version: string;\n success: boolean;\n distExists: boolean;\n checksum: string | null;\n message: string;\n}\n\nexport interface AuditResult {\n packageName: string;\n severity: string;\n vulnerability: string;\n description: string;\n}\n\nexport interface BundleSize {\n packageName: string;\n version: string;\n distSizeBytes: number;\n fileCount: number;\n}\n\nexport interface InstalledPackageInfo {\n packageName: string;\n version: string;\n distSizeBytes: number | null;\n installedAt: string | null;\n}\n\ninterface JsonRpcRequest {\n jsonrpc: \"2.0\";\n id: string;\n method: string;\n params?: Record<string, unknown>;\n}\n\ninterface JsonRpcResponse {\n jsonrpc: \"2.0\";\n id: string;\n result?: unknown;\n error?: {\n code: number;\n message: string;\n data?: unknown;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst REQUEST_TIMEOUT = 30000;\n\n// ---------------------------------------------------------------------------\n// Rust Bridge Class\n// ---------------------------------------------------------------------------\n\n/**\n * Bridge to the Rust worker process.\n *\n * Handles JSON-RPC communication over stdin/stdout.\n */\nexport class RustBridge {\n private process: ChildProcess | null = null;\n private pendingRequests = new Map<string, {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n timeout: ReturnType<typeof setTimeout>;\n }>();\n private requestId = 0;\n private buffer = \"\";\n\n /**\n * Start the Rust worker process.\n */\n async start(): Promise<void> {\n if (this.process) {\n return;\n }\n\n const binaryPath = this.getBinaryPath();\n\n // Check if binary exists\n try {\n accessSync(binaryPath, fsConstants.X_OK);\n } catch {\n throw new Error(\n `Rust binary not found at ${binaryPath}. ` +\n `Run 'bun run build:rust' in the pkg-ops package.`\n );\n }\n\n this.process = spawn(binaryPath, [], {\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n\n if (!this.process.stdin || !this.process.stdout) {\n throw new Error(\"Failed to create stdin/stdout pipes\");\n }\n\n // Handle stdout (JSON-RPC responses)\n this.process.stdout.on(\"data\", (data: Buffer) => {\n this.buffer += data.toString(\"utf-8\");\n this.processBuffer();\n });\n\n // Handle stderr (logs)\n this.process.stderr?.on(\"data\", (data: Buffer) => {\n console.error(\"[rust-worker]\", data.toString(\"utf-8\").trim());\n });\n\n // Handle process exit\n this.process.on(\"exit\", (code: number | null) => {\n console.error(`Rust worker exited with code ${code}`);\n this.process = null;\n });\n }\n\n /**\n * Stop the Rust worker process.\n */\n async stop(): Promise<void> {\n if (!this.process) {\n return;\n }\n\n // Send shutdown request\n try {\n await this.sendRequest(\"shutdown\", {});\n } catch {\n // Ignore errors on shutdown\n }\n\n // Give it time to shutdown gracefully\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n // Force kill if still running\n if (this.process) {\n this.process.kill(\"SIGTERM\");\n this.process = null;\n }\n\n // Clear pending requests\n for (const [id, pending] of this.pendingRequests) {\n clearTimeout(pending.timeout);\n pending.reject(new Error(\"Bridge shutdown\"));\n }\n this.pendingRequests.clear();\n }\n\n /**\n * Install a package.\n */\n async install(packageName: string, version: string): Promise<InstallResult> {\n return this.sendRequest(\"install\", { packageName, version }) as Promise<InstallResult>;\n }\n\n /**\n * Update a package to latest version.\n */\n async update(packageName: string): Promise<InstallResult> {\n return this.sendRequest(\"update\", { packageName }) as Promise<InstallResult>;\n }\n\n /**\n * Update all managed packages.\n */\n async updateAll(): Promise<InstallResult[]> {\n return this.sendRequest(\"updateAll\", {}) as Promise<InstallResult[]>;\n }\n\n /**\n * List installed packages.\n */\n async list(): Promise<PackageInfo[]> {\n return this.sendRequest(\"list\", {}) as Promise<PackageInfo[]>;\n }\n\n /**\n * Rollback a package to previous version.\n */\n async rollback(packageName: string): Promise<RollbackResult> {\n return this.sendRequest(\"rollback\", { packageName }) as Promise<RollbackResult>;\n }\n\n /**\n * Check health of all services.\n */\n async health(): Promise<HealthCheckResult> {\n return this.sendRequest(\"health\", {}) as Promise<HealthCheckResult>;\n }\n\n /**\n * Verify package integrity.\n */\n async verify(packageName: string): Promise<VerifyResult> {\n return this.sendRequest(\"verify\", { packageName }) as Promise<VerifyResult>;\n }\n\n /**\n * Run vulnerability scan.\n */\n async audit(): Promise<AuditResult[]> {\n return this.sendRequest(\"audit\", {}) as Promise<AuditResult[]>;\n }\n\n /**\n * Get bundle sizes.\n */\n async getBundleSizes(): Promise<BundleSize[]> {\n return this.sendRequest(\"sizes\", {}) as Promise<BundleSize[]>;\n }\n\n /**\n * Get detailed installed package info.\n */\n async getInstalledInfo(): Promise<InstalledPackageInfo[]> {\n return this.sendRequest(\"installedInfo\", {}) as Promise<InstalledPackageInfo[]>;\n }\n\n // ---------------------------------------------------------------------------\n // Private Methods\n // ---------------------------------------------------------------------------\n\n private getBinaryPath(): string {\n // Get the directory of this module\n const currentDir = dirname(fileURLToPath(import.meta.url));\n\n // Paths to check (in order of preference)\n const paths = [\n // Cargo build output (works on VPS after `cargo build --release`)\n join(currentDir, \"..\", \"rust\", \"target\", \"release\", \"pkg-ops-core\"),\n // Pre-built binary in rust folder (for npm package distribution)\n join(currentDir, \"..\", \"rust\", \"pkg-ops-core\"),\n // Linux-specific cargo output\n join(currentDir, \"..\", \"rust\", \"target\", \"x86_64-unknown-linux-gnu\", \"release\", \"pkg-ops-core\"),\n ];\n\n for (const path of paths) {\n try {\n accessSync(path, fsConstants.X_OK);\n return path;\n } catch {\n // Try next path\n }\n }\n\n // Return the most likely path for error message\n throw new Error(\n `Rust binary not found. Tried:\\n${paths.map(p => ` - ${p}`).join(\"\\n\")}\\n` +\n `Run 'bun run build:rust' or 'cargo build --release' in the pkg-ops package.`\n );\n }\n\n private sendRequest<T>(method: string, params: Record<string, unknown>): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.process?.stdin) {\n reject(new Error(\"Rust worker not started\"));\n return;\n }\n\n const id = String(++this.requestId);\n const request: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n id,\n method,\n params,\n };\n\n // Set up timeout\n const timeout = setTimeout(() => {\n this.pendingRequests.delete(id);\n reject(new Error(`Request timeout: ${method}`));\n }, REQUEST_TIMEOUT);\n\n // Store pending request\n this.pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timeout,\n });\n\n // Send request\n const json = JSON.stringify(request) + \"\\n\";\n this.process.stdin.write(json, \"utf-8\", (err: Error | null | undefined) => {\n if (err) {\n this.pendingRequests.delete(id);\n clearTimeout(timeout);\n reject(err);\n }\n });\n });\n }\n\n private processBuffer(): void {\n const lines = this.buffer.split(\"\\n\");\n this.buffer = lines.pop() ?? \"\";\n\n for (const line of lines) {\n if (!line.trim()) continue;\n\n try {\n const response: JsonRpcResponse = JSON.parse(line);\n const pending = this.pendingRequests.get(response.id);\n\n if (pending) {\n clearTimeout(pending.timeout);\n this.pendingRequests.delete(response.id);\n\n if (response.error) {\n pending.reject(new Error(response.error.message));\n } else {\n pending.resolve(response.result);\n }\n }\n } catch (err) {\n console.error(\"Failed to parse response:\", line, err);\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton Instance\n// ---------------------------------------------------------------------------\n\nlet defaultBridge: RustBridge | null = null;\n\n/**\n * Get the default bridge instance.\n */\nexport function getBridge(): RustBridge {\n if (!defaultBridge) {\n defaultBridge = new RustBridge();\n }\n return defaultBridge;\n}\n\n/**\n * Start the default bridge.\n */\nexport async function startBridge(): Promise<RustBridge> {\n const bridge = getBridge();\n await bridge.start();\n return bridge;\n}\n\n/**\n * Stop the default bridge.\n */\nexport async function stopBridge(): Promise<void> {\n if (defaultBridge) {\n await defaultBridge.stop();\n defaultBridge = null;\n }\n}\n",
|
|
11
|
-
"/**\n * Health monitoring HTTP server.\n *\n * Provides an HTTP endpoint for health checks on port 8914 (configurable).\n *\n * @example\n * ```typescript\n * import { HealthServer, startHealthServer } from \"@ebowwa/pkg-ops/health-server\";\n *\n * // Start health server\n * const server = await startHealthServer(8914);\n *\n * // Custom health checks\n * server.addCheck(\"custom\", async () => ({\n * healthy: true,\n * message: \"Custom check passed\",\n * }));\n *\n * // Stop server\n * await server.stop();\n * ```\n */\n\nimport { createServer, type Server as HttpServer, type IncomingMessage, type ServerResponse } from \"http\";\nimport { getServiceManager, type ServiceStatus } from \"./service-manager.js\";\nimport { loadConfig, type PkgOpsConfig } from \"./config.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface HealthCheckResult {\n /** Whether the check passed */\n healthy: boolean;\n /** Human-readable message */\n message: string;\n /** Additional data */\n data?: Record<string, unknown>;\n}\n\nexport interface ServiceHealth {\n /** Service name */\n name: string;\n /** Whether the service is healthy */\n healthy: boolean;\n /** Service status */\n status: ServiceStatus;\n /** Last check timestamp */\n checkedAt: string;\n}\n\nexport interface SystemHealth {\n /** Overall health status */\n healthy: boolean;\n /** All services health */\n services: ServiceHealth[];\n /** System uptime in seconds */\n uptime: number;\n /** Timestamp of this check */\n timestamp: string;\n}\n\nexport type HealthCheckFn = () => Promise<HealthCheckResult> | HealthCheckResult;\n\n// ---------------------------------------------------------------------------\n// Health Server Class\n// ---------------------------------------------------------------------------\n\n/**\n * HTTP server for health monitoring.\n */\nexport class HealthServer {\n private server: HttpServer | null = null;\n private checks = new Map<string, HealthCheckFn>();\n private startTime = Date.now();\n private port: number;\n\n constructor(port: number = 8914) {\n this.port = port;\n }\n\n /**\n * Start the health server.\n */\n async start(): Promise<void> {\n if (this.server) {\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.server = createServer((req, res) => this.handleRequest(req, res));\n\n this.server.on(\"error\", reject);\n\n this.server.listen(this.port, () => {\n console.log(`Health server listening on port ${this.port}`);\n this.server?.off(\"error\", reject);\n resolve();\n });\n });\n }\n\n /**\n * Stop the health server.\n */\n async stop(): Promise<void> {\n if (!this.server) {\n return;\n }\n\n return new Promise((resolve) => {\n this.server?.close(() => {\n this.server = null;\n resolve();\n });\n });\n }\n\n /**\n * Add a custom health check.\n */\n addCheck(name: string, check: HealthCheckFn): void {\n this.checks.set(name, check);\n }\n\n /**\n * Remove a health check.\n */\n removeCheck(name: string): void {\n this.checks.delete(name);\n }\n\n /**\n * Check health of all services or a specific service.\n * Public method for CLI usage.\n */\n async checkHealth(serviceName?: string): Promise<SystemHealth | ServiceHealth | null> {\n if (serviceName) {\n return this.getServiceHealth(serviceName);\n }\n return this.getSystemHealth();\n }\n\n // ---------------------------------------------------------------------------\n // Private Methods\n // ---------------------------------------------------------------------------\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = req.url ?? \"/\";\n const method = req.method ?? \"GET\";\n\n try {\n if (method === \"GET\" && url === \"/health\") {\n const health = await this.getSystemHealth();\n this.sendJson(res, 200, health);\n } else if (method === \"GET\" && url.startsWith(\"/health/\")) {\n const serviceName = url.slice(8).replace(\".service\", \"\");\n const health = await this.getServiceHealth(serviceName);\n this.sendJson(res, health ? 200 : 404, health ?? { error: \"Service not found\" });\n } else if (method === \"GET\" && url === \"/ready\") {\n const health = await this.getSystemHealth();\n this.sendJson(res, health.healthy ? 200 : 503, { ready: health.healthy });\n } else if (method === \"GET\" && url === \"/live\") {\n this.sendJson(res, 200, { alive: true });\n } else {\n this.sendJson(res, 404, { error: \"Not found\" });\n }\n } catch (error) {\n console.error(\"Health check error:\", error);\n this.sendJson(res, 500, { error: \"Internal server error\" });\n }\n }\n\n private async getSystemHealth(): Promise<SystemHealth> {\n const config = loadConfig();\n const serviceManager = getServiceManager();\n\n const services: ServiceHealth[] = [];\n\n for (const [packageName, pkgConfig] of Object.entries(config.packages)) {\n if (!pkgConfig.service) continue;\n\n const status = await serviceManager.status(pkgConfig.service);\n const healthy = status.active && status.subState === \"running\";\n\n services.push({\n name: pkgConfig.service,\n healthy,\n status,\n checkedAt: new Date().toISOString(),\n });\n }\n\n // Run custom checks\n const customResults: Record<string, HealthCheckResult> = {};\n for (const [name, check] of this.checks) {\n try {\n customResults[name] = await check();\n } catch (error) {\n customResults[name] = {\n healthy: false,\n message: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }\n\n const allHealthy = services.every((s) => s.healthy) &&\n Object.values(customResults).every((r) => r.healthy);\n\n return {\n healthy: allHealthy,\n services,\n uptime: Math.floor((Date.now() - this.startTime) / 1000),\n timestamp: new Date().toISOString(),\n };\n }\n\n private async getServiceHealth(serviceName: string): Promise<ServiceHealth | null> {\n const serviceManager = getServiceManager();\n\n const exists = await serviceManager.exists(serviceName);\n if (!exists) {\n return null;\n }\n\n const status = await serviceManager.status(serviceName);\n const healthy = status.active && status.subState === \"running\";\n\n return {\n name: serviceName,\n healthy,\n status,\n checkedAt: new Date().toISOString(),\n };\n }\n\n private sendJson(res: ServerResponse, statusCode: number, data: unknown): void {\n res.statusCode = statusCode;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify(data, null, 2));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton Instance\n// ---------------------------------------------------------------------------\n\nlet healthServer: HealthServer | null = null;\n\n/**\n * Start the health server with config port.\n */\nexport async function startHealthServer(port?: number): Promise<HealthServer> {\n const config = loadConfig();\n const actualPort = port ?? config.healthPort ?? 8914;\n\n if (!healthServer) {\n healthServer = new HealthServer(actualPort);\n }\n\n await healthServer.start();\n return healthServer;\n}\n\n/**\n * Stop the health server.\n */\nexport async function stopHealthServer(): Promise<void> {\n if (healthServer) {\n await healthServer.stop();\n healthServer = null;\n }\n}\n\n/**\n * Get the health server instance.\n */\nexport function getHealthServer(): HealthServer | null {\n return healthServer;\n}\n"
|
|
11
|
+
"/**\n * Health monitoring HTTP server.\n *\n * Provides an HTTP endpoint for health checks on port 8914 (configurable).\n *\n * @example\n * ```typescript\n * import { HealthServer, startHealthServer } from \"@ebowwa/pkg-ops/health-server\";\n *\n * // Start health server\n * const server = await startHealthServer(8914);\n *\n * // Custom health checks\n * server.addCheck(\"custom\", async () => ({\n * healthy: true,\n * message: \"Custom check passed\",\n * }));\n *\n * // Stop server\n * await server.stop();\n * ```\n */\n\nimport { createServer, type Server as HttpServer, type IncomingMessage, type ServerResponse } from \"http\";\nimport { getServiceManager, type ServiceStatus } from \"./service-manager.js\";\nimport { loadConfig, type PkgOpsConfig } from \"./config.js\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface HealthCheckResult {\n /** Whether the check passed */\n healthy: boolean;\n /** Human-readable message */\n message: string;\n /** Additional data */\n data?: Record<string, unknown>;\n}\n\nexport interface ServiceHealth {\n /** Service name */\n name: string;\n /** Whether the service is healthy */\n healthy: boolean;\n /** Service status */\n status: ServiceStatus;\n /** Last check timestamp */\n checkedAt: string;\n}\n\nexport interface SystemHealth {\n /** Overall health status */\n healthy: boolean;\n /** All services health */\n services: ServiceHealth[];\n /** System uptime in seconds */\n uptime: number;\n /** Timestamp of this check */\n timestamp: string;\n}\n\nexport type HealthCheckFn = () => Promise<HealthCheckResult> | HealthCheckResult;\n\n// ---------------------------------------------------------------------------\n// Health Server Class\n// ---------------------------------------------------------------------------\n\n/**\n * HTTP server for health monitoring.\n */\nexport class HealthServer {\n private server: HttpServer | null = null;\n private checks = new Map<string, HealthCheckFn>();\n private startTime = Date.now();\n private port: number;\n\n constructor(port: number = 8914) {\n this.port = port;\n }\n\n /**\n * Start the health server.\n */\n async start(): Promise<void> {\n if (this.server) {\n return;\n }\n\n return new Promise((resolve, reject) => {\n this.server = createServer((req, res) => this.handleRequest(req, res));\n\n this.server.on(\"error\", reject);\n\n this.server.listen(this.port, () => {\n console.log(`Health server listening on port ${this.port}`);\n this.server?.off(\"error\", reject);\n resolve();\n });\n });\n }\n\n /**\n * Stop the health server.\n */\n async stop(): Promise<void> {\n if (!this.server) {\n return;\n }\n\n return new Promise((resolve) => {\n this.server?.close(() => {\n this.server = null;\n resolve();\n });\n });\n }\n\n /**\n * Add a custom health check.\n */\n addCheck(name: string, check: HealthCheckFn): void {\n this.checks.set(name, check);\n }\n\n /**\n * Remove a health check.\n */\n removeCheck(name: string): void {\n this.checks.delete(name);\n }\n\n /**\n * Check health of all services or a specific service.\n * Public method for CLI usage.\n */\n async checkHealth(serviceName?: string): Promise<SystemHealth | ServiceHealth | null> {\n if (serviceName) {\n return this.getServiceHealth(serviceName);\n }\n return this.getSystemHealth();\n }\n\n // ---------------------------------------------------------------------------\n // Private Methods\n // ---------------------------------------------------------------------------\n\n private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {\n const url = req.url ?? \"/\";\n const method = req.method ?? \"GET\";\n\n try {\n if (method === \"GET\" && url === \"/health\") {\n const health = await this.getSystemHealth();\n this.sendJson(res, 200, health);\n } else if (method === \"GET\" && url.startsWith(\"/health/\")) {\n const serviceName = url.slice(8).replace(\".service\", \"\");\n const health = await this.getServiceHealth(serviceName);\n this.sendJson(res, health ? 200 : 404, health ?? { error: \"Service not found\" });\n } else if (method === \"GET\" && url === \"/ready\") {\n const health = await this.getSystemHealth();\n this.sendJson(res, health.healthy ? 200 : 503, { ready: health.healthy });\n } else if (method === \"GET\" && url === \"/live\") {\n this.sendJson(res, 200, { alive: true });\n } else {\n this.sendJson(res, 404, { error: \"Not found\" });\n }\n } catch (error) {\n console.error(\"Health check error:\", error);\n this.sendJson(res, 500, { error: \"Internal server error\" });\n }\n }\n\n private async getSystemHealth(): Promise<SystemHealth> {\n const config = loadConfig();\n const serviceManager = getServiceManager();\n\n const services: ServiceHealth[] = [];\n\n for (const [packageName, pkgConfig] of Object.entries(config.packages)) {\n if (!pkgConfig.service) continue;\n\n const status = await serviceManager.status(pkgConfig.service);\n const healthy = status.active && status.subState === \"running\";\n\n services.push({\n name: pkgConfig.service,\n healthy,\n status,\n checkedAt: new Date().toISOString(),\n });\n }\n\n // Run custom checks\n const customResults: Record<string, HealthCheckResult> = {};\n for (const [name, check] of this.checks) {\n try {\n customResults[name] = await check();\n } catch (error) {\n customResults[name] = {\n healthy: false,\n message: error instanceof Error ? error.message : \"Unknown error\",\n };\n }\n }\n\n const allHealthy = services.every((s) => s.healthy) &&\n Object.values(customResults).every((r) => r.healthy);\n\n return {\n healthy: allHealthy,\n services,\n uptime: Math.floor((Date.now() - this.startTime) / 1000),\n timestamp: new Date().toISOString(),\n };\n }\n\n private async getServiceHealth(serviceName: string): Promise<ServiceHealth | null> {\n const serviceManager = getServiceManager();\n\n const exists = await serviceManager.exists(serviceName);\n if (!exists) {\n return null;\n }\n\n const status = await serviceManager.status(serviceName);\n const healthy = status.active && status.subState === \"running\";\n\n return {\n name: serviceName,\n healthy,\n status,\n checkedAt: new Date().toISOString(),\n };\n }\n\n private sendJson(res: ServerResponse, statusCode: number, data: unknown): void {\n res.statusCode = statusCode;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify(data, null, 2));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton Instance\n// ---------------------------------------------------------------------------\n\nlet healthServer: HealthServer | null = null;\n\n/**\n * Start the health server with config port.\n */\nexport async function startHealthServer(port?: number): Promise<HealthServer> {\n const config = loadConfig();\n const actualPort = port ?? config.healthPort ?? 8914;\n\n if (!healthServer) {\n healthServer = new HealthServer(actualPort);\n }\n\n await healthServer.start();\n return healthServer;\n}\n\n/**\n * Stop the health server.\n */\nexport async function stopHealthServer(): Promise<void> {\n if (healthServer) {\n await healthServer.stop();\n healthServer = null;\n }\n}\n\n/**\n * Get the health server instance.\n */\nexport function getHealthServer(): HealthServer | null {\n return healthServer;\n}\n",
|
|
12
|
+
"/**\n * Service management using @ebowwa/installations.\n *\n * Wraps systemd operations for package operations.\n *\n * @example\n * ```typescript\n * import { ServiceManager } from \"@ebowwa/pkg-ops/service-manager\";\n *\n * const manager = new ServiceManager();\n *\n * // Start a service\n * await manager.start(\"stack\");\n *\n * // Check status\n * const status = await manager.status(\"stack\");\n * console.log(status.active ? \"Running\" : \"Stopped\");\n *\n * // View logs\n * const logs = await manager.logs(\"stack\", { lines: 50 });\n * ```\n */\n\nimport {\n startService,\n stopService,\n restartService,\n getServiceStatus,\n enableService,\n disableService,\n serviceExists,\n getServiceLogs,\n type ServiceStatus,\n} from \"@ebowwa/installations/systemd\";\n\nimport type { SudoOptions } from \"@ebowwa/installations\";\n\n// Re-export ServiceStatus for other modules\nexport type { ServiceStatus } from \"@ebowwa/installations/systemd\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface ServiceInfo {\n /** Service name (without .service suffix) */\n name: string;\n /** Whether the service exists */\n exists: boolean;\n /** Service status */\n status: ServiceStatus;\n /** Associated package (if known) */\n package?: string;\n}\n\nexport interface ServiceLogsOptions {\n /** Number of lines to show (default: 100) */\n lines?: number;\n /** Show logs since timestamp */\n since?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Service Manager Class\n// ---------------------------------------------------------------------------\n\n/**\n * Manages systemd services for packages.\n */\nexport class ServiceManager {\n private sudoOptions: SudoOptions;\n\n constructor(sudoOptions?: SudoOptions) {\n this.sudoOptions = sudoOptions ?? { context: { type: \"local\" } };\n }\n\n /**\n * Start a service.\n */\n async start(name: string): Promise<{ success: boolean; message: string }> {\n const result = await startService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} started` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Stop a service.\n */\n async stop(name: string): Promise<{ success: boolean; message: string }> {\n const result = await stopService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} stopped` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Restart a service.\n */\n async restart(name: string): Promise<{ success: boolean; message: string }> {\n const result = await restartService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} restarted` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Get service status.\n */\n async status(name: string): Promise<ServiceStatus> {\n return getServiceStatus(name, this.sudoOptions);\n }\n\n /**\n * Enable a service to start on boot.\n */\n async enable(name: string): Promise<{ success: boolean; message: string }> {\n const result = await enableService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} enabled` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Disable a service from starting on boot.\n */\n async disable(name: string): Promise<{ success: boolean; message: string }> {\n const result = await disableService(name, this.sudoOptions);\n return {\n success: result.ok,\n message: result.ok ? `Service ${name} disabled` : result.stderr || result.stdout,\n };\n }\n\n /**\n * Check if a service exists.\n */\n async exists(name: string): Promise<boolean> {\n return serviceExists(name, this.sudoOptions);\n }\n\n /**\n * Get service logs.\n */\n async logs(name: string, options?: ServiceLogsOptions): Promise<string> {\n return getServiceLogs(name, {\n ...this.sudoOptions,\n lines: options?.lines ?? 100,\n since: options?.since,\n });\n }\n\n /**\n * Get comprehensive service info.\n */\n async info(name: string): Promise<ServiceInfo> {\n const [existsResult, statusResult] = await Promise.all([\n this.exists(name),\n this.status(name),\n ]);\n\n return {\n name,\n exists: existsResult,\n status: statusResult,\n };\n }\n\n /**\n * Check if a service is healthy (running and active).\n */\n async isHealthy(name: string): Promise<boolean> {\n const status = await this.status(name);\n return status.active && status.subState === \"running\";\n }\n\n /**\n * Wait for a service to become healthy.\n */\n async waitForHealthy(\n name: string,\n options?: { timeout?: number; interval?: number }\n ): Promise<boolean> {\n const timeout = options?.timeout ?? 30000;\n const interval = options?.interval ?? 1000;\n const start = Date.now();\n\n while (Date.now() - start < timeout) {\n const healthy = await this.isHealthy(name);\n if (healthy) return true;\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton Instance\n// ---------------------------------------------------------------------------\n\nlet defaultManager: ServiceManager | null = null;\n\n/**\n * Get the default service manager instance.\n */\nexport function getServiceManager(): ServiceManager {\n if (!defaultManager) {\n defaultManager = new ServiceManager();\n }\n return defaultManager;\n}\n",
|
|
13
|
+
"/**\n * Configuration management for PkgOps.\n *\n * Handles reading/writing config file at /etc/pkg-ops/config.json\n *\n * @example\n * ```typescript\n * import { loadConfig, saveConfig, getConfigPath } from \"@ebowwa/pkg-ops/config\";\n *\n * const config = await loadConfig();\n * console.log(config.packages);\n *\n * config.packages[\"@ebowwa/stack\"] = { version: \"0.7.13\", service: \"stack.service\" };\n * await saveConfig(config);\n * ```\n */\n\nimport { accessSync, constants, mkdirSync, readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface PackageConfig {\n /** Package version (semver or \"latest\") */\n version: string;\n /** Associated systemd service name (without .service suffix) */\n service?: string;\n /** Whether to auto-start the service after install */\n autoStart?: boolean;\n /** Custom environment variables for the service */\n environment?: Record<string, string>;\n}\n\nexport interface PkgOpsConfig {\n /** Managed packages */\n packages: Record<string, PackageConfig>;\n /** Health check HTTP port (default: 8914) */\n healthPort?: number;\n /** Working directory for installations (default: /root) */\n workDir?: string;\n /** Log level (default: \"info\") */\n logLevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nexport const DEFAULT_CONFIG: PkgOpsConfig = {\n packages: {},\n healthPort: 8914,\n workDir: \"/root\",\n logLevel: \"info\",\n};\n\nexport const CONFIG_DIR = \"/etc/pkg-ops\";\nexport const CONFIG_PATH = `${CONFIG_DIR}/config.json`;\n\n// ---------------------------------------------------------------------------\n// Functions\n// ---------------------------------------------------------------------------\n\n/**\n * Get the config file path.\n * Respects PKG_OPS_CONFIG env override.\n */\nexport function getConfigPath(): string {\n return process.env.PKG_OPS_CONFIG ?? CONFIG_PATH;\n}\n\n/**\n * Ensure config directory exists (requires sudo on most systems).\n */\nexport function ensureConfigDir(): void {\n const configDir = dirname(getConfigPath());\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true, mode: constants.S_IRWXU | constants.S_IRGRP | constants.S_IXGRP });\n }\n}\n\n/**\n * Load configuration from file.\n * Returns default config if file doesn't exist.\n */\nexport function loadConfig(): PkgOpsConfig {\n const configPath = getConfigPath();\n\n try {\n if (!existsSync(configPath)) {\n return { ...DEFAULT_CONFIG };\n }\n\n const content = readFileSync(configPath, \"utf-8\");\n const parsed = JSON.parse(content);\n\n // Merge with defaults\n return {\n ...DEFAULT_CONFIG,\n ...parsed,\n };\n } catch (error) {\n console.error(`Failed to load config from ${configPath}:`, error);\n return { ...DEFAULT_CONFIG };\n }\n}\n\n/**\n * Save configuration to file.\n * Creates directory if it doesn't exist.\n */\nexport function saveConfig(config: PkgOpsConfig): void {\n const configPath = getConfigPath();\n ensureConfigDir();\n\n const content = JSON.stringify(config, null, 2);\n writeFileSync(configPath, content, {\n encoding: \"utf-8\",\n mode: constants.S_IRUSR | constants.S_IWUSR | constants.S_IRGRP,\n });\n}\n\n/**\n * Update a package in the config.\n */\nexport function updatePackageConfig(\n packageName: string,\n packageConfig: PackageConfig\n): PkgOpsConfig {\n const config = loadConfig();\n config.packages[packageName] = packageConfig;\n saveConfig(config);\n return config;\n}\n\n/**\n * Remove a package from the config.\n */\nexport function removePackageConfig(packageName: string): PkgOpsConfig {\n const config = loadConfig();\n delete config.packages[packageName];\n saveConfig(config);\n return config;\n}\n\n/**\n * Get a specific package config.\n */\nexport function getPackageConfig(packageName: string): PackageConfig | undefined {\n const config = loadConfig();\n return config.packages[packageName];\n}\n\n/**\n * List all managed packages.\n */\nexport function listManagedPackages(): Array<{ name: string; config: PackageConfig }> {\n const config = loadConfig();\n return Object.entries(config.packages).map(([name, cfg]) => ({ name, config: cfg }));\n}\n\n/**\n * Validate package name (must be @ebowwa/* scope).\n */\nexport function isValidPackageName(name: string): boolean {\n return name.startsWith(\"@ebowwa/\");\n}\n\n/**\n * Parse package specifier into name and version.\n * @example\n * parsePackageSpec(\"@ebowwa/stack@0.7.12\") => { name: \"@ebowwa/stack\", version: \"0.7.12\" }\n * parsePackageSpec(\"@ebowwa/stack\") => { name: \"@ebowwa/stack\", version: \"latest\" }\n */\nexport function parsePackageSpec(spec: string): { name: string; version: string } {\n const atIndex = spec.lastIndexOf(\"@\");\n if (atIndex <= 0) {\n // No version specified or scoped package without version\n return { name: spec, version: \"latest\" };\n }\n\n const name = spec.slice(0, atIndex);\n const version = spec.slice(atIndex + 1);\n\n if (!version) {\n return { name, version: \"latest\" };\n }\n\n return { name, version };\n}\n"
|
|
12
14
|
],
|
|
13
|
-
"mappings": ";8YAKA,IAAI,EAAY,GAAQ,EAAK,UAAa,QAAS,EAAG,CASlD,OARA,EAAW,OAAO,QAAU,QAAQ,CAAC,EAAG,CACpC,QAAS,EAAG,EAAI,EAAG,EAAI,UAAU,OAAQ,EAAI,EAAG,IAAK,CACjD,EAAI,UAAU,GACd,QAAS,KAAK,EAAG,GAAI,OAAO,UAAU,eAAe,KAAK,EAAG,CAAC,EAC1D,EAAE,GAAK,EAAE,GAEjB,OAAO,GAEJ,EAAS,MAAM,KAAM,SAAS,GAErC,EAAa,GAAQ,EAAK,WAAc,QAAS,CAAC,EAAS,EAAY,EAAG,EAAW,CACrF,SAAS,CAAK,CAAC,EAAO,CAAE,OAAO,aAAiB,EAAI,EAAQ,IAAI,EAAE,QAAS,CAAC,EAAS,CAAE,EAAQ,CAAK,EAAI,EACxG,OAAO,IAAK,IAAM,EAAI,UAAU,QAAS,CAAC,EAAS,EAAQ,CACvD,SAAS,CAAS,CAAC,EAAO,CAAE,GAAI,CAAE,EAAK,EAAU,KAAK,CAAK,CAAC,EAAK,MAAO,EAAG,CAAE,EAAO,CAAC,GACrF,SAAS,CAAQ,CAAC,EAAO,CAAE,GAAI,CAAE,EAAK,EAAU,MAAS,CAAK,CAAC,EAAK,MAAO,EAAG,CAAE,EAAO,CAAC,GACxF,SAAS,CAAI,CAAC,EAAQ,CAAE,EAAO,KAAO,EAAQ,EAAO,KAAK,EAAI,EAAM,EAAO,KAAK,EAAE,KAAK,EAAW,CAAQ,EAC1G,GAAM,EAAY,EAAU,MAAM,EAAS,GAAc,CAAC,CAAC,GAAG,KAAK,CAAC,EACvE,GAED,EAAe,GAAQ,EAAK,aAAgB,QAAS,CAAC,EAAS,EAAM,CACrE,IAAI,EAAI,CAAE,MAAO,EAAG,KAAM,QAAQ,EAAG,CAAE,GAAI,EAAE,GAAK,EAAG,MAAM,EAAE,GAAI,OAAO,EAAE,IAAO,KAAM,CAAC,EAAG,IAAK,CAAC,CAAE,EAAG,EAAG,EAAG,EAAG,EAAI,OAAO,QAAQ,OAAO,WAAa,WAAa,SAAW,QAAQ,SAAS,EAC/L,OAAO,EAAE,KAAO,EAAK,CAAC,EAAG,EAAE,MAAW,EAAK,CAAC,EAAG,EAAE,OAAY,EAAK,CAAC,EAAG,OAAO,SAAW,aAAe,EAAE,OAAO,UAAY,QAAQ,EAAG,CAAE,OAAO,OAAU,EAC1J,SAAS,CAAI,CAAC,EAAG,CAAE,OAAO,QAAS,CAAC,EAAG,CAAE,OAAO,EAAK,CAAC,EAAG,CAAC,CAAC,GAC3D,SAAS,CAAI,CAAC,EAAI,CACd,GAAI,EAAG,MAAU,UAAU,iCAAiC,EAC5D,MAAO,IAAM,EAAI,EAAG,EAAG,KAAO,EAAI,IAAK,EAAG,GAAI,CAC1C,GAAI,EAAI,EAAG,IAAM,EAAI,EAAG,GAAK,EAAI,EAAE,OAAY,EAAG,GAAK,EAAE,SAAc,EAAI,EAAE,SAAc,EAAE,KAAK,CAAC,EAAG,GAAK,EAAE,OAAS,EAAE,EAAI,EAAE,KAAK,EAAG,EAAG,EAAE,GAAG,KAAM,OAAO,EAC3J,GAAI,EAAI,EAAG,EAAG,EAAK,CAAC,EAAG,GAAK,EAAG,EAAE,KAAK,EACtC,OAAQ,EAAG,QACF,OAAQ,GAAG,EAAI,EAAI,UACnB,GAAc,OAAX,EAAE,QAAgB,CAAE,MAAO,EAAG,GAAI,KAAM,EAAM,MACjD,GAAG,EAAE,QAAS,EAAI,EAAG,GAAI,EAAK,CAAC,CAAC,EAAG,aACnC,GAAG,EAAK,EAAE,IAAI,IAAI,EAAG,EAAE,KAAK,IAAI,EAAG,iBAEpC,IAAM,EAAI,EAAE,KAAM,IAAI,EAAE,OAAS,GAAK,EAAE,EAAE,OAAS,OAAQ,EAAG,KAAO,GAAK,EAAG,KAAO,GAAI,CAAE,EAAI,EAAG,SACjG,GAAI,EAAG,KAAO,IAAM,CAAC,GAAM,EAAG,GAAK,EAAE,IAAM,EAAG,GAAK,EAAE,IAAM,CAAE,EAAE,MAAQ,EAAG,GAAI,MAC9E,GAAI,EAAG,KAAO,GAAK,EAAE,MAAQ,EAAE,GAAI,CAAE,EAAE,MAAQ,EAAE,GAAI,EAAI,EAAI,MAC7D,GAAI,GAAK,EAAE,MAAQ,EAAE,GAAI,CAAE,EAAE,MAAQ,EAAE,GAAI,EAAE,IAAI,KAAK,CAAE,EAAG,MAC3D,GAAI,EAAE,GAAI,EAAE,IAAI,IAAI,EACpB,EAAE,KAAK,IAAI,EAAG,SAEtB,EAAK,EAAK,KAAK,EAAS,CAAC,EAC3B,MAAO,EAAG,CAAE,EAAK,CAAC,EAAG,CAAC,EAAG,EAAI,SAAK,CAAU,EAAI,EAAI,EACtD,GAAI,EAAG,GAAK,EAAG,MAAM,EAAG,GAAI,MAAO,CAAE,MAAO,EAAG,GAAK,EAAG,GAAU,OAAG,KAAM,EAAK,IAGnF,EAAiB,GAAQ,EAAK,eAAkB,QAAS,CAAC,EAAI,EAAM,EAAM,CAC1E,GAAI,GAAQ,UAAU,SAAW,GAAG,QAAS,EAAI,EAAG,EAAI,EAAK,OAAQ,EAAI,EAAI,EAAG,IAC5E,GAAI,GAAM,EAAE,KAAK,GAAO,CACpB,GAAI,CAAC,EAAI,EAAK,MAAM,UAAU,MAAM,KAAK,EAAM,EAAG,CAAC,EACnD,EAAG,GAAK,EAAK,IAGrB,OAAO,EAAG,OAAO,GAAM,MAAM,UAAU,MAAM,KAAK,CAAI,CAAC,GAE3D,OAAO,eAAe,EAAS,aAAc,CAAE,MAAO,EAAK,CAAC,EAC5D,EAAQ,KAAO,EACf,EAAQ,WAAa,GACrB,EAAQ,UAAY,GACpB,EAAQ,QAAU,GAClB,EAAQ,cAAgB,GACxB,EAAQ,KAAO,EAKf,SAAS,CAAI,CAAC,EAAK,EAAM,CACrB,OAAO,EAAU,KAAW,OAAQ,OAAG,QAAS,EAAG,CAC/C,IAAI,EAAO,EAAW,EACtB,OAAO,EAAY,KAAM,QAAS,CAAC,EAAI,CASnC,OARA,EAAQ,MAAM,QAAQ,CAAG,EAAI,EAAM,EAAI,MAAM,KAAK,EAClD,EAAY,EAAK,IACX,OAAO,QAAQ,EAAK,GAAG,EAAE,IAAI,QAAS,CAAC,EAAI,CACzC,IAAI,EAAI,EAAG,GAAI,EAAI,EAAG,GACtB,MAAO,GAAG,OAAO,EAAG,GAAG,EAAE,OAAO,EAAY,CAAC,CAAC,EACjD,EACC,CAAC,EACP,EAAU,EAAc,EAAc,CAAC,MAAM,EAAG,EAAW,EAAI,EAAG,EAAO,EAAI,EACtE,CAAC,EAAc,EAAK,EAAS,CAAI,CAAC,EAC5C,EACJ,EAEL,IAAI,GAAa,CACb,IAAK,CAAC,UAAW,UAAW,IAAI,EAChC,IAAK,CAAC,MAAO,UAAW,IAAI,EAC5B,IAAK,CAAC,MAAO,MAAO,YAAY,CACpC,EACI,GAAY,CACZ,IAAK,CAAC,UAAW,SAAU,KAAK,EAChC,IAAK,CAAC,MAAO,cAAc,EAC3B,IAAK,CAAC,MAAO,QAAQ,CACzB,EAEA,SAAS,EAAU,CAAC,EAAU,EAAM,CAChC,OAAO,EAAU,KAAW,OAAQ,OAAG,QAAS,EAAG,CAC/C,IAAI,EAAI,EACJ,EACJ,OAAO,EAAY,KAAM,QAAS,CAAC,EAAI,CACnC,OAAQ,EAAG,WACF,GAID,OAHA,GAAM,EAAK,EAAK,MAAQ,MAAQ,IAAY,OAAI,EAAK,MACrD,EAAc,EAAS,EAAS,CAAC,EAAG,EAAK,GAAG,EAAI,EAAK,iBAAmB,GAAQ,CAAE,gBAAiB,gBAAiB,EAAI,CAAC,CAAE,EAEpH,CAAC,EAAa,EAAK,GAAU,GAAK,EAAS,EAAS,CAAC,EAAG,CAAI,EAAG,CAAE,IAAK,EAAa,MAAO,EAAK,CAAC,CAAC,CAAC,MACxG,GAGD,OADA,EAAG,KAAK,EACD,CAAC,EAAc,EAAK,EAAc,EAAc,CAAC,EAAG,GAAW,GAAK,EAAI,EAAG,EAAU,EAAI,EAAG,EAAS,EAAS,CAAC,EAAG,CAAI,EAAG,CAAE,IAAK,CAAY,CAAC,CAAC,CAAC,GAEjK,EACJ,EAGL,SAAS,EAAS,CAAC,EAAM,EAAS,EAAM,CACpC,OAAO,EAAU,KAAW,OAAQ,OAAG,QAAS,EAAG,CAC/C,IAAI,EAAI,EAAQ,EAChB,OAAO,EAAY,KAAM,QAAS,CAAC,EAAI,CACnC,OAAQ,EAAG,WACF,GAGD,OAFA,EAAK,EAAK,OAAS,KAAO,GAC1B,EAAS,OAAO,OAAO,EAAI,GAAG,EAAE,OAAO,EAAY,CAAI,CAAC,EAAE,KAAK,EACxD,CAAC,EAAa,GAAS,EAAS,CAAC,OAAQ,CAAM,EAAG,CAAI,CAAC,MAC7D,GAED,GADA,EAAS,EAAG,KAAK,EACb,EAAE,EAAO,IAAM,EAAK,MAAO,MAAO,CAAC,EAAa,CAAC,EACrD,MAAO,CAAC,EAAa,EAAK,CAAC,QAAS,EAAK,KAAM,CAAI,EAAG,CAAI,CAAC,MAC1D,GACD,EAAG,KAAK,EACR,EAAG,MAAQ,MACV,GACD,GAAI,EAAE,EAAO,IAAM,EAAK,OAAQ,MAAO,CAAC,EAAa,CAAC,EACtD,MAAO,CAAC,EAAa,EAAK,CAAC,QAAS,EAAK,MAAO,CAAI,EAAG,CAAI,CAAC,MAC3D,GACD,EAAG,KAAK,EACR,EAAG,MAAQ,MACV,GAAG,MAAO,CAAC,EAAc,CAAM,GAE3C,EACJ,EAGL,SAAS,EAAO,CAAC,EAAM,EAAQ,EAAM,CACjC,OAAO,EAAU,KAAW,OAAQ,OAAG,QAAS,EAAG,CAC/C,OAAO,EAAY,KAAM,QAAS,CAAC,EAAI,CACnC,MAAO,CAAC,EAAc,EAAK,CAAC,YAAa,EAAQ,CAAI,EAAG,CAAI,CAAC,EAChE,EACJ,EAGL,SAAS,EAAa,CAAC,EAAM,EAAM,CAC/B,OAAO,EAAU,KAAW,OAAQ,OAAG,QAAS,EAAG,CAC/C,OAAO,EAAY,KAAM,QAAS,CAAC,EAAI,CACnC,MAAO,CAAC,EAAc,EAAK,CAAC,YAAa,SAAU,QAAS,CAAI,EAAG,CAAI,CAAC,EAC3E,EACJ,EAKL,SAAS,CAAc,CAAC,EAAK,CACzB,IAAI,EACA,EAAQ,CAAC,MAAO,KAAM,YAAa,KAAM,2BAA4B,KAAM,8BAA8B,EAC7G,GAAI,EAAI,QACJ,EAAM,KAAK,KAAM,EAAI,OAAO,EAC3B,QAAI,EAAI,IACT,EAAM,KAAK,KAAM,EAAI,GAAG,EAC5B,GAAI,EAAI,KACJ,EAAM,KAAK,KAAM,OAAO,EAAI,IAAI,CAAC,EAErC,OADA,EAAM,KAAK,GAAG,QAAQ,EAAK,EAAI,QAAU,MAAQ,IAAY,OAAI,EAAK,OAAQ,GAAG,EAAE,OAAO,EAAI,IAAI,CAAC,EAC5F,EAEX,SAAS,CAAI,CAAC,EAAM,EAAM,CACtB,OAAO,EAAU,KAAW,OAAQ,OAAG,QAAS,EAAG,CAC/C,IAAI,EAAK,EAAW,EAAM,EAAU,EAAQ,EAAI,EAC5C,EAAI,EACR,OAAO,EAAY,KAAM,QAAS,CAAC,EAAI,CACnC,OAAQ,EAAG,WACF,GASD,OARA,GAAO,EAAK,EAAK,WAAa,MAAQ,IAAY,OAAI,EAAK,CAAE,KAAM,OAAQ,EAC3E,EAAY,EAAI,OAAS,MACnB,EAAc,EAAc,CAAC,EAAG,EAAe,CAAG,EAAG,EAAI,EAAG,CAAC,EAAK,IAAI,CAAW,EAAE,KAAK,GAAG,CAAC,EAAG,EAAK,EAAI,EAC9G,EAAO,IAAI,MAAM,EAAW,CACxB,OAAQ,OACR,OAAQ,OACR,SAAU,EAAK,EAAK,WAAa,MAAQ,IAAY,OAAI,EAAK,KAClE,CAAC,EACM,CAAC,EAAa,EAAK,MAAM,MAC/B,GAED,GADA,EAAW,EAAG,KAAK,EACf,CAAC,EAAK,MAAO,MAAO,CAAC,EAAa,CAAC,EAEvC,OADA,EAAK,GACE,CAAC,EAAa,CAAC,MACrB,GAAG,MAAO,CAAC,EAAa,IAAI,SAAS,EAAK,MAAM,EAAE,KAAK,CAAC,MACxD,GACD,EAAK,EAAG,KAAK,EACb,EAAG,MAAQ,MACV,GAED,OADA,EAAS,EACF,CAAC,EAAa,IAAI,SAAS,EAAK,MAAM,EAAE,KAAK,CAAC,MACpD,GAED,OADA,EAAS,EAAG,KAAK,EACV,CAAC,EAAc,CAAE,OAAQ,EAAQ,OAAQ,EAAQ,SAAU,EAAU,GAAI,IAAa,CAAE,CAAC,GAE3G,EACJ,EAEL,SAAS,EAAQ,CAAC,EAAO,EAAM,EAAM,CACjC,OAAO,EAAU,KAAW,OAAQ,OAAG,QAAS,EAAG,CAC/C,IAAI,EAAK,EAAW,EAAW,EAAU,EAAQ,EAAY,EAAU,EAAI,EAAU,EAAM,EAAU,EAAQ,EAAI,EAC7G,EAAI,EAAI,EACZ,OAAO,EAAY,KAAM,QAAS,CAAC,EAAI,CACnC,OAAQ,EAAG,WACF,GAED,GADA,GAAO,EAAK,EAAK,WAAa,MAAQ,IAAY,OAAI,EAAK,CAAE,KAAM,OAAQ,EACrE,EAAI,OAAS,MAAQ,MAAO,CAAC,EAAa,CAAC,EAUjD,OATA,EAAY,EAAe,CAAG,EAC9B,EAAY,EAAK,KAAK,GAAG,EACzB,EAAW,EAAc,EAAc,CAAC,EAAG,EAAW,EAAI,EAAG,CAAC,CAAS,EAAG,EAAK,EAC/E,EAAS,IAAI,MAAM,EAAU,CACzB,MAAO,IAAI,YAAY,EAAE,OAAO,CAAK,EACrC,OAAQ,OACR,OAAQ,OACR,SAAU,EAAK,EAAK,WAAa,MAAQ,IAAY,OAAI,EAAK,KAClE,CAAC,EACM,CAAC,EAAa,EAAO,MAAM,MACjC,GAED,GADA,EAAa,EAAG,KAAK,EACjB,CAAC,EAAK,MAAO,MAAO,CAAC,EAAa,CAAC,EAEvC,OADA,EAAK,GACE,CAAC,EAAa,CAAC,MACrB,GAAG,MAAO,CAAC,EAAa,IAAI,SAAS,EAAO,MAAM,EAAE,KAAK,CAAC,MAC1D,GACD,EAAK,EAAG,KAAK,EACb,EAAG,MAAQ,MACV,GAED,OADA,EAAW,EACJ,CAAC,EAAa,IAAI,SAAS,EAAO,MAAM,EAAE,KAAK,CAAC,MACtD,GAED,OADA,EAAW,EAAG,KAAK,EACZ,CAAC,EAAc,CAAE,OAAQ,EAAU,OAAQ,EAAU,SAAU,EAAY,GAAI,IAAe,CAAE,CAAC,MACvG,GAOD,OANA,EAAO,IAAI,MAAM,CAAC,KAAM,KAAM,EAAK,KAAK,GAAG,CAAC,EAAG,CAC3C,MAAO,IAAI,YAAY,EAAE,OAAO,CAAK,EACrC,OAAQ,OACR,OAAQ,OACR,SAAU,EAAK,EAAK,WAAa,MAAQ,IAAY,OAAI,EAAK,KAClE,CAAC,EACM,CAAC,EAAa,EAAK,MAAM,MAC/B,GAED,GADA,EAAW,EAAG,KAAK,EACf,CAAC,EAAK,MAAO,MAAO,CAAC,EAAa,CAAC,EAEvC,OADA,EAAK,GACE,CAAC,EAAa,EAAE,MACtB,GAAG,MAAO,CAAC,EAAa,IAAI,SAAS,EAAK,MAAM,EAAE,KAAK,CAAC,MACxD,GACD,EAAK,EAAG,KAAK,EACb,EAAG,MAAQ,OACV,IAED,OADA,EAAS,EACF,CAAC,EAAa,IAAI,SAAS,EAAK,MAAM,EAAE,KAAK,CAAC,MACpD,IAED,OADA,EAAS,EAAG,KAAK,EACV,CAAC,EAAc,CAAE,OAAQ,EAAQ,OAAQ,EAAQ,SAAU,EAAU,GAAI,IAAa,CAAE,CAAC,GAE3G,EACJ,EAEL,SAAS,CAAW,CAAC,EAAG,CACpB,GAAI,0BAA0B,KAAK,CAAC,EAChC,OAAO,EACX,MAAO,IAAI,OAAO,EAAE,QAAQ,KAAM,OAAO,EAAG,GAAG,KC5PnD,uBAAS,iBAAc,iBCPvB,oBAAqB,eAAW,mBAAW,oBAAc,iBAAe,gBACxE,kBAAS,mBAiCF,IAAM,EAA+B,CAC1C,SAAU,CAAC,EACX,WAAY,KACZ,QAAS,QACT,SAAU,MACZ,EAEa,GAAa,eACb,GAAc,GAAG,iBAUvB,SAAS,CAAa,EAAW,CACtC,OAAO,QAAQ,IAAI,gBAAkB,GAMhC,SAAS,EAAe,EAAS,CACtC,IAAM,EAAY,GAAQ,EAAc,CAAC,EACzC,GAAI,CAAC,EAAW,CAAS,EACvB,GAAU,EAAW,CAAE,UAAW,GAAM,KAAM,EAAU,QAAU,EAAU,QAAU,EAAU,OAAQ,CAAC,EAQtG,SAAS,CAAU,EAAiB,CACzC,IAAM,EAAa,EAAc,EAEjC,GAAI,CACF,GAAI,CAAC,EAAW,CAAU,EAC1B,MAAO,IAAK,CAAe,EAG3B,IAAM,EAAU,GAAa,EAAY,OAAO,EAC1C,EAAS,KAAK,MAAM,CAAO,EAGjC,MAAO,IACF,KACA,CACL,EACA,MAAO,EAAO,CAEd,OADA,QAAQ,MAAM,8BAA8B,KAAe,CAAK,EACzD,IAAK,CAAe,GAQxB,SAAS,EAAU,CAAC,EAA4B,CACrD,IAAM,EAAa,EAAc,EACjC,GAAgB,EAEhB,IAAM,EAAU,KAAK,UAAU,EAAQ,KAAM,CAAC,EAC9C,GAAc,EAAY,EAAS,CACjC,SAAU,QACV,KAAM,EAAU,QAAU,EAAU,QAAU,EAAU,OAC1D,CAAC,EAMI,SAAS,CAAmB,CACjC,EACA,EACc,CACd,IAAM,EAAS,EAAW,EAG1B,OAFA,EAAO,SAAS,GAAe,EAC/B,GAAW,CAAM,EACV,EAgBF,SAAS,CAAgB,CAAC,EAAgD,CAE/E,OADe,EAAW,EACZ,SAAS,GAMlB,SAAS,CAAmB,EAAmD,CACpF,IAAM,EAAS,EAAW,EAC1B,OAAO,OAAO,QAAQ,EAAO,QAAQ,EAAE,IAAI,EAAE,EAAM,MAAU,CAAE,OAAM,OAAQ,CAAI,EAAE,EAM9E,SAAS,CAAkB,CAAC,EAAuB,CACxD,OAAO,EAAK,WAAW,UAAU,EAS5B,SAAS,CAAgB,CAAC,EAAiD,CAChF,IAAM,EAAU,EAAK,YAAY,GAAG,EACpC,GAAI,GAAW,EAEb,MAAO,CAAE,KAAM,EAAM,QAAS,QAAS,EAGzC,IAAM,EAAO,EAAK,MAAM,EAAG,CAAO,EAC5B,EAAU,EAAK,MAAM,EAAU,CAAC,EAEtC,GAAI,CAAC,EACH,MAAO,CAAE,OAAM,QAAS,QAAS,EAGnC,MAAO,CAAE,OAAM,SAAQ,EC9HzB,eAAe,CAAI,CAAC,EAAgB,EAAwC,CAC1E,IAAQ,QAAS,8CACjB,OAAO,EAAK,EAAM,CAAI,EA0WxB,eAAsB,CAAa,CACjC,EACA,EACqB,CACrB,OAAO,EAAK,CAAC,YAAa,SAAU,CAAI,EAAG,CAAI,EAMjD,eAAsB,CAAc,CAClC,EACA,EACqB,CACrB,OAAO,EAAK,CAAC,YAAa,UAAW,CAAI,EAAG,CAAI,EAMlD,eAAsB,CAAY,CAChC,EACA,EACqB,CACrB,OAAO,EAAK,CAAC,YAAa,QAAS,CAAI,EAAG,CAAI,EAMhD,eAAsB,CAAW,CAC/B,EACA,EACqB,CACrB,OAAO,EAAK,CAAC,YAAa,OAAQ,CAAI,EAAG,CAAI,EAM/C,eAAsB,CAAc,CAClC,EACA,EACqB,CACrB,OAAO,EAAK,CAAC,YAAa,UAAW,CAAI,EAAG,CAAI,EAgBlD,eAAsB,EAAgB,CACpC,EACA,EACwB,CACxB,IAAM,EAAS,MAAM,EAAK,CAAC,YAAa,OAAQ,EAAM,+DAA+D,EAAG,IACnH,CACL,CAAC,EAED,GAAI,CAAC,EAAO,GACV,MAAO,CAAE,OAAQ,GAAO,OAAQ,GAAO,SAAU,UAAW,QAAS,EAAG,YAAa,EAAG,EAG1F,IAAM,EAAQ,CAAC,IAAwB,CAErC,OADc,EAAO,OAAO,MAAM,IAAI,OAAO,IAAI,UAAa,GAAG,CAAC,IACnD,IAAI,KAAK,GAAK,IAG/B,MAAO,CACL,OAAQ,EAAM,WAAW,IAAM,SAC/B,OAAQ,EAAM,aAAa,IAAM,SACjC,SAAU,EAAM,UAAU,EAC1B,QAAS,SAAS,EAAM,SAAS,GAAK,IAAK,EAAE,EAC7C,YAAa,EAAM,aAAa,CAClC,EA6BF,eAAsB,EAAa,CACjC,EACA,EACkB,CAClB,IAAM,EAAS,MAAM,EAAK,CAAC,YAAa,kBAAmB,EAAO,UAAU,EAAG,IAC1E,EACH,MAAO,EACT,CAAC,EACD,OAAO,EAAO,IAAM,EAAO,OAAO,SAAS,CAAI,EAMjD,eAAsB,EAAc,CAClC,EACA,EAOI,CAAC,EACY,CACjB,IAAM,EAAO,CAAC,aAAc,KAAM,EAAM,KAAM,OAAO,EAAK,OAAS,GAAG,CAAC,EACvE,GAAI,EAAK,MAAO,EAAK,KAAK,UAAW,EAAK,KAAK,EAC/C,GAAI,CAAC,EAAK,OAAQ,EAAK,KAAK,KAAM,OAAO,EAAK,OAAS,GAAG,CAAC,EAG3D,OADe,MAAM,EAAK,EAAM,CAAI,GACtB,OCrfT,MAAM,EAAe,CAClB,YAER,WAAW,CAAC,EAA2B,CACrC,KAAK,YAAc,GAAe,CAAE,QAAS,CAAE,KAAM,OAAQ,CAAE,OAM3D,MAAK,CAAC,EAA8D,CACxE,IAAM,EAAS,MAAM,EAAa,EAAM,KAAK,WAAW,EACxD,MAAO,CACL,QAAS,EAAO,GAChB,QAAS,EAAO,GAAK,WAAW,YAAiB,EAAO,QAAU,EAAO,MAC3E,OAMI,KAAI,CAAC,EAA8D,CACvE,IAAM,EAAS,MAAM,EAAY,EAAM,KAAK,WAAW,EACvD,MAAO,CACL,QAAS,EAAO,GAChB,QAAS,EAAO,GAAK,WAAW,YAAiB,EAAO,QAAU,EAAO,MAC3E,OAMI,QAAO,CAAC,EAA8D,CAC1E,IAAM,EAAS,MAAM,EAAe,EAAM,KAAK,WAAW,EAC1D,MAAO,CACL,QAAS,EAAO,GAChB,QAAS,EAAO,GAAK,WAAW,cAAmB,EAAO,QAAU,EAAO,MAC7E,OAMI,OAAM,CAAC,EAAsC,CACjD,OAAO,GAAiB,EAAM,KAAK,WAAW,OAM1C,OAAM,CAAC,EAA8D,CACzE,IAAM,EAAS,MAAM,EAAc,EAAM,KAAK,WAAW,EACzD,MAAO,CACL,QAAS,EAAO,GAChB,QAAS,EAAO,GAAK,WAAW,YAAiB,EAAO,QAAU,EAAO,MAC3E,OAMI,QAAO,CAAC,EAA8D,CAC1E,IAAM,EAAS,MAAM,EAAe,EAAM,KAAK,WAAW,EAC1D,MAAO,CACL,QAAS,EAAO,GAChB,QAAS,EAAO,GAAK,WAAW,aAAkB,EAAO,QAAU,EAAO,MAC5E,OAMI,OAAM,CAAC,EAAgC,CAC3C,OAAO,GAAc,EAAM,KAAK,WAAW,OAMvC,KAAI,CAAC,EAAc,EAA+C,CACtE,OAAO,GAAe,EAAM,IACvB,KAAK,YACR,MAAO,GAAS,OAAS,IACzB,MAAO,GAAS,KAClB,CAAC,OAMG,KAAI,CAAC,EAAoC,CAC7C,IAAO,EAAc,GAAgB,MAAM,QAAQ,IAAI,CACrD,KAAK,OAAO,CAAI,EAChB,KAAK,OAAO,CAAI,CAClB,CAAC,EAED,MAAO,CACL,OACA,OAAQ,EACR,OAAQ,CACV,OAMI,UAAS,CAAC,EAAgC,CAC9C,IAAM,EAAS,MAAM,KAAK,OAAO,CAAI,EACrC,OAAO,EAAO,QAAU,EAAO,WAAa,eAMxC,eAAc,CAClB,EACA,EACkB,CAClB,IAAM,EAAU,GAAS,SAAW,MAC9B,EAAW,GAAS,UAAY,KAChC,EAAQ,KAAK,IAAI,EAEvB,MAAO,KAAK,IAAI,EAAI,EAAQ,EAAS,CAEnC,GADgB,MAAM,KAAK,UAAU,CAAI,EAC5B,MAAO,GACpB,MAAM,IAAI,QAAQ,CAAC,IAAY,WAAW,EAAS,CAAQ,CAAC,EAG9D,MAAO,GAEX,CAMA,IAAI,EAAwC,KAKrC,SAAS,CAAiB,EAAmB,CAClD,GAAI,CAAC,EACH,EAAiB,IAAI,GAEvB,OAAO,EC/LT,gBAAS,uBACT,qBAAS,gBAAY,YACrB,eAAS,aAAM,cACf,wBAAS,aAwFT,IAAM,GAAkB,MAWjB,MAAM,EAAW,CACd,QAA+B,KAC/B,gBAAkB,IAAI,IAKtB,UAAY,EACZ,OAAS,QAKX,MAAK,EAAkB,CAC3B,GAAI,KAAK,QACP,OAGF,IAAM,EAAa,KAAK,cAAc,EAGtC,GAAI,CACF,GAAW,EAAY,GAAY,IAAI,EACvC,KAAM,CACN,MAAU,MACR,4BAA4B,qDAE9B,EAOF,GAJA,KAAK,QAAU,GAAM,EAAY,CAAC,EAAG,CACnC,MAAO,CAAC,OAAQ,OAAQ,MAAM,CAChC,CAAC,EAEG,CAAC,KAAK,QAAQ,OAAS,CAAC,KAAK,QAAQ,OACvC,MAAU,MAAM,qCAAqC,EAIvD,KAAK,QAAQ,OAAO,GAAG,OAAQ,CAAC,IAAiB,CAC/C,KAAK,QAAU,EAAK,SAAS,OAAO,EACpC,KAAK,cAAc,EACpB,EAGD,KAAK,QAAQ,QAAQ,GAAG,OAAQ,CAAC,IAAiB,CAChD,QAAQ,MAAM,gBAAiB,EAAK,SAAS,OAAO,EAAE,KAAK,CAAC,EAC7D,EAGD,KAAK,QAAQ,GAAG,OAAQ,CAAC,IAAwB,CAC/C,QAAQ,MAAM,gCAAgC,GAAM,EACpD,KAAK,QAAU,KAChB,OAMG,KAAI,EAAkB,CAC1B,GAAI,CAAC,KAAK,QACR,OAIF,GAAI,CACF,MAAM,KAAK,YAAY,WAAY,CAAC,CAAC,EACrC,KAAM,EAQR,GAHA,MAAM,IAAI,QAAQ,CAAC,IAAY,WAAW,EAAS,IAAI,CAAC,EAGpD,KAAK,QACP,KAAK,QAAQ,KAAK,SAAS,EAC3B,KAAK,QAAU,KAIjB,QAAY,EAAI,KAAY,KAAK,gBAC/B,aAAa,EAAQ,OAAO,EAC5B,EAAQ,OAAW,MAAM,iBAAiB,CAAC,EAE7C,KAAK,gBAAgB,MAAM,OAMvB,QAAO,CAAC,EAAqB,EAAyC,CAC1E,OAAO,KAAK,YAAY,UAAW,CAAE,cAAa,SAAQ,CAAC,OAMvD,OAAM,CAAC,EAA6C,CACxD,OAAO,KAAK,YAAY,SAAU,CAAE,aAAY,CAAC,OAM7C,UAAS,EAA6B,CAC1C,OAAO,KAAK,YAAY,YAAa,CAAC,CAAC,OAMnC,KAAI,EAA2B,CACnC,OAAO,KAAK,YAAY,OAAQ,CAAC,CAAC,OAM9B,SAAQ,CAAC,EAA8C,CAC3D,OAAO,KAAK,YAAY,WAAY,CAAE,aAAY,CAAC,OAM/C,OAAM,EAA+B,CACzC,OAAO,KAAK,YAAY,SAAU,CAAC,CAAC,OAMhC,OAAM,CAAC,EAA4C,CACvD,OAAO,KAAK,YAAY,SAAU,CAAE,aAAY,CAAC,OAM7C,MAAK,EAA2B,CACpC,OAAO,KAAK,YAAY,QAAS,CAAC,CAAC,OAM/B,eAAc,EAA0B,CAC5C,OAAO,KAAK,YAAY,QAAS,CAAC,CAAC,OAM/B,iBAAgB,EAAoC,CACxD,OAAO,KAAK,YAAY,gBAAiB,CAAC,CAAC,EAOrC,aAAa,EAAW,CAE9B,IAAM,EAAa,GAAQ,GAAc,YAAY,GAAG,CAAC,EAGnD,EAAQ,CAEZ,EAAK,EAAY,KAAM,OAAQ,SAAU,UAAW,cAAc,EAElE,EAAK,EAAY,KAAM,OAAQ,cAAc,EAE7C,EAAK,EAAY,KAAM,OAAQ,SAAU,2BAA4B,UAAW,cAAc,CAChG,EAEA,QAAW,KAAQ,EACjB,GAAI,CAEF,OADA,GAAW,EAAM,GAAY,IAAI,EAC1B,EACP,KAAM,EAMV,MAAU,MACR;AAAA,EAAkC,EAAM,IAAI,KAAK,OAAO,GAAG,EAAE,KAAK;AAAA,CAAI;AAAA,4EAExE,EAGM,WAAc,CAAC,EAAgB,EAA6C,CAClF,OAAO,IAAI,QAAQ,CAAC,EAAS,IAAW,CACtC,GAAI,CAAC,KAAK,SAAS,MAAO,CACxB,EAAW,MAAM,yBAAyB,CAAC,EAC3C,OAGF,IAAM,EAAK,OAAO,EAAE,KAAK,SAAS,EAC5B,EAA0B,CAC9B,QAAS,MACT,KACA,SACA,QACF,EAGM,EAAU,WAAW,IAAM,CAC/B,KAAK,gBAAgB,OAAO,CAAE,EAC9B,EAAW,MAAM,oBAAoB,GAAQ,CAAC,GAC7C,EAAe,EAGlB,KAAK,gBAAgB,IAAI,EAAI,CAC3B,QAAS,EACT,SACA,SACF,CAAC,EAGD,IAAM,EAAO,KAAK,UAAU,CAAO,EAAI;AAAA,EACvC,KAAK,QAAQ,MAAM,MAAM,EAAM,QAAS,CAAC,IAAkC,CACzE,GAAI,EACF,KAAK,gBAAgB,OAAO,CAAE,EAC9B,aAAa,CAAO,EACpB,EAAO,CAAG,EAEb,EACF,EAGK,aAAa,EAAS,CAC5B,IAAM,EAAQ,KAAK,OAAO,MAAM;AAAA,CAAI,EACpC,KAAK,OAAS,EAAM,IAAI,GAAK,GAE7B,QAAW,KAAQ,EAAO,CACxB,GAAI,CAAC,EAAK,KAAK,EAAG,SAElB,GAAI,CACF,IAAM,EAA4B,KAAK,MAAM,CAAI,EAC3C,EAAU,KAAK,gBAAgB,IAAI,EAAS,EAAE,EAEpD,GAAI,EAIF,GAHA,aAAa,EAAQ,OAAO,EAC5B,KAAK,gBAAgB,OAAO,EAAS,EAAE,EAEnC,EAAS,MACX,EAAQ,OAAW,MAAM,EAAS,MAAM,OAAO,CAAC,EAEhD,OAAQ,QAAQ,EAAS,MAAM,EAGnC,MAAO,EAAK,CACZ,QAAQ,MAAM,4BAA6B,EAAM,CAAG,IAI5D,CAMA,IAAI,EAAmC,KAKhC,SAAS,EAAS,EAAe,CACtC,GAAI,CAAC,EACH,EAAgB,IAAI,GAEtB,OAAO,EAMT,eAAsB,CAAW,EAAwB,CACvD,IAAM,EAAS,GAAU,EAEzB,OADA,MAAM,EAAO,MAAM,EACZ,EAMT,eAAsB,CAAU,EAAkB,CAChD,GAAI,EACF,MAAM,EAAc,KAAK,EACzB,EAAgB,KCzYpB,uBAAS,cAgDF,MAAM,EAAa,CAChB,OAA4B,KAC5B,OAAS,IAAI,IACb,UAAY,KAAK,IAAI,EACrB,KAER,WAAW,CAAC,EAAe,KAAM,CAC/B,KAAK,KAAO,OAMR,MAAK,EAAkB,CAC3B,GAAI,KAAK,OACP,OAGF,OAAO,IAAI,QAAQ,CAAC,EAAS,IAAW,CACtC,KAAK,OAAS,GAAa,CAAC,EAAK,IAAQ,KAAK,cAAc,EAAK,CAAG,CAAC,EAErE,KAAK,OAAO,GAAG,QAAS,CAAM,EAE9B,KAAK,OAAO,OAAO,KAAK,KAAM,IAAM,CAClC,QAAQ,IAAI,mCAAmC,KAAK,MAAM,EAC1D,KAAK,QAAQ,IAAI,QAAS,CAAM,EAChC,EAAQ,EACT,EACF,OAMG,KAAI,EAAkB,CAC1B,GAAI,CAAC,KAAK,OACR,OAGF,OAAO,IAAI,QAAQ,CAAC,IAAY,CAC9B,KAAK,QAAQ,MAAM,IAAM,CACvB,KAAK,OAAS,KACd,EAAQ,EACT,EACF,EAMH,QAAQ,CAAC,EAAc,EAA4B,CACjD,KAAK,OAAO,IAAI,EAAM,CAAK,EAM7B,WAAW,CAAC,EAAoB,CAC9B,KAAK,OAAO,OAAO,CAAI,OAOnB,YAAW,CAAC,EAAoE,CACpF,GAAI,EACF,OAAO,KAAK,iBAAiB,CAAW,EAE1C,OAAO,KAAK,gBAAgB,OAOhB,cAAa,CAAC,EAAsB,EAAoC,CACpF,IAAM,EAAM,EAAI,KAAO,IACjB,EAAS,EAAI,QAAU,MAE7B,GAAI,CACF,GAAI,IAAW,OAAS,IAAQ,UAAW,CACzC,IAAM,EAAS,MAAM,KAAK,gBAAgB,EAC1C,KAAK,SAAS,EAAK,IAAK,CAAM,EACzB,QAAI,IAAW,OAAS,EAAI,WAAW,UAAU,EAAG,CACzD,IAAM,EAAc,EAAI,MAAM,CAAC,EAAE,QAAQ,WAAY,EAAE,EACjD,EAAS,MAAM,KAAK,iBAAiB,CAAW,EACtD,KAAK,SAAS,EAAK,EAAS,IAAM,IAAK,GAAU,CAAE,MAAO,mBAAoB,CAAC,EAC1E,QAAI,IAAW,OAAS,IAAQ,SAAU,CAC/C,IAAM,EAAS,MAAM,KAAK,gBAAgB,EAC1C,KAAK,SAAS,EAAK,EAAO,QAAU,IAAM,IAAK,CAAE,MAAO,EAAO,OAAQ,CAAC,EACnE,QAAI,IAAW,OAAS,IAAQ,QACrC,KAAK,SAAS,EAAK,IAAK,CAAE,MAAO,EAAK,CAAC,EAEvC,UAAK,SAAS,EAAK,IAAK,CAAE,MAAO,WAAY,CAAC,EAEhD,MAAO,EAAO,CACd,QAAQ,MAAM,sBAAuB,CAAK,EAC1C,KAAK,SAAS,EAAK,IAAK,CAAE,MAAO,uBAAwB,CAAC,QAIhD,gBAAe,EAA0B,CACrD,IAAM,EAAS,EAAW,EACpB,EAAiB,EAAkB,EAEnC,EAA4B,CAAC,EAEnC,QAAY,EAAa,KAAc,OAAO,QAAQ,EAAO,QAAQ,EAAG,CACtE,GAAI,CAAC,EAAU,QAAS,SAExB,IAAM,EAAS,MAAM,EAAe,OAAO,EAAU,OAAO,EACtD,EAAU,EAAO,QAAU,EAAO,WAAa,UAErD,EAAS,KAAK,CACZ,KAAM,EAAU,QAChB,UACA,SACA,UAAW,IAAI,KAAK,EAAE,YAAY,CACpC,CAAC,EAIH,IAAM,EAAmD,CAAC,EAC1D,QAAY,EAAM,KAAU,KAAK,OAC/B,GAAI,CACF,EAAc,GAAQ,MAAM,EAAM,EAClC,MAAO,EAAO,CACd,EAAc,GAAQ,CACpB,QAAS,GACT,QAAS,aAAiB,MAAQ,EAAM,QAAU,eACpD,EAOJ,MAAO,CACL,QAJiB,EAAS,MAAM,CAAC,IAAM,EAAE,OAAO,GAChD,OAAO,OAAO,CAAa,EAAE,MAAM,CAAC,IAAM,EAAE,OAAO,EAInD,WACA,OAAQ,KAAK,OAAO,KAAK,IAAI,EAAI,KAAK,WAAa,IAAI,EACvD,UAAW,IAAI,KAAK,EAAE,YAAY,CACpC,OAGY,iBAAgB,CAAC,EAAoD,CACjF,IAAM,EAAiB,EAAkB,EAGzC,GAAI,CADW,MAAM,EAAe,OAAO,CAAW,EAEpD,OAAO,KAGT,IAAM,EAAS,MAAM,EAAe,OAAO,CAAW,EAChD,EAAU,EAAO,QAAU,EAAO,WAAa,UAErD,MAAO,CACL,KAAM,EACN,UACA,SACA,UAAW,IAAI,KAAK,EAAE,YAAY,CACpC,EAGM,QAAQ,CAAC,EAAqB,EAAoB,EAAqB,CAC7E,EAAI,WAAa,EACjB,EAAI,UAAU,eAAgB,kBAAkB,EAChD,EAAI,IAAI,KAAK,UAAU,EAAM,KAAM,CAAC,CAAC,EAEzC,CAMA,IAAI,GAAoC,KA8BjC,SAAS,EAAe,EAAwB,CACrD,OAAO,GLzNT,eAAe,EAAa,CAAC,EAA+B,CAC1D,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,4CAA4C,EAC1D,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAO,EAAK,IACV,OAAM,WAAY,EAAiB,CAAI,EAE/C,GAAI,CAAC,EAAmB,CAAI,EAC1B,QAAQ,MAAM,8DAA8D,EAC5E,QAAQ,KAAK,CAAC,EAGhB,QAAQ,IAAI,cAAc,KAAQ,MAAY,EAE9C,GAAI,CAEF,IAAM,EAAS,MADA,MAAM,EAAY,GACL,QAAQ,EAAM,CAAO,EAEjD,GAAI,EAAO,QAAS,CAElB,GADA,QAAQ,IAAI,0BAA0B,KAAQ,EAAO,SAAS,EAC1D,EAAO,gBACT,QAAQ,IAAI,uBAAuB,EAAO,iBAAiB,EAI7D,EAAoB,EAAM,CACxB,QAAS,EAAO,QAChB,QAAS,EAAK,QAAQ,WAAY,EAAE,CACtC,CAAC,EAGD,IAAM,EAAS,EAAiB,CAAI,EACpC,GAAI,GAAQ,SAAW,EAAO,YAAc,GAAO,CAEjD,IAAM,EAAc,MADT,EAAkB,EACA,MAAM,EAAO,OAAO,EACjD,GAAI,EAAY,QACd,QAAQ,IAAI,aAAa,EAAO,iBAAiB,EAEjD,aAAQ,KAAK,8BAA8B,EAAY,SAAS,GAIpE,aAAQ,MAAM,qBAAqB,MAAS,EAAO,SAAS,EAC5D,QAAQ,KAAK,CAAC,EAEhB,MAAO,EAAO,CACd,QAAQ,MAAM,kBAAmB,CAAK,EACtC,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAIrB,eAAe,EAAY,CAAC,EAA+B,CACzD,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,iCAAiC,EAC/C,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GAEzB,GAAI,CAAC,EAAmB,CAAW,EACjC,QAAQ,MAAM,8DAA8D,EAC5E,QAAQ,KAAK,CAAC,EAGhB,QAAQ,IAAI,YAAY,MAAgB,EAExC,GAAI,CAEF,IAAM,EAAS,MADA,MAAM,EAAY,GACL,OAAO,CAAW,EAE9C,GAAI,EAAO,QAAS,CAElB,GADA,QAAQ,IAAI,wBAAwB,QAAkB,EAAO,SAAS,EAClE,EAAO,gBACT,QAAQ,IAAI,uBAAuB,EAAO,iBAAiB,EAI7D,EAAoB,EAAa,CAC/B,QAAS,EAAO,QAChB,QAAS,EAAY,QAAQ,WAAY,EAAE,CAC7C,CAAC,EAGD,IAAM,EAAK,EAAkB,EACvB,EAAS,EAAiB,CAAW,EAC3C,GAAI,GAAQ,SAEV,IADe,MAAM,EAAG,OAAO,EAAO,OAAO,GAClC,OACT,MAAM,EAAG,QAAQ,EAAO,OAAO,EAC/B,QAAQ,IAAI,aAAa,EAAO,mBAAmB,GAIvD,aAAQ,MAAM,oBAAoB,MAAgB,EAAO,SAAS,EAClE,QAAQ,KAAK,CAAC,EAEhB,MAAO,EAAO,CACd,QAAQ,MAAM,iBAAkB,CAAK,EACrC,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAIrB,eAAe,EAAe,CAAC,EAAgC,CAC7D,QAAQ,IAAI,kCAAkC,EAE9C,GAAI,CAEF,IAAM,EAAU,MADD,MAAM,EAAY,GACJ,UAAU,EAEvC,QAAW,KAAU,EACnB,GAAI,EAAO,QACT,QAAQ,IAAI,WAAW,EAAO,SAAS,EAEvC,aAAQ,MAAM,qBAAqB,EAAO,SAAS,EAGvD,MAAO,EAAO,CACd,QAAQ,MAAM,qBAAsB,CAAK,EACzC,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAIrB,eAAe,EAAU,CAAC,EAAgC,CACxD,QAAQ,IAAI;AAAA,CAAuB,EAEnC,GAAI,CAEF,IAAM,EAAW,MADF,MAAM,EAAY,GACH,KAAK,EAEnC,GAAI,EAAS,SAAW,EAAG,CACzB,QAAQ,IAAI,yBAAyB,EACrC,OAGF,QAAW,KAAO,EAAU,CAC1B,IAAM,EAAS,EAAI,UAAY,YAAc,gBACvC,EAAU,EAAI,QAAU,cAAc,EAAI,WAAa,GAC7D,QAAQ,IAAI,KAAK,EAAI,QAAQ,EAAI,YAAY,KAAU,GAAS,GAElE,MAAO,EAAO,CACd,QAAQ,MAAM,2BAA4B,CAAK,EAC/C,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAIrB,eAAe,EAAc,CAAC,EAA+B,CAC3D,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,mCAAmC,EACjD,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GAEzB,QAAQ,IAAI,gBAAgB,MAAgB,EAE5C,GAAI,CAEF,IAAM,EAAS,MADA,MAAM,EAAY,GACL,SAAS,CAAW,EAEhD,GAAI,EAAO,QAAS,CAClB,QAAQ,IAAI,eAAe,UAAoB,EAAO,qBAAqB,EAAO,iBAAiB,EAGnG,IAAM,EAAK,EAAkB,EACvB,EAAS,EAAiB,CAAW,EAC3C,GAAI,GAAQ,SAEV,IADe,MAAM,EAAG,OAAO,EAAO,OAAO,GAClC,OACT,MAAM,EAAG,QAAQ,EAAO,OAAO,EAC/B,QAAQ,IAAI,aAAa,EAAO,mBAAmB,GAIvD,aAAQ,MAAM,oBAAoB,EAAO,SAAS,EAClD,QAAQ,KAAK,CAAC,EAEhB,MAAO,EAAO,CACd,QAAQ,MAAM,mBAAoB,CAAK,EACvC,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAQrB,eAAe,EAAkB,CAAC,EAA+B,CAC/D,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,qCAAqC,EACnD,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GACnB,EAAK,EAAkB,EAE7B,QAAQ,IAAI,YAAY,MAAgB,EACxC,IAAM,EAAS,MAAM,EAAG,MAAM,CAAW,EAEzC,GAAI,EAAO,QACT,QAAQ,IAAI,WAAW,WAAqB,EAE5C,aAAQ,MAAM,mBAAmB,MAAgB,EAAO,SAAS,EACjE,QAAQ,KAAK,CAAC,EAIlB,eAAe,EAAiB,CAAC,EAA+B,CAC9D,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,oCAAoC,EAClD,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GACnB,EAAK,EAAkB,EAE7B,QAAQ,IAAI,YAAY,MAAgB,EACxC,IAAM,EAAS,MAAM,EAAG,KAAK,CAAW,EAExC,GAAI,EAAO,QACT,QAAQ,IAAI,WAAW,WAAqB,EAE5C,aAAQ,MAAM,kBAAkB,MAAgB,EAAO,SAAS,EAChE,QAAQ,KAAK,CAAC,EAIlB,eAAe,EAAoB,CAAC,EAA+B,CACjE,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,uCAAuC,EACrD,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GACnB,EAAK,EAAkB,EAE7B,QAAQ,IAAI,cAAc,MAAgB,EAC1C,IAAM,EAAS,MAAM,EAAG,QAAQ,CAAW,EAE3C,GAAI,EAAO,QACT,QAAQ,IAAI,WAAW,aAAuB,EAE9C,aAAQ,MAAM,qBAAqB,MAAgB,EAAO,SAAS,EACnE,QAAQ,KAAK,CAAC,EAIlB,eAAe,EAAmB,CAAC,EAA+B,CAChE,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,sCAAsC,EACpD,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GAGnB,EAAO,MAFF,EAAkB,EAEP,KAAK,CAAW,EAEtC,GAAI,CAAC,EAAK,OAAQ,CAChB,QAAQ,IAAI,WAAW,aAAuB,EAC9C,OAGF,QAAQ,IAAI,YAAY,GAAa,EACrC,QAAQ,IAAI,aAAa,EAAK,OAAO,QAAQ,EAC7C,QAAQ,IAAI,aAAa,EAAK,OAAO,QAAQ,EAC7C,QAAQ,IAAI,YAAY,EAAK,OAAO,UAAU,EAC9C,QAAQ,IAAI,UAAU,EAAK,OAAO,SAAW,OAAO,EACpD,QAAQ,IAAI,kBAAkB,EAAK,OAAO,aAAe,OAAO,EAGlE,eAAe,EAAiB,CAAC,EAA+B,CAC9D,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,gDAAgD,EAC9D,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GACnB,EAAa,EAAK,QAAQ,SAAS,EACnC,EAAQ,GAAc,GAAK,EAAK,EAAa,GAC/C,SAAS,EAAK,EAAa,GAAI,EAAE,EACjC,IAGE,EAAO,MADF,EAAkB,EACP,KAAK,EAAa,CAAE,OAAM,CAAC,EAEjD,QAAQ,IAAI,CAAI,EAGlB,eAAe,EAAmB,CAAC,EAA+B,CAChE,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,sCAAsC,EACpD,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GACnB,EAAK,EAAkB,EAE7B,QAAQ,IAAI,YAAY,MAAgB,EACxC,IAAM,EAAS,MAAM,EAAG,OAAO,CAAW,EAE1C,GAAI,EAAO,QACT,QAAQ,IAAI,WAAW,mBAA6B,EAEpD,aAAQ,MAAM,oBAAoB,MAAgB,EAAO,SAAS,EAClE,QAAQ,KAAK,CAAC,EAIlB,eAAe,EAAoB,CAAC,EAA+B,CACjE,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,uCAAuC,EACrD,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GACnB,EAAK,EAAkB,EAE7B,QAAQ,IAAI,aAAa,MAAgB,EACzC,IAAM,EAAS,MAAM,EAAG,QAAQ,CAAW,EAE3C,GAAI,EAAO,QACT,QAAQ,IAAI,WAAW,sBAAgC,EAEvD,aAAQ,MAAM,qBAAqB,MAAgB,EAAO,SAAS,EACnE,QAAQ,KAAK,CAAC,EAQlB,eAAe,EAAY,CAAC,EAA+B,CACzD,IAAM,EAAc,EAAK,GAEnB,EAAe,GAAgB,EACrC,GAAI,CAAC,EACH,QAAQ,MAAM,+BAA+B,EAC7C,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAS,MAAM,EAAa,YAAY,CAAW,EAEzD,GAAI,CAAC,EAAQ,CACX,QAAQ,IAAI,mBAAmB,EAC/B,OAGF,GAAI,aAAc,EAAQ,CAExB,GAAI,EAAO,QACT,QAAQ,IAAI,sBAAsB,EAElC,aAAQ,IAAI,yBAAyB,EAGvC,QAAW,KAAW,EAAO,SAAU,CACrC,IAAM,EAAO,EAAQ,QAAU,KAAO,OACtC,QAAQ,IAAI,MAAM,MAAS,EAAQ,SAAS,EAAQ,OAAO,UAAU,GAElE,KAEL,IAAM,EAAO,EAAO,QAAU,KAAO,OACrC,QAAQ,IAAI,IAAI,MAAS,EAAO,SAAS,EAAO,OAAO,UAAU,GAQrE,eAAe,EAAgB,CAAC,EAAgC,CAC9D,IAAM,EAAS,EAAW,EAE1B,QAAQ,IAAI,sBAAsB,EAClC,QAAQ,IAAI,uCAAuC,EACnD,QAAQ,IAAI,gBAAgB,EAAO,YAAY,EAC/C,QAAQ,IAAI,aAAa,EAAO,SAAS,EACzC,QAAQ,IAAI,cAAc,EAAO,UAAU,EAC3C,QAAQ,IAAI;AAAA,UAAa,EAEzB,IAAM,EAAW,EAAoB,EACrC,GAAI,EAAS,SAAW,EAAG,CACzB,QAAQ,IAAI,0BAA0B,EACtC,OAGF,QAAa,OAAM,OAAQ,KAAe,EAAU,CAGlD,GAFA,QAAQ,IAAI,KAAK,IAAO,EACxB,QAAQ,IAAI,gBAAgB,EAAU,SAAS,EAC3C,EAAU,QACZ,QAAQ,IAAI,gBAAgB,EAAU,SAAS,EAEjD,GAAI,EAAU,YAAc,OAC1B,QAAQ,IAAI,mBAAmB,EAAU,WAAW,GAK1D,eAAe,EAAe,CAAC,EAA+B,CAC5D,GAAI,EAAK,OAAS,EAChB,QAAQ,MAAM,mDAAmD,EACjE,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GACnB,EAAM,EAAK,GACX,EAAQ,EAAK,GAEnB,GAAI,CAAC,EAAmB,CAAW,EACjC,QAAQ,MAAM,8DAA8D,EAC5E,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAS,EAAiB,CAAW,GAAK,CAC9C,QAAS,QACX,EAGA,OAAQ,OACD,UACH,EAAO,QAAU,EACjB,UACG,UACH,EAAO,QAAU,EACjB,UACG,YACH,EAAO,UAAY,IAAU,OAC7B,cAEA,QAAQ,MAAM,uBAAuB,GAAK,EAC1C,QAAQ,MAAM,yCAAyC,EACvD,QAAQ,KAAK,CAAC,EAGlB,EAAoB,EAAa,CAAM,EACvC,QAAQ,IAAI,WAAW,KAAe,OAAS,GAAO,EAOxD,eAAe,EAAY,CAAC,EAA+B,CACzD,GAAI,EAAK,SAAW,EAClB,QAAQ,MAAM,iCAAiC,EAC/C,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GAEzB,GAAI,CAAC,EAAmB,CAAW,EACjC,QAAQ,MAAM,8DAA8D,EAC5E,QAAQ,KAAK,CAAC,EAGhB,QAAQ,IAAI,aAAa,MAAgB,EAEzC,GAAI,CAEF,IAAM,EAAS,MADA,MAAM,EAAY,GACL,OAAO,CAAW,EAK9C,GAHA,QAAQ,IAAI;AAAA,WAAc,EAAO,eAAe,EAAO,SAAS,EAChE,QAAQ,IAAI,aAAa,EAAO,QAAU,QAAU,WAAW,EAC/D,QAAQ,IAAI,kBAAkB,EAAO,WAAa,MAAQ,MAAM,EAC5D,EAAO,SACT,QAAQ,IAAI,eAAe,EAAO,UAAU,EAE9C,QAAQ,IAAI,cAAc,EAAO,SAAS,EAC1C,MAAO,EAAO,CACd,QAAQ,MAAM,uBAAwB,CAAK,EAC3C,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAIrB,eAAe,EAAgB,CAAC,EAA+B,CAC7D,IAAM,EAAa,EAAK,QAAQ,SAAS,EACnC,EAAiB,EAAK,QAAQ,cAAc,EAE9C,EAAY,iBAChB,GAAI,GAAkB,GAAK,EAAK,EAAiB,GAC/C,EAAY,EAAK,EAAiB,GAGpC,IAAM,EAAY,GAAc,GAAK,GAAkB,EAEvD,GAAI,CAEF,IAAM,EAAc,MADL,MAAM,EAAY,GACA,iBAAiB,EAIlD,GAFA,QAAQ,IAAI;AAAA,CAA6B,EAErC,GAAa,GAAW,CAAS,EAAG,CACtC,IAAM,EAAe,GAAa,EAAW,OAAO,EAC9C,EAAW,KAAK,MAAM,CAAY,EAClC,EAAO,IAAK,EAAS,gBAAiB,EAAS,eAAgB,EAG/D,EAAS,IAAI,IACnB,QAAW,KAAO,EAChB,EAAO,IAAI,EAAI,YAAa,EAAI,OAAO,EAIzC,QAAY,EAAM,KAAiB,OAAO,QAAQ,CAAI,EAAG,CACvD,GAAI,CAAC,EAAK,WAAW,UAAU,EAAG,SAElC,IAAM,EAAa,EAAO,IAAI,CAAI,EAC5B,EAAc,EAAwB,QAAQ,SAAU,EAAE,EAEhE,GAAI,EAAY,CACd,GAAI,IAAe,EACjB,QAAQ,IAAI,KAAK,YAAe,UAAmB,aAAsB,EACpE,QAAI,EAAa,EACtB,QAAQ,IAAI,KAAK,YAAe,UAAmB,gBAAyB,EAE5E,aAAQ,IAAI,KAAK,YAAe,UAAmB,kBAA2B,EAEhF,EAAO,OAAO,CAAI,EAElB,aAAQ,IAAI,KAAK,YAAe,sBAA+B,EAKnE,QAAY,EAAM,KAAY,EAC5B,QAAQ,IAAI,KAAK,qCAAwC,GAAS,EAIpE,QAAI,EAAY,SAAW,EACzB,QAAQ,IAAI,gCAAgC,EAE5C,aAAW,KAAO,EAAa,CAC7B,IAAM,EAAW,EAAI,cACjB,MAAM,EAAI,cAAgB,MAAM,QAAQ,CAAC,QACzC,GACJ,QAAQ,IAAI,KAAK,EAAI,eAAe,EAAI,UAAU,GAAU,GAIlE,MAAO,EAAO,CACd,QAAQ,MAAM,6BAA8B,CAAK,EACjD,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAIrB,eAAe,EAAW,CAAC,EAAgC,CACzD,QAAQ,IAAI;AAAA,CAAiC,EAE7C,GAAI,CAEF,IAAM,EAAU,MADD,MAAM,EAAY,GACJ,MAAM,EAEnC,GAAI,EAAQ,SAAW,EAAG,CACxB,QAAQ,IAAI,2BAA2B,EACvC,OAGF,QAAQ,IAAI,SAAS,EAAQ;AAAA,CAA6B,EAE1D,QAAW,KAAQ,EACjB,QAAQ,IAAI,IAAI,EAAK,SAAS,YAAY,MAAM,EAAK,aAAa,EAClE,QAAQ,IAAI,oBAAoB,EAAK,eAAe,EACpD,QAAQ,IAAI,kBAAkB,EAAK,aAAa,EAChD,QAAQ,IAAI,EAAE,EAEhB,MAAO,EAAO,CACd,QAAQ,MAAM,gBAAiB,CAAK,EACpC,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAIrB,eAAe,EAAU,CAAC,EAA+B,CAEvD,MAAM,GAAY,CAAI,EAGxB,eAAe,EAAW,CAAC,EAAgC,CACzD,QAAQ,IAAI;AAAA,CAAiB,EAE7B,GAAI,CAEF,IAAM,EAAQ,MADC,MAAM,EAAY,GACN,eAAe,EAE1C,GAAI,EAAM,SAAW,EAAG,CACtB,QAAQ,IAAI,yBAAyB,EACrC,OAIF,QAAQ,IAAI,0DAA0D,EACtE,QAAQ,IAAI,2DAA2D,EAEvE,QAAW,KAAO,EAAO,CACvB,IAAM,EAAO,EAAI,YAAY,OAAO,EAAE,EAChC,EAAU,EAAI,QAAQ,OAAO,CAAC,EAC9B,GAAU,EAAI,cAAgB,MAAM,QAAQ,CAAC,EAAI,MACjD,EAAQ,EAAI,UAAY,KAAK,EAAI,mBAAqB,GAC5D,QAAQ,IAAI,KAAK,OAAU,OAAa,IAAS,GAAO,GAE1D,MAAO,EAAO,CACd,QAAQ,MAAM,8BAA+B,CAAK,EAClD,QAAQ,KAAK,CAAC,SACd,CACA,MAAM,EAAW,GAQrB,IAAM,GAAsB,CAE1B,CAAE,KAAM,UAAW,YAAa,+BAAgC,MAAO,sCAAuC,QAAS,EAAc,EACrI,CAAE,KAAM,SAAU,YAAa,qCAAsC,MAAO,2BAA4B,QAAS,EAAa,EAC9H,CAAE,KAAM,aAAc,YAAa,8BAA+B,MAAO,qBAAsB,QAAS,EAAgB,EACxH,CAAE,KAAM,OAAQ,YAAa,0BAA2B,MAAO,eAAgB,QAAS,EAAW,EACnG,CAAE,KAAM,WAAY,YAAa,yCAA0C,MAAO,6BAA8B,QAAS,EAAe,EAExI,CAAE,KAAM,QAAS,YAAa,0BAA2B,MAAO,+BAAgC,QAAS,EAAmB,EAC5H,CAAE,KAAM,OAAQ,YAAa,yBAA0B,MAAO,8BAA+B,QAAS,EAAkB,EACxH,CAAE,KAAM,UAAW,YAAa,4BAA6B,MAAO,iCAAkC,QAAS,EAAqB,EACpI,CAAE,KAAM,SAAU,YAAa,qBAAsB,MAAO,gCAAiC,QAAS,EAAoB,EAC1H,CAAE,KAAM,OAAQ,YAAa,oBAAqB,MAAO,0CAA2C,QAAS,EAAkB,EAC/H,CAAE,KAAM,SAAU,YAAa,yBAA0B,MAAO,gCAAiC,QAAS,EAAoB,EAC9H,CAAE,KAAM,UAAW,YAAa,4BAA6B,MAAO,iCAAkC,QAAS,EAAqB,EAEpI,CAAE,KAAM,SAAU,YAAa,+BAAgC,MAAO,2BAA4B,QAAS,EAAa,EAExH,CAAE,KAAM,SAAU,YAAa,qBAAsB,MAAO,sBAAuB,QAAS,EAAiB,EAC7G,CAAE,KAAM,aAAc,YAAa,qBAAsB,MAAO,6CAA8C,QAAS,EAAgB,EAEvI,CAAE,KAAM,SAAU,YAAa,2BAA4B,MAAO,2BAA4B,QAAS,EAAa,EACpH,CAAE,KAAM,cAAe,YAAa,iCAAkC,MAAO,0CAA2C,QAAS,EAAiB,EAClJ,CAAE,KAAM,QAAS,YAAa,4BAA6B,MAAO,gBAAiB,QAAS,EAAY,EACxG,CAAE,KAAM,OAAQ,YAAa,kBAAmB,MAAO,eAAgB,QAAS,EAAW,EAC3F,CAAE,KAAM,QAAS,YAAa,oBAAqB,MAAO,gBAAiB,QAAS,EAAY,CAClG,EAEM,GAAgC,CACpC,CAAE,KAAM,QAAS,YAAa,0BAA2B,MAAO,+BAAgC,QAAS,EAAmB,EAC5H,CAAE,KAAM,OAAQ,YAAa,yBAA0B,MAAO,8BAA+B,QAAS,EAAkB,EACxH,CAAE,KAAM,UAAW,YAAa,4BAA6B,MAAO,iCAAkC,QAAS,EAAqB,EACpI,CAAE,KAAM,SAAU,YAAa,qBAAsB,MAAO,gCAAiC,QAAS,EAAoB,EAC1H,CAAE,KAAM,OAAQ,YAAa,oBAAqB,MAAO,0CAA2C,QAAS,EAAkB,EAC/H,CAAE,KAAM,SAAU,YAAa,yBAA0B,MAAO,gCAAiC,QAAS,EAAoB,EAC9H,CAAE,KAAM,UAAW,YAAa,4BAA6B,MAAO,iCAAkC,QAAS,EAAqB,CACtI,EAEM,GAA+B,CACnC,CAAE,KAAM,OAAQ,YAAa,qBAAsB,MAAO,sBAAuB,QAAS,EAAiB,EAC3G,CAAE,KAAM,MAAO,YAAa,qBAAsB,MAAO,6CAA8C,QAAS,EAAgB,CAClI,EAEA,SAAS,EAAS,EAAS,CACzB,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA+Cb,EAGD,eAAe,EAAI,EAAkB,CACnC,IAAM,EAAO,QAAQ,KAAK,MAAM,CAAC,EAEjC,GAAI,EAAK,SAAW,GAAK,EAAK,KAAO,UAAY,EAAK,KAAO,KAC3D,GAAU,EACV,QAAQ,KAAK,CAAC,EAGhB,GAAI,EAAK,KAAO,aAAe,EAAK,KAAO,KAAM,CAC/C,IAAM,EAAS,EAAW,EAC1B,QAAQ,IAAI,WAAW,EAAO,WAAW,oBAAoB,SAAW,SAAS,EACjF,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAc,EAAK,GACnB,EAAc,EAAK,MAAM,CAAC,EAGhC,GAAI,IAAgB,UAAW,CAC7B,GAAI,EAAY,SAAW,EACzB,QAAQ,MAAM,4BAA4B,EAC1C,QAAQ,MAAM,+EAA+E,EAC7F,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAiB,EAAY,GAC7B,EAAa,GAAgB,KAAK,CAAC,IAAM,EAAE,OAAS,CAAc,EAExE,GAAI,CAAC,EACH,QAAQ,MAAM,+BAA+B,GAAgB,EAC7D,QAAQ,KAAK,CAAC,EAGhB,MAAM,EAAW,QAAQ,EAAY,MAAM,CAAC,CAAC,EAC7C,OAIF,GAAI,IAAgB,SAAU,CAC5B,GAAI,EAAY,SAAW,EACzB,QAAQ,MAAM,2BAA2B,EACzC,QAAQ,MAAM,4CAA4C,EAC1D,QAAQ,KAAK,CAAC,EAGhB,IAAM,EAAiB,EAAY,GAC7B,EAAa,GAAe,KAAK,CAAC,IAAM,EAAE,OAAS,CAAc,EAEvE,GAAI,CAAC,EACH,QAAQ,MAAM,8BAA8B,GAAgB,EAC5D,QAAQ,KAAK,CAAC,EAGhB,MAAM,EAAW,QAAQ,EAAY,MAAM,CAAC,CAAC,EAC7C,OAIF,IAAM,EAAU,GAAS,KAAK,CAAC,IAAM,EAAE,OAAS,CAAW,EAE3D,GAAI,CAAC,EACH,QAAQ,MAAM,oBAAoB,GAAa,EAC/C,QAAQ,MAAM,gCAAgC,EAC9C,QAAQ,KAAK,CAAC,EAGhB,MAAM,EAAQ,QAAQ,CAAW,EAInC,GAAK,EAAE,MAAM,CAAC,IAAU,CACtB,QAAQ,MAAM,eAAgB,CAAK,EACnC,QAAQ,KAAK,CAAC,EACf",
|
|
14
|
-
"debugId": "
|
|
15
|
+
"mappings": "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",
|
|
16
|
+
"debugId": "F69AE2C07BD29FEC64756E2164756E21",
|
|
15
17
|
"names": []
|
|
16
18
|
}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED