cligr 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +12 -0
- package/README.md +65 -0
- package/dist/index.js +94 -0
- package/package.json +26 -0
- package/scripts/build.js +20 -0
- package/scripts/test.js +164 -0
- package/src/commands/config.ts +121 -0
- package/src/commands/down.ts +6 -0
- package/src/commands/groups.ts +68 -0
- package/src/commands/ls.ts +26 -0
- package/src/commands/up.ts +44 -0
- package/src/config/loader.ts +103 -0
- package/src/config/types.ts +20 -0
- package/src/index.ts +96 -0
- package/src/process/manager.ts +199 -0
- package/src/process/template.ts +72 -0
- package/tests/integration/blocking-processes-fixed.test.ts +255 -0
- package/tests/integration/blocking-processes.test.ts +497 -0
- package/tests/integration/commands.test.ts +674 -0
- package/tests/integration/config-loader.test.ts +426 -0
- package/tests/integration/process-manager.test.ts +391 -0
- package/tests/integration/template-expander.test.ts +362 -0
- package/tsconfig.json +15 -0
- package/usage.md +9 -0
package/README.md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Cligr
|
|
2
|
+
|
|
3
|
+
A simple CLI tool for managing groups of concurrent processes.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g Cligri
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Create a `.cligr.yml` configuration file. Cligr looks for the config in:
|
|
14
|
+
|
|
15
|
+
1. **User home directory** (`~/.cligr.yml`) - checked first
|
|
16
|
+
2. **Current directory** (`./.cligr.yml`) - fallback
|
|
17
|
+
|
|
18
|
+
You can keep a global config in your home directory and override it per project.
|
|
19
|
+
|
|
20
|
+
Quick start:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
cligr config # Opens ~/.cligr.yml in your editor
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This creates a config file with examples if it doesn't exist.
|
|
27
|
+
|
|
28
|
+
Example config:
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
tools:
|
|
32
|
+
kubefwd:
|
|
33
|
+
cmd: kubectl port-forward $1 $2:$3
|
|
34
|
+
|
|
35
|
+
groups:
|
|
36
|
+
myapp:
|
|
37
|
+
tool: kubefwd
|
|
38
|
+
restart: yes
|
|
39
|
+
items:
|
|
40
|
+
- service1,8080,80
|
|
41
|
+
- service2,8081,80
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Syntax:**
|
|
45
|
+
- Items are comma-separated: `"name,arg2,arg3"`
|
|
46
|
+
- `$1` = name (first value)
|
|
47
|
+
- `$2`, `$3`... = additional arguments
|
|
48
|
+
- If no `tool` specified, executes directly
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cligr config # Open config file in editor
|
|
54
|
+
cligr up <group> # Start all processes in group
|
|
55
|
+
cligr ls <group> # List group items
|
|
56
|
+
cligr down <group> # Stop group (Ctrl+C also works)
|
|
57
|
+
cligr groups # List all groups
|
|
58
|
+
cligr groups -v # List groups with details
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Restart Policies
|
|
62
|
+
|
|
63
|
+
- `yes` - Always restart on exit
|
|
64
|
+
- `no` - Never restart
|
|
65
|
+
- `unless-stopped` - Restart unless killed by cligr
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import Z from"fs";import En from"os";import U from"path";function Ne(e){return typeof e>"u"||e===null}function On(e){return typeof e=="object"&&e!==null}function Ln(e){return Array.isArray(e)?e:Ne(e)?[]:[e]}function Nn(e,n){var r,o,i,t;if(n)for(t=Object.keys(n),r=0,o=t.length;r<o;r+=1)i=t[r],e[i]=n[i];return e}function Rn(e,n){var r="",o;for(o=0;o<n;o+=1)r+=e;return r}function Pn(e){return e===0&&Number.NEGATIVE_INFINITY===1/e}var Mn=Ne,Dn=On,jn=Ln,Yn=Rn,$n=Pn,Gn=Nn,y={isNothing:Mn,isObject:Dn,toArray:jn,repeat:Yn,isNegativeZero:$n,extend:Gn};function Re(e,n){var r="",o=e.reason||"(unknown reason)";return e.mark?(e.mark.name&&(r+='in "'+e.mark.name+'" '),r+="("+(e.mark.line+1)+":"+(e.mark.column+1)+")",!n&&e.mark.snippet&&(r+=`
|
|
3
|
+
|
|
4
|
+
`+e.mark.snippet),o+" "+r):o}function $(e,n){Error.call(this),this.name="YAMLException",this.reason=e,this.mark=n,this.message=Re(this,!1),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack||""}$.prototype=Object.create(Error.prototype);$.prototype.constructor=$;$.prototype.toString=function(n){return this.name+": "+Re(this,n)};var E=$;function ne(e,n,r,o,i){var t="",l="",u=Math.floor(i/2)-1;return o-n>u&&(t=" ... ",n=o-u+t.length),r-o>u&&(l=" ...",r=o+u-l.length),{str:t+e.slice(n,r).replace(/\t/g,"\u2192")+l,pos:o-n+t.length}}function re(e,n){return y.repeat(" ",n-e.length)+e}function Bn(e,n){if(n=Object.create(n||null),!e.buffer)return null;n.maxLength||(n.maxLength=79),typeof n.indent!="number"&&(n.indent=1),typeof n.linesBefore!="number"&&(n.linesBefore=3),typeof n.linesAfter!="number"&&(n.linesAfter=2);for(var r=/\r?\n|\r|\0/g,o=[0],i=[],t,l=-1;t=r.exec(e.buffer);)i.push(t.index),o.push(t.index+t[0].length),e.position<=t.index&&l<0&&(l=o.length-2);l<0&&(l=o.length-1);var u="",c,f,s=Math.min(e.line+n.linesAfter,i.length).toString().length,a=n.maxLength-(n.indent+s+3);for(c=1;c<=n.linesBefore&&!(l-c<0);c++)f=ne(e.buffer,o[l-c],i[l-c],e.position-(o[l]-o[l-c]),a),u=y.repeat(" ",n.indent)+re((e.line-c+1).toString(),s)+" | "+f.str+`
|
|
5
|
+
`+u;for(f=ne(e.buffer,o[l],i[l],e.position,a),u+=y.repeat(" ",n.indent)+re((e.line+1).toString(),s)+" | "+f.str+`
|
|
6
|
+
`,u+=y.repeat("-",n.indent+s+3+f.pos)+`^
|
|
7
|
+
`,c=1;c<=n.linesAfter&&!(l+c>=i.length);c++)f=ne(e.buffer,o[l+c],i[l+c],e.position-(o[l]-o[l+c]),a),u+=y.repeat(" ",n.indent)+re((e.line+c+1).toString(),s)+" | "+f.str+`
|
|
8
|
+
`;return u.replace(/\n$/,"")}var Hn=Bn,Un=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],Kn=["scalar","sequence","mapping"];function qn(e){var n={};return e!==null&&Object.keys(e).forEach(function(r){e[r].forEach(function(o){n[String(o)]=r})}),n}function Wn(e,n){if(n=n||{},Object.keys(n).forEach(function(r){if(Un.indexOf(r)===-1)throw new E('Unknown option "'+r+'" is met in definition of "'+e+'" YAML type.')}),this.options=n,this.tag=e,this.kind=n.kind||null,this.resolve=n.resolve||function(){return!0},this.construct=n.construct||function(r){return r},this.instanceOf=n.instanceOf||null,this.predicate=n.predicate||null,this.represent=n.represent||null,this.representName=n.representName||null,this.defaultStyle=n.defaultStyle||null,this.multi=n.multi||!1,this.styleAliases=qn(n.styleAliases||null),Kn.indexOf(this.kind)===-1)throw new E('Unknown kind "'+this.kind+'" is specified for "'+e+'" YAML type.')}var C=Wn;function ve(e,n){var r=[];return e[n].forEach(function(o){var i=r.length;r.forEach(function(t,l){t.tag===o.tag&&t.kind===o.kind&&t.multi===o.multi&&(i=l)}),r[i]=o}),r}function Qn(){var e={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}},n,r;function o(i){i.multi?(e.multi[i.kind].push(i),e.multi.fallback.push(i)):e[i.kind][i.tag]=e.fallback[i.tag]=i}for(n=0,r=arguments.length;n<r;n+=1)arguments[n].forEach(o);return e}function oe(e){return this.extend(e)}oe.prototype.extend=function(n){var r=[],o=[];if(n instanceof C)o.push(n);else if(Array.isArray(n))o=o.concat(n);else if(n&&(Array.isArray(n.implicit)||Array.isArray(n.explicit)))n.implicit&&(r=r.concat(n.implicit)),n.explicit&&(o=o.concat(n.explicit));else throw new E("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");r.forEach(function(t){if(!(t instanceof C))throw new E("Specified list of YAML types (or a single Type object) contains a non-Type object.");if(t.loadKind&&t.loadKind!=="scalar")throw new E("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");if(t.multi)throw new E("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.")}),o.forEach(function(t){if(!(t instanceof C))throw new E("Specified list of YAML types (or a single Type object) contains a non-Type object.")});var i=Object.create(oe.prototype);return i.implicit=(this.implicit||[]).concat(r),i.explicit=(this.explicit||[]).concat(o),i.compiledImplicit=ve(i,"implicit"),i.compiledExplicit=ve(i,"explicit"),i.compiledTypeMap=Qn(i.compiledImplicit,i.compiledExplicit),i};var Pe=oe,Me=new C("tag:yaml.org,2002:str",{kind:"scalar",construct:function(e){return e!==null?e:""}}),De=new C("tag:yaml.org,2002:seq",{kind:"sequence",construct:function(e){return e!==null?e:[]}}),je=new C("tag:yaml.org,2002:map",{kind:"mapping",construct:function(e){return e!==null?e:{}}}),Ye=new Pe({explicit:[Me,De,je]});function Vn(e){if(e===null)return!0;var n=e.length;return n===1&&e==="~"||n===4&&(e==="null"||e==="Null"||e==="NULL")}function Xn(){return null}function Zn(e){return e===null}var $e=new C("tag:yaml.org,2002:null",{kind:"scalar",resolve:Vn,construct:Xn,predicate:Zn,represent:{canonical:function(){return"~"},lowercase:function(){return"null"},uppercase:function(){return"NULL"},camelcase:function(){return"Null"},empty:function(){return""}},defaultStyle:"lowercase"});function zn(e){if(e===null)return!1;var n=e.length;return n===4&&(e==="true"||e==="True"||e==="TRUE")||n===5&&(e==="false"||e==="False"||e==="FALSE")}function Jn(e){return e==="true"||e==="True"||e==="TRUE"}function er(e){return Object.prototype.toString.call(e)==="[object Boolean]"}var Ge=new C("tag:yaml.org,2002:bool",{kind:"scalar",resolve:zn,construct:Jn,predicate:er,represent:{lowercase:function(e){return e?"true":"false"},uppercase:function(e){return e?"TRUE":"FALSE"},camelcase:function(e){return e?"True":"False"}},defaultStyle:"lowercase"});function nr(e){return 48<=e&&e<=57||65<=e&&e<=70||97<=e&&e<=102}function rr(e){return 48<=e&&e<=55}function ir(e){return 48<=e&&e<=57}function or(e){if(e===null)return!1;var n=e.length,r=0,o=!1,i;if(!n)return!1;if(i=e[r],(i==="-"||i==="+")&&(i=e[++r]),i==="0"){if(r+1===n)return!0;if(i=e[++r],i==="b"){for(r++;r<n;r++)if(i=e[r],i!=="_"){if(i!=="0"&&i!=="1")return!1;o=!0}return o&&i!=="_"}if(i==="x"){for(r++;r<n;r++)if(i=e[r],i!=="_"){if(!nr(e.charCodeAt(r)))return!1;o=!0}return o&&i!=="_"}if(i==="o"){for(r++;r<n;r++)if(i=e[r],i!=="_"){if(!rr(e.charCodeAt(r)))return!1;o=!0}return o&&i!=="_"}}if(i==="_")return!1;for(;r<n;r++)if(i=e[r],i!=="_"){if(!ir(e.charCodeAt(r)))return!1;o=!0}return!(!o||i==="_")}function lr(e){var n=e,r=1,o;if(n.indexOf("_")!==-1&&(n=n.replace(/_/g,"")),o=n[0],(o==="-"||o==="+")&&(o==="-"&&(r=-1),n=n.slice(1),o=n[0]),n==="0")return 0;if(o==="0"){if(n[1]==="b")return r*parseInt(n.slice(2),2);if(n[1]==="x")return r*parseInt(n.slice(2),16);if(n[1]==="o")return r*parseInt(n.slice(2),8)}return r*parseInt(n,10)}function tr(e){return Object.prototype.toString.call(e)==="[object Number]"&&e%1===0&&!y.isNegativeZero(e)}var Be=new C("tag:yaml.org,2002:int",{kind:"scalar",resolve:or,construct:lr,predicate:tr,represent:{binary:function(e){return e>=0?"0b"+e.toString(2):"-0b"+e.toString(2).slice(1)},octal:function(e){return e>=0?"0o"+e.toString(8):"-0o"+e.toString(8).slice(1)},decimal:function(e){return e.toString(10)},hexadecimal:function(e){return e>=0?"0x"+e.toString(16).toUpperCase():"-0x"+e.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),ur=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function cr(e){return!(e===null||!ur.test(e)||e[e.length-1]==="_")}function fr(e){var n,r;return n=e.replace(/_/g,"").toLowerCase(),r=n[0]==="-"?-1:1,"+-".indexOf(n[0])>=0&&(n=n.slice(1)),n===".inf"?r===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:n===".nan"?NaN:r*parseFloat(n,10)}var ar=/^[-+]?[0-9]+e/;function sr(e,n){var r;if(isNaN(e))switch(n){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===e)switch(n){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===e)switch(n){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(y.isNegativeZero(e))return"-0.0";return r=e.toString(10),ar.test(r)?r.replace("e",".e"):r}function pr(e){return Object.prototype.toString.call(e)==="[object Number]"&&(e%1!==0||y.isNegativeZero(e))}var He=new C("tag:yaml.org,2002:float",{kind:"scalar",resolve:cr,construct:fr,predicate:pr,represent:sr,defaultStyle:"lowercase"}),Ue=Ye.extend({implicit:[$e,Ge,Be,He]}),Ke=Ue,qe=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),We=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function hr(e){return e===null?!1:qe.exec(e)!==null||We.exec(e)!==null}function dr(e){var n,r,o,i,t,l,u,c=0,f=null,s,a,h;if(n=qe.exec(e),n===null&&(n=We.exec(e)),n===null)throw new Error("Date resolve error");if(r=+n[1],o=+n[2]-1,i=+n[3],!n[4])return new Date(Date.UTC(r,o,i));if(t=+n[4],l=+n[5],u=+n[6],n[7]){for(c=n[7].slice(0,3);c.length<3;)c+="0";c=+c}return n[9]&&(s=+n[10],a=+(n[11]||0),f=(s*60+a)*6e4,n[9]==="-"&&(f=-f)),h=new Date(Date.UTC(r,o,i,t,l,u,c)),f&&h.setTime(h.getTime()-f),h}function mr(e){return e.toISOString()}var Qe=new C("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:hr,construct:dr,instanceOf:Date,represent:mr});function gr(e){return e==="<<"||e===null}var Ve=new C("tag:yaml.org,2002:merge",{kind:"scalar",resolve:gr}),fe=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
|
|
9
|
+
\r`;function xr(e){if(e===null)return!1;var n,r,o=0,i=e.length,t=fe;for(r=0;r<i;r++)if(n=t.indexOf(e.charAt(r)),!(n>64)){if(n<0)return!1;o+=6}return o%8===0}function vr(e){var n,r,o=e.replace(/[\r\n=]/g,""),i=o.length,t=fe,l=0,u=[];for(n=0;n<i;n++)n%4===0&&n&&(u.push(l>>16&255),u.push(l>>8&255),u.push(l&255)),l=l<<6|t.indexOf(o.charAt(n));return r=i%4*6,r===0?(u.push(l>>16&255),u.push(l>>8&255),u.push(l&255)):r===18?(u.push(l>>10&255),u.push(l>>2&255)):r===12&&u.push(l>>4&255),new Uint8Array(u)}function Ar(e){var n="",r=0,o,i,t=e.length,l=fe;for(o=0;o<t;o++)o%3===0&&o&&(n+=l[r>>18&63],n+=l[r>>12&63],n+=l[r>>6&63],n+=l[r&63]),r=(r<<8)+e[o];return i=t%3,i===0?(n+=l[r>>18&63],n+=l[r>>12&63],n+=l[r>>6&63],n+=l[r&63]):i===2?(n+=l[r>>10&63],n+=l[r>>4&63],n+=l[r<<2&63],n+=l[64]):i===1&&(n+=l[r>>2&63],n+=l[r<<4&63],n+=l[64],n+=l[64]),n}function yr(e){return Object.prototype.toString.call(e)==="[object Uint8Array]"}var Xe=new C("tag:yaml.org,2002:binary",{kind:"scalar",resolve:xr,construct:vr,predicate:yr,represent:Ar}),Cr=Object.prototype.hasOwnProperty,wr=Object.prototype.toString;function Er(e){if(e===null)return!0;var n=[],r,o,i,t,l,u=e;for(r=0,o=u.length;r<o;r+=1){if(i=u[r],l=!1,wr.call(i)!=="[object Object]")return!1;for(t in i)if(Cr.call(i,t))if(!l)l=!0;else return!1;if(!l)return!1;if(n.indexOf(t)===-1)n.push(t);else return!1}return!0}function Sr(e){return e!==null?e:[]}var Ze=new C("tag:yaml.org,2002:omap",{kind:"sequence",resolve:Er,construct:Sr}),_r=Object.prototype.toString;function br(e){if(e===null)return!0;var n,r,o,i,t,l=e;for(t=new Array(l.length),n=0,r=l.length;n<r;n+=1){if(o=l[n],_r.call(o)!=="[object Object]"||(i=Object.keys(o),i.length!==1))return!1;t[n]=[i[0],o[i[0]]]}return!0}function Tr(e){if(e===null)return[];var n,r,o,i,t,l=e;for(t=new Array(l.length),n=0,r=l.length;n<r;n+=1)o=l[n],i=Object.keys(o),t[n]=[i[0],o[i[0]]];return t}var ze=new C("tag:yaml.org,2002:pairs",{kind:"sequence",resolve:br,construct:Tr}),Ir=Object.prototype.hasOwnProperty;function Fr(e){if(e===null)return!0;var n,r=e;for(n in r)if(Ir.call(r,n)&&r[n]!==null)return!1;return!0}function kr(e){return e!==null?e:{}}var Je=new C("tag:yaml.org,2002:set",{kind:"mapping",resolve:Fr,construct:kr}),ae=Ke.extend({implicit:[Qe,Ve],explicit:[Xe,Ze,ze,Je]}),F=Object.prototype.hasOwnProperty,K=1,en=2,nn=3,q=4,ie=1,Or=2,Ae=3,Lr=/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/,Nr=/[\x85\u2028\u2029]/,Rr=/[,\[\]\{\}]/,rn=/^(?:!|!!|![a-z\-]+!)$/i,on=/^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;function ye(e){return Object.prototype.toString.call(e)}function b(e){return e===10||e===13}function L(e){return e===9||e===32}function S(e){return e===9||e===32||e===10||e===13}function P(e){return e===44||e===91||e===93||e===123||e===125}function Pr(e){var n;return 48<=e&&e<=57?e-48:(n=e|32,97<=n&&n<=102?n-97+10:-1)}function Mr(e){return e===120?2:e===117?4:e===85?8:0}function Dr(e){return 48<=e&&e<=57?e-48:-1}function Ce(e){return e===48?"\0":e===97?"\x07":e===98?"\b":e===116||e===9?" ":e===110?`
|
|
10
|
+
`:e===118?"\v":e===102?"\f":e===114?"\r":e===101?"\x1B":e===32?" ":e===34?'"':e===47?"/":e===92?"\\":e===78?"\x85":e===95?"\xA0":e===76?"\u2028":e===80?"\u2029":""}function jr(e){return e<=65535?String.fromCharCode(e):String.fromCharCode((e-65536>>10)+55296,(e-65536&1023)+56320)}function ln(e,n,r){n==="__proto__"?Object.defineProperty(e,n,{configurable:!0,enumerable:!0,writable:!0,value:r}):e[n]=r}var tn=new Array(256),un=new Array(256);for(O=0;O<256;O++)tn[O]=Ce(O)?1:0,un[O]=Ce(O);var O;function Yr(e,n){this.input=e,this.filename=n.filename||null,this.schema=n.schema||ae,this.onWarning=n.onWarning||null,this.legacy=n.legacy||!1,this.json=n.json||!1,this.listener=n.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=e.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function cn(e,n){var r={name:e.filename,buffer:e.input.slice(0,-1),position:e.position,line:e.line,column:e.position-e.lineStart};return r.snippet=Hn(r),new E(n,r)}function p(e,n){throw cn(e,n)}function W(e,n){e.onWarning&&e.onWarning.call(null,cn(e,n))}var we={YAML:function(n,r,o){var i,t,l;n.version!==null&&p(n,"duplication of %YAML directive"),o.length!==1&&p(n,"YAML directive accepts exactly one argument"),i=/^([0-9]+)\.([0-9]+)$/.exec(o[0]),i===null&&p(n,"ill-formed argument of the YAML directive"),t=parseInt(i[1],10),l=parseInt(i[2],10),t!==1&&p(n,"unacceptable YAML version of the document"),n.version=o[0],n.checkLineBreaks=l<2,l!==1&&l!==2&&W(n,"unsupported YAML version of the document")},TAG:function(n,r,o){var i,t;o.length!==2&&p(n,"TAG directive accepts exactly two arguments"),i=o[0],t=o[1],rn.test(i)||p(n,"ill-formed tag handle (first argument) of the TAG directive"),F.call(n.tagMap,i)&&p(n,'there is a previously declared suffix for "'+i+'" tag handle'),on.test(t)||p(n,"ill-formed tag prefix (second argument) of the TAG directive");try{t=decodeURIComponent(t)}catch{p(n,"tag prefix is malformed: "+t)}n.tagMap[i]=t}};function I(e,n,r,o){var i,t,l,u;if(n<r){if(u=e.input.slice(n,r),o)for(i=0,t=u.length;i<t;i+=1)l=u.charCodeAt(i),l===9||32<=l&&l<=1114111||p(e,"expected valid JSON character");else Lr.test(u)&&p(e,"the stream contains non-printable characters");e.result+=u}}function Ee(e,n,r,o){var i,t,l,u;for(y.isObject(r)||p(e,"cannot merge mappings; the provided source object is unacceptable"),i=Object.keys(r),l=0,u=i.length;l<u;l+=1)t=i[l],F.call(n,t)||(ln(n,t,r[t]),o[t]=!0)}function M(e,n,r,o,i,t,l,u,c){var f,s;if(Array.isArray(i))for(i=Array.prototype.slice.call(i),f=0,s=i.length;f<s;f+=1)Array.isArray(i[f])&&p(e,"nested arrays are not supported inside keys"),typeof i=="object"&&ye(i[f])==="[object Object]"&&(i[f]="[object Object]");if(typeof i=="object"&&ye(i)==="[object Object]"&&(i="[object Object]"),i=String(i),n===null&&(n={}),o==="tag:yaml.org,2002:merge")if(Array.isArray(t))for(f=0,s=t.length;f<s;f+=1)Ee(e,n,t[f],r);else Ee(e,n,t,r);else!e.json&&!F.call(r,i)&&F.call(n,i)&&(e.line=l||e.line,e.lineStart=u||e.lineStart,e.position=c||e.position,p(e,"duplicated mapping key")),ln(n,i,t),delete r[i];return n}function se(e){var n;n=e.input.charCodeAt(e.position),n===10?e.position++:n===13?(e.position++,e.input.charCodeAt(e.position)===10&&e.position++):p(e,"a line break is expected"),e.line+=1,e.lineStart=e.position,e.firstTabInLine=-1}function A(e,n,r){for(var o=0,i=e.input.charCodeAt(e.position);i!==0;){for(;L(i);)i===9&&e.firstTabInLine===-1&&(e.firstTabInLine=e.position),i=e.input.charCodeAt(++e.position);if(n&&i===35)do i=e.input.charCodeAt(++e.position);while(i!==10&&i!==13&&i!==0);if(b(i))for(se(e),i=e.input.charCodeAt(e.position),o++,e.lineIndent=0;i===32;)e.lineIndent++,i=e.input.charCodeAt(++e.position);else break}return r!==-1&&o!==0&&e.lineIndent<r&&W(e,"deficient indentation"),o}function X(e){var n=e.position,r;return r=e.input.charCodeAt(n),!!((r===45||r===46)&&r===e.input.charCodeAt(n+1)&&r===e.input.charCodeAt(n+2)&&(n+=3,r=e.input.charCodeAt(n),r===0||S(r)))}function pe(e,n){n===1?e.result+=" ":n>1&&(e.result+=y.repeat(`
|
|
11
|
+
`,n-1))}function $r(e,n,r){var o,i,t,l,u,c,f,s,a=e.kind,h=e.result,d;if(d=e.input.charCodeAt(e.position),S(d)||P(d)||d===35||d===38||d===42||d===33||d===124||d===62||d===39||d===34||d===37||d===64||d===96||(d===63||d===45)&&(i=e.input.charCodeAt(e.position+1),S(i)||r&&P(i)))return!1;for(e.kind="scalar",e.result="",t=l=e.position,u=!1;d!==0;){if(d===58){if(i=e.input.charCodeAt(e.position+1),S(i)||r&&P(i))break}else if(d===35){if(o=e.input.charCodeAt(e.position-1),S(o))break}else{if(e.position===e.lineStart&&X(e)||r&&P(d))break;if(b(d))if(c=e.line,f=e.lineStart,s=e.lineIndent,A(e,!1,-1),e.lineIndent>=n){u=!0,d=e.input.charCodeAt(e.position);continue}else{e.position=l,e.line=c,e.lineStart=f,e.lineIndent=s;break}}u&&(I(e,t,l,!1),pe(e,e.line-c),t=l=e.position,u=!1),L(d)||(l=e.position+1),d=e.input.charCodeAt(++e.position)}return I(e,t,l,!1),e.result?!0:(e.kind=a,e.result=h,!1)}function Gr(e,n){var r,o,i;if(r=e.input.charCodeAt(e.position),r!==39)return!1;for(e.kind="scalar",e.result="",e.position++,o=i=e.position;(r=e.input.charCodeAt(e.position))!==0;)if(r===39)if(I(e,o,e.position,!0),r=e.input.charCodeAt(++e.position),r===39)o=e.position,e.position++,i=e.position;else return!0;else b(r)?(I(e,o,i,!0),pe(e,A(e,!1,n)),o=i=e.position):e.position===e.lineStart&&X(e)?p(e,"unexpected end of the document within a single quoted scalar"):(e.position++,i=e.position);p(e,"unexpected end of the stream within a single quoted scalar")}function Br(e,n){var r,o,i,t,l,u;if(u=e.input.charCodeAt(e.position),u!==34)return!1;for(e.kind="scalar",e.result="",e.position++,r=o=e.position;(u=e.input.charCodeAt(e.position))!==0;){if(u===34)return I(e,r,e.position,!0),e.position++,!0;if(u===92){if(I(e,r,e.position,!0),u=e.input.charCodeAt(++e.position),b(u))A(e,!1,n);else if(u<256&&tn[u])e.result+=un[u],e.position++;else if((l=Mr(u))>0){for(i=l,t=0;i>0;i--)u=e.input.charCodeAt(++e.position),(l=Pr(u))>=0?t=(t<<4)+l:p(e,"expected hexadecimal character");e.result+=jr(t),e.position++}else p(e,"unknown escape sequence");r=o=e.position}else b(u)?(I(e,r,o,!0),pe(e,A(e,!1,n)),r=o=e.position):e.position===e.lineStart&&X(e)?p(e,"unexpected end of the document within a double quoted scalar"):(e.position++,o=e.position)}p(e,"unexpected end of the stream within a double quoted scalar")}function Hr(e,n){var r=!0,o,i,t,l=e.tag,u,c=e.anchor,f,s,a,h,d,m=Object.create(null),x,v,_,g;if(g=e.input.charCodeAt(e.position),g===91)s=93,d=!1,u=[];else if(g===123)s=125,d=!0,u={};else return!1;for(e.anchor!==null&&(e.anchorMap[e.anchor]=u),g=e.input.charCodeAt(++e.position);g!==0;){if(A(e,!0,n),g=e.input.charCodeAt(e.position),g===s)return e.position++,e.tag=l,e.anchor=c,e.kind=d?"mapping":"sequence",e.result=u,!0;r?g===44&&p(e,"expected the node content, but found ','"):p(e,"missed comma between flow collection entries"),v=x=_=null,a=h=!1,g===63&&(f=e.input.charCodeAt(e.position+1),S(f)&&(a=h=!0,e.position++,A(e,!0,n))),o=e.line,i=e.lineStart,t=e.position,D(e,n,K,!1,!0),v=e.tag,x=e.result,A(e,!0,n),g=e.input.charCodeAt(e.position),(h||e.line===o)&&g===58&&(a=!0,g=e.input.charCodeAt(++e.position),A(e,!0,n),D(e,n,K,!1,!0),_=e.result),d?M(e,u,m,v,x,_,o,i,t):a?u.push(M(e,null,m,v,x,_,o,i,t)):u.push(x),A(e,!0,n),g=e.input.charCodeAt(e.position),g===44?(r=!0,g=e.input.charCodeAt(++e.position)):r=!1}p(e,"unexpected end of the stream within a flow collection")}function Ur(e,n){var r,o,i=ie,t=!1,l=!1,u=n,c=0,f=!1,s,a;if(a=e.input.charCodeAt(e.position),a===124)o=!1;else if(a===62)o=!0;else return!1;for(e.kind="scalar",e.result="";a!==0;)if(a=e.input.charCodeAt(++e.position),a===43||a===45)ie===i?i=a===43?Ae:Or:p(e,"repeat of a chomping mode identifier");else if((s=Dr(a))>=0)s===0?p(e,"bad explicit indentation width of a block scalar; it cannot be less than one"):l?p(e,"repeat of an indentation width identifier"):(u=n+s-1,l=!0);else break;if(L(a)){do a=e.input.charCodeAt(++e.position);while(L(a));if(a===35)do a=e.input.charCodeAt(++e.position);while(!b(a)&&a!==0)}for(;a!==0;){for(se(e),e.lineIndent=0,a=e.input.charCodeAt(e.position);(!l||e.lineIndent<u)&&a===32;)e.lineIndent++,a=e.input.charCodeAt(++e.position);if(!l&&e.lineIndent>u&&(u=e.lineIndent),b(a)){c++;continue}if(e.lineIndent<u){i===Ae?e.result+=y.repeat(`
|
|
12
|
+
`,t?1+c:c):i===ie&&t&&(e.result+=`
|
|
13
|
+
`);break}for(o?L(a)?(f=!0,e.result+=y.repeat(`
|
|
14
|
+
`,t?1+c:c)):f?(f=!1,e.result+=y.repeat(`
|
|
15
|
+
`,c+1)):c===0?t&&(e.result+=" "):e.result+=y.repeat(`
|
|
16
|
+
`,c):e.result+=y.repeat(`
|
|
17
|
+
`,t?1+c:c),t=!0,l=!0,c=0,r=e.position;!b(a)&&a!==0;)a=e.input.charCodeAt(++e.position);I(e,r,e.position,!1)}return!0}function Se(e,n){var r,o=e.tag,i=e.anchor,t=[],l,u=!1,c;if(e.firstTabInLine!==-1)return!1;for(e.anchor!==null&&(e.anchorMap[e.anchor]=t),c=e.input.charCodeAt(e.position);c!==0&&(e.firstTabInLine!==-1&&(e.position=e.firstTabInLine,p(e,"tab characters must not be used in indentation")),!(c!==45||(l=e.input.charCodeAt(e.position+1),!S(l))));){if(u=!0,e.position++,A(e,!0,-1)&&e.lineIndent<=n){t.push(null),c=e.input.charCodeAt(e.position);continue}if(r=e.line,D(e,n,nn,!1,!0),t.push(e.result),A(e,!0,-1),c=e.input.charCodeAt(e.position),(e.line===r||e.lineIndent>n)&&c!==0)p(e,"bad indentation of a sequence entry");else if(e.lineIndent<n)break}return u?(e.tag=o,e.anchor=i,e.kind="sequence",e.result=t,!0):!1}function Kr(e,n,r){var o,i,t,l,u,c,f=e.tag,s=e.anchor,a={},h=Object.create(null),d=null,m=null,x=null,v=!1,_=!1,g;if(e.firstTabInLine!==-1)return!1;for(e.anchor!==null&&(e.anchorMap[e.anchor]=a),g=e.input.charCodeAt(e.position);g!==0;){if(!v&&e.firstTabInLine!==-1&&(e.position=e.firstTabInLine,p(e,"tab characters must not be used in indentation")),o=e.input.charCodeAt(e.position+1),t=e.line,(g===63||g===58)&&S(o))g===63?(v&&(M(e,a,h,d,m,null,l,u,c),d=m=x=null),_=!0,v=!0,i=!0):v?(v=!1,i=!0):p(e,"incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line"),e.position+=1,g=o;else{if(l=e.line,u=e.lineStart,c=e.position,!D(e,r,en,!1,!0))break;if(e.line===t){for(g=e.input.charCodeAt(e.position);L(g);)g=e.input.charCodeAt(++e.position);if(g===58)g=e.input.charCodeAt(++e.position),S(g)||p(e,"a whitespace character is expected after the key-value separator within a block mapping"),v&&(M(e,a,h,d,m,null,l,u,c),d=m=x=null),_=!0,v=!1,i=!1,d=e.tag,m=e.result;else if(_)p(e,"can not read an implicit mapping pair; a colon is missed");else return e.tag=f,e.anchor=s,!0}else if(_)p(e,"can not read a block mapping entry; a multiline key may not be an implicit key");else return e.tag=f,e.anchor=s,!0}if((e.line===t||e.lineIndent>n)&&(v&&(l=e.line,u=e.lineStart,c=e.position),D(e,n,q,!0,i)&&(v?m=e.result:x=e.result),v||(M(e,a,h,d,m,x,l,u,c),d=m=x=null),A(e,!0,-1),g=e.input.charCodeAt(e.position)),(e.line===t||e.lineIndent>n)&&g!==0)p(e,"bad indentation of a mapping entry");else if(e.lineIndent<n)break}return v&&M(e,a,h,d,m,null,l,u,c),_&&(e.tag=f,e.anchor=s,e.kind="mapping",e.result=a),_}function qr(e){var n,r=!1,o=!1,i,t,l;if(l=e.input.charCodeAt(e.position),l!==33)return!1;if(e.tag!==null&&p(e,"duplication of a tag property"),l=e.input.charCodeAt(++e.position),l===60?(r=!0,l=e.input.charCodeAt(++e.position)):l===33?(o=!0,i="!!",l=e.input.charCodeAt(++e.position)):i="!",n=e.position,r){do l=e.input.charCodeAt(++e.position);while(l!==0&&l!==62);e.position<e.length?(t=e.input.slice(n,e.position),l=e.input.charCodeAt(++e.position)):p(e,"unexpected end of the stream within a verbatim tag")}else{for(;l!==0&&!S(l);)l===33&&(o?p(e,"tag suffix cannot contain exclamation marks"):(i=e.input.slice(n-1,e.position+1),rn.test(i)||p(e,"named tag handle cannot contain such characters"),o=!0,n=e.position+1)),l=e.input.charCodeAt(++e.position);t=e.input.slice(n,e.position),Rr.test(t)&&p(e,"tag suffix cannot contain flow indicator characters")}t&&!on.test(t)&&p(e,"tag name cannot contain such characters: "+t);try{t=decodeURIComponent(t)}catch{p(e,"tag name is malformed: "+t)}return r?e.tag=t:F.call(e.tagMap,i)?e.tag=e.tagMap[i]+t:i==="!"?e.tag="!"+t:i==="!!"?e.tag="tag:yaml.org,2002:"+t:p(e,'undeclared tag handle "'+i+'"'),!0}function Wr(e){var n,r;if(r=e.input.charCodeAt(e.position),r!==38)return!1;for(e.anchor!==null&&p(e,"duplication of an anchor property"),r=e.input.charCodeAt(++e.position),n=e.position;r!==0&&!S(r)&&!P(r);)r=e.input.charCodeAt(++e.position);return e.position===n&&p(e,"name of an anchor node must contain at least one character"),e.anchor=e.input.slice(n,e.position),!0}function Qr(e){var n,r,o;if(o=e.input.charCodeAt(e.position),o!==42)return!1;for(o=e.input.charCodeAt(++e.position),n=e.position;o!==0&&!S(o)&&!P(o);)o=e.input.charCodeAt(++e.position);return e.position===n&&p(e,"name of an alias node must contain at least one character"),r=e.input.slice(n,e.position),F.call(e.anchorMap,r)||p(e,'unidentified alias "'+r+'"'),e.result=e.anchorMap[r],A(e,!0,-1),!0}function D(e,n,r,o,i){var t,l,u,c=1,f=!1,s=!1,a,h,d,m,x,v;if(e.listener!==null&&e.listener("open",e),e.tag=null,e.anchor=null,e.kind=null,e.result=null,t=l=u=q===r||nn===r,o&&A(e,!0,-1)&&(f=!0,e.lineIndent>n?c=1:e.lineIndent===n?c=0:e.lineIndent<n&&(c=-1)),c===1)for(;qr(e)||Wr(e);)A(e,!0,-1)?(f=!0,u=t,e.lineIndent>n?c=1:e.lineIndent===n?c=0:e.lineIndent<n&&(c=-1)):u=!1;if(u&&(u=f||i),(c===1||q===r)&&(K===r||en===r?x=n:x=n+1,v=e.position-e.lineStart,c===1?u&&(Se(e,v)||Kr(e,v,x))||Hr(e,x)?s=!0:(l&&Ur(e,x)||Gr(e,x)||Br(e,x)?s=!0:Qr(e)?(s=!0,(e.tag!==null||e.anchor!==null)&&p(e,"alias node should not have any properties")):$r(e,x,K===r)&&(s=!0,e.tag===null&&(e.tag="?")),e.anchor!==null&&(e.anchorMap[e.anchor]=e.result)):c===0&&(s=u&&Se(e,v))),e.tag===null)e.anchor!==null&&(e.anchorMap[e.anchor]=e.result);else if(e.tag==="?"){for(e.result!==null&&e.kind!=="scalar"&&p(e,'unacceptable node kind for !<?> tag; it should be "scalar", not "'+e.kind+'"'),a=0,h=e.implicitTypes.length;a<h;a+=1)if(m=e.implicitTypes[a],m.resolve(e.result)){e.result=m.construct(e.result),e.tag=m.tag,e.anchor!==null&&(e.anchorMap[e.anchor]=e.result);break}}else if(e.tag!=="!"){if(F.call(e.typeMap[e.kind||"fallback"],e.tag))m=e.typeMap[e.kind||"fallback"][e.tag];else for(m=null,d=e.typeMap.multi[e.kind||"fallback"],a=0,h=d.length;a<h;a+=1)if(e.tag.slice(0,d[a].tag.length)===d[a].tag){m=d[a];break}m||p(e,"unknown tag !<"+e.tag+">"),e.result!==null&&m.kind!==e.kind&&p(e,"unacceptable node kind for !<"+e.tag+'> tag; it should be "'+m.kind+'", not "'+e.kind+'"'),m.resolve(e.result,e.tag)?(e.result=m.construct(e.result,e.tag),e.anchor!==null&&(e.anchorMap[e.anchor]=e.result)):p(e,"cannot resolve a node with !<"+e.tag+"> explicit tag")}return e.listener!==null&&e.listener("close",e),e.tag!==null||e.anchor!==null||s}function Vr(e){var n=e.position,r,o,i,t=!1,l;for(e.version=null,e.checkLineBreaks=e.legacy,e.tagMap=Object.create(null),e.anchorMap=Object.create(null);(l=e.input.charCodeAt(e.position))!==0&&(A(e,!0,-1),l=e.input.charCodeAt(e.position),!(e.lineIndent>0||l!==37));){for(t=!0,l=e.input.charCodeAt(++e.position),r=e.position;l!==0&&!S(l);)l=e.input.charCodeAt(++e.position);for(o=e.input.slice(r,e.position),i=[],o.length<1&&p(e,"directive name must not be less than one character in length");l!==0;){for(;L(l);)l=e.input.charCodeAt(++e.position);if(l===35){do l=e.input.charCodeAt(++e.position);while(l!==0&&!b(l));break}if(b(l))break;for(r=e.position;l!==0&&!S(l);)l=e.input.charCodeAt(++e.position);i.push(e.input.slice(r,e.position))}l!==0&&se(e),F.call(we,o)?we[o](e,o,i):W(e,'unknown document directive "'+o+'"')}if(A(e,!0,-1),e.lineIndent===0&&e.input.charCodeAt(e.position)===45&&e.input.charCodeAt(e.position+1)===45&&e.input.charCodeAt(e.position+2)===45?(e.position+=3,A(e,!0,-1)):t&&p(e,"directives end mark is expected"),D(e,e.lineIndent-1,q,!1,!0),A(e,!0,-1),e.checkLineBreaks&&Nr.test(e.input.slice(n,e.position))&&W(e,"non-ASCII line breaks are interpreted as content"),e.documents.push(e.result),e.position===e.lineStart&&X(e)){e.input.charCodeAt(e.position)===46&&(e.position+=3,A(e,!0,-1));return}if(e.position<e.length-1)p(e,"end of the stream or a document separator is expected");else return}function fn(e,n){e=String(e),n=n||{},e.length!==0&&(e.charCodeAt(e.length-1)!==10&&e.charCodeAt(e.length-1)!==13&&(e+=`
|
|
18
|
+
`),e.charCodeAt(0)===65279&&(e=e.slice(1)));var r=new Yr(e,n),o=e.indexOf("\0");for(o!==-1&&(r.position=o,p(r,"null byte is not allowed in input")),r.input+="\0";r.input.charCodeAt(r.position)===32;)r.lineIndent+=1,r.position+=1;for(;r.position<r.length-1;)Vr(r);return r.documents}function Xr(e,n,r){n!==null&&typeof n=="object"&&typeof r>"u"&&(r=n,n=null);var o=fn(e,r);if(typeof n!="function")return o;for(var i=0,t=o.length;i<t;i+=1)n(o[i])}function Zr(e,n){var r=fn(e,n);if(r.length!==0){if(r.length===1)return r[0];throw new E("expected a single document in the stream, but found more")}}var zr=Xr,Jr=Zr,an={loadAll:zr,load:Jr},sn=Object.prototype.toString,pn=Object.prototype.hasOwnProperty,he=65279,ei=9,G=10,ni=13,ri=32,ii=33,oi=34,le=35,li=37,ti=38,ui=39,ci=42,hn=44,fi=45,Q=58,ai=61,si=62,pi=63,hi=64,dn=91,mn=93,di=96,gn=123,mi=124,xn=125,w={};w[0]="\\0";w[7]="\\a";w[8]="\\b";w[9]="\\t";w[10]="\\n";w[11]="\\v";w[12]="\\f";w[13]="\\r";w[27]="\\e";w[34]='\\"';w[92]="\\\\";w[133]="\\N";w[160]="\\_";w[8232]="\\L";w[8233]="\\P";var gi=["y","Y","yes","Yes","YES","on","On","ON","n","N","no","No","NO","off","Off","OFF"],xi=/^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;function vi(e,n){var r,o,i,t,l,u,c;if(n===null)return{};for(r={},o=Object.keys(n),i=0,t=o.length;i<t;i+=1)l=o[i],u=String(n[l]),l.slice(0,2)==="!!"&&(l="tag:yaml.org,2002:"+l.slice(2)),c=e.compiledTypeMap.fallback[l],c&&pn.call(c.styleAliases,u)&&(u=c.styleAliases[u]),r[l]=u;return r}function Ai(e){var n,r,o;if(n=e.toString(16).toUpperCase(),e<=255)r="x",o=2;else if(e<=65535)r="u",o=4;else if(e<=4294967295)r="U",o=8;else throw new E("code point within a string may not be greater than 0xFFFFFFFF");return"\\"+r+y.repeat("0",o-n.length)+n}var yi=1,B=2;function Ci(e){this.schema=e.schema||ae,this.indent=Math.max(1,e.indent||2),this.noArrayIndent=e.noArrayIndent||!1,this.skipInvalid=e.skipInvalid||!1,this.flowLevel=y.isNothing(e.flowLevel)?-1:e.flowLevel,this.styleMap=vi(this.schema,e.styles||null),this.sortKeys=e.sortKeys||!1,this.lineWidth=e.lineWidth||80,this.noRefs=e.noRefs||!1,this.noCompatMode=e.noCompatMode||!1,this.condenseFlow=e.condenseFlow||!1,this.quotingType=e.quotingType==='"'?B:yi,this.forceQuotes=e.forceQuotes||!1,this.replacer=typeof e.replacer=="function"?e.replacer:null,this.implicitTypes=this.schema.compiledImplicit,this.explicitTypes=this.schema.compiledExplicit,this.tag=null,this.result="",this.duplicates=[],this.usedDuplicates=null}function _e(e,n){for(var r=y.repeat(" ",n),o=0,i=-1,t="",l,u=e.length;o<u;)i=e.indexOf(`
|
|
19
|
+
`,o),i===-1?(l=e.slice(o),o=u):(l=e.slice(o,i+1),o=i+1),l.length&&l!==`
|
|
20
|
+
`&&(t+=r),t+=l;return t}function te(e,n){return`
|
|
21
|
+
`+y.repeat(" ",e.indent*n)}function wi(e,n){var r,o,i;for(r=0,o=e.implicitTypes.length;r<o;r+=1)if(i=e.implicitTypes[r],i.resolve(n))return!0;return!1}function V(e){return e===ri||e===ei}function H(e){return 32<=e&&e<=126||161<=e&&e<=55295&&e!==8232&&e!==8233||57344<=e&&e<=65533&&e!==he||65536<=e&&e<=1114111}function be(e){return H(e)&&e!==he&&e!==ni&&e!==G}function Te(e,n,r){var o=be(e),i=o&&!V(e);return(r?o:o&&e!==hn&&e!==dn&&e!==mn&&e!==gn&&e!==xn)&&e!==le&&!(n===Q&&!i)||be(n)&&!V(n)&&e===le||n===Q&&i}function Ei(e){return H(e)&&e!==he&&!V(e)&&e!==fi&&e!==pi&&e!==Q&&e!==hn&&e!==dn&&e!==mn&&e!==gn&&e!==xn&&e!==le&&e!==ti&&e!==ci&&e!==ii&&e!==mi&&e!==ai&&e!==si&&e!==ui&&e!==oi&&e!==li&&e!==hi&&e!==di}function Si(e){return!V(e)&&e!==Q}function Y(e,n){var r=e.charCodeAt(n),o;return r>=55296&&r<=56319&&n+1<e.length&&(o=e.charCodeAt(n+1),o>=56320&&o<=57343)?(r-55296)*1024+o-56320+65536:r}function vn(e){var n=/^\n* /;return n.test(e)}var An=1,ue=2,yn=3,Cn=4,R=5;function _i(e,n,r,o,i,t,l,u){var c,f=0,s=null,a=!1,h=!1,d=o!==-1,m=-1,x=Ei(Y(e,0))&&Si(Y(e,e.length-1));if(n||l)for(c=0;c<e.length;f>=65536?c+=2:c++){if(f=Y(e,c),!H(f))return R;x=x&&Te(f,s,u),s=f}else{for(c=0;c<e.length;f>=65536?c+=2:c++){if(f=Y(e,c),f===G)a=!0,d&&(h=h||c-m-1>o&&e[m+1]!==" ",m=c);else if(!H(f))return R;x=x&&Te(f,s,u),s=f}h=h||d&&c-m-1>o&&e[m+1]!==" "}return!a&&!h?x&&!l&&!i(e)?An:t===B?R:ue:r>9&&vn(e)?R:l?t===B?R:ue:h?Cn:yn}function bi(e,n,r,o,i){e.dump=function(){if(n.length===0)return e.quotingType===B?'""':"''";if(!e.noCompatMode&&(gi.indexOf(n)!==-1||xi.test(n)))return e.quotingType===B?'"'+n+'"':"'"+n+"'";var t=e.indent*Math.max(1,r),l=e.lineWidth===-1?-1:Math.max(Math.min(e.lineWidth,40),e.lineWidth-t),u=o||e.flowLevel>-1&&r>=e.flowLevel;function c(f){return wi(e,f)}switch(_i(n,u,e.indent,l,c,e.quotingType,e.forceQuotes&&!o,i)){case An:return n;case ue:return"'"+n.replace(/'/g,"''")+"'";case yn:return"|"+Ie(n,e.indent)+Fe(_e(n,t));case Cn:return">"+Ie(n,e.indent)+Fe(_e(Ti(n,l),t));case R:return'"'+Ii(n)+'"';default:throw new E("impossible error: invalid scalar style")}}()}function Ie(e,n){var r=vn(e)?String(n):"",o=e[e.length-1]===`
|
|
22
|
+
`,i=o&&(e[e.length-2]===`
|
|
23
|
+
`||e===`
|
|
24
|
+
`),t=i?"+":o?"":"-";return r+t+`
|
|
25
|
+
`}function Fe(e){return e[e.length-1]===`
|
|
26
|
+
`?e.slice(0,-1):e}function Ti(e,n){for(var r=/(\n+)([^\n]*)/g,o=function(){var f=e.indexOf(`
|
|
27
|
+
`);return f=f!==-1?f:e.length,r.lastIndex=f,ke(e.slice(0,f),n)}(),i=e[0]===`
|
|
28
|
+
`||e[0]===" ",t,l;l=r.exec(e);){var u=l[1],c=l[2];t=c[0]===" ",o+=u+(!i&&!t&&c!==""?`
|
|
29
|
+
`:"")+ke(c,n),i=t}return o}function ke(e,n){if(e===""||e[0]===" ")return e;for(var r=/ [^ ]/g,o,i=0,t,l=0,u=0,c="";o=r.exec(e);)u=o.index,u-i>n&&(t=l>i?l:u,c+=`
|
|
30
|
+
`+e.slice(i,t),i=t+1),l=u;return c+=`
|
|
31
|
+
`,e.length-i>n&&l>i?c+=e.slice(i,l)+`
|
|
32
|
+
`+e.slice(l+1):c+=e.slice(i),c.slice(1)}function Ii(e){for(var n="",r=0,o,i=0;i<e.length;r>=65536?i+=2:i++)r=Y(e,i),o=w[r],!o&&H(r)?(n+=e[i],r>=65536&&(n+=e[i+1])):n+=o||Ai(r);return n}function Fi(e,n,r){var o="",i=e.tag,t,l,u;for(t=0,l=r.length;t<l;t+=1)u=r[t],e.replacer&&(u=e.replacer.call(r,String(t),u)),(T(e,n,u,!1,!1)||typeof u>"u"&&T(e,n,null,!1,!1))&&(o!==""&&(o+=","+(e.condenseFlow?"":" ")),o+=e.dump);e.tag=i,e.dump="["+o+"]"}function Oe(e,n,r,o){var i="",t=e.tag,l,u,c;for(l=0,u=r.length;l<u;l+=1)c=r[l],e.replacer&&(c=e.replacer.call(r,String(l),c)),(T(e,n+1,c,!0,!0,!1,!0)||typeof c>"u"&&T(e,n+1,null,!0,!0,!1,!0))&&((!o||i!=="")&&(i+=te(e,n)),e.dump&&G===e.dump.charCodeAt(0)?i+="-":i+="- ",i+=e.dump);e.tag=t,e.dump=i||"[]"}function ki(e,n,r){var o="",i=e.tag,t=Object.keys(r),l,u,c,f,s;for(l=0,u=t.length;l<u;l+=1)s="",o!==""&&(s+=", "),e.condenseFlow&&(s+='"'),c=t[l],f=r[c],e.replacer&&(f=e.replacer.call(r,c,f)),T(e,n,c,!1,!1)&&(e.dump.length>1024&&(s+="? "),s+=e.dump+(e.condenseFlow?'"':"")+":"+(e.condenseFlow?"":" "),T(e,n,f,!1,!1)&&(s+=e.dump,o+=s));e.tag=i,e.dump="{"+o+"}"}function Oi(e,n,r,o){var i="",t=e.tag,l=Object.keys(r),u,c,f,s,a,h;if(e.sortKeys===!0)l.sort();else if(typeof e.sortKeys=="function")l.sort(e.sortKeys);else if(e.sortKeys)throw new E("sortKeys must be a boolean or a function");for(u=0,c=l.length;u<c;u+=1)h="",(!o||i!=="")&&(h+=te(e,n)),f=l[u],s=r[f],e.replacer&&(s=e.replacer.call(r,f,s)),T(e,n+1,f,!0,!0,!0)&&(a=e.tag!==null&&e.tag!=="?"||e.dump&&e.dump.length>1024,a&&(e.dump&&G===e.dump.charCodeAt(0)?h+="?":h+="? "),h+=e.dump,a&&(h+=te(e,n)),T(e,n+1,s,!0,a)&&(e.dump&&G===e.dump.charCodeAt(0)?h+=":":h+=": ",h+=e.dump,i+=h));e.tag=t,e.dump=i||"{}"}function Le(e,n,r){var o,i,t,l,u,c;for(i=r?e.explicitTypes:e.implicitTypes,t=0,l=i.length;t<l;t+=1)if(u=i[t],(u.instanceOf||u.predicate)&&(!u.instanceOf||typeof n=="object"&&n instanceof u.instanceOf)&&(!u.predicate||u.predicate(n))){if(r?u.multi&&u.representName?e.tag=u.representName(n):e.tag=u.tag:e.tag="?",u.represent){if(c=e.styleMap[u.tag]||u.defaultStyle,sn.call(u.represent)==="[object Function]")o=u.represent(n,c);else if(pn.call(u.represent,c))o=u.represent[c](n,c);else throw new E("!<"+u.tag+'> tag resolver accepts not "'+c+'" style');e.dump=o}return!0}return!1}function T(e,n,r,o,i,t,l){e.tag=null,e.dump=r,Le(e,r,!1)||Le(e,r,!0);var u=sn.call(e.dump),c=o,f;o&&(o=e.flowLevel<0||e.flowLevel>n);var s=u==="[object Object]"||u==="[object Array]",a,h;if(s&&(a=e.duplicates.indexOf(r),h=a!==-1),(e.tag!==null&&e.tag!=="?"||h||e.indent!==2&&n>0)&&(i=!1),h&&e.usedDuplicates[a])e.dump="*ref_"+a;else{if(s&&h&&!e.usedDuplicates[a]&&(e.usedDuplicates[a]=!0),u==="[object Object]")o&&Object.keys(e.dump).length!==0?(Oi(e,n,e.dump,i),h&&(e.dump="&ref_"+a+e.dump)):(ki(e,n,e.dump),h&&(e.dump="&ref_"+a+" "+e.dump));else if(u==="[object Array]")o&&e.dump.length!==0?(e.noArrayIndent&&!l&&n>0?Oe(e,n-1,e.dump,i):Oe(e,n,e.dump,i),h&&(e.dump="&ref_"+a+e.dump)):(Fi(e,n,e.dump),h&&(e.dump="&ref_"+a+" "+e.dump));else if(u==="[object String]")e.tag!=="?"&&bi(e,e.dump,n,t,c);else{if(u==="[object Undefined]")return!1;if(e.skipInvalid)return!1;throw new E("unacceptable kind of an object to dump "+u)}e.tag!==null&&e.tag!=="?"&&(f=encodeURI(e.tag[0]==="!"?e.tag.slice(1):e.tag).replace(/!/g,"%21"),e.tag[0]==="!"?f="!"+f:f.slice(0,18)==="tag:yaml.org,2002:"?f="!!"+f.slice(18):f="!<"+f+">",e.dump=f+" "+e.dump)}return!0}function Li(e,n){var r=[],o=[],i,t;for(ce(e,r,o),i=0,t=o.length;i<t;i+=1)n.duplicates.push(r[o[i]]);n.usedDuplicates=new Array(t)}function ce(e,n,r){var o,i,t;if(e!==null&&typeof e=="object")if(i=n.indexOf(e),i!==-1)r.indexOf(i)===-1&&r.push(i);else if(n.push(e),Array.isArray(e))for(i=0,t=e.length;i<t;i+=1)ce(e[i],n,r);else for(o=Object.keys(e),i=0,t=o.length;i<t;i+=1)ce(e[o[i]],n,r)}function Ni(e,n){n=n||{};var r=new Ci(n);r.noRefs||Li(e,r);var o=e;return r.replacer&&(o=r.replacer.call({"":o},"",o)),T(r,0,o,!0,!0)?r.dump+`
|
|
33
|
+
`:""}var Ri=Ni,Pi={dump:Ri};function de(e,n){return function(){throw new Error("Function yaml."+e+" is removed in js-yaml 4. Use yaml."+n+" instead, which is now safe by default.")}}var Mi=C,Di=Pe,ji=Ye,Yi=Ue,$i=Ke,Gi=ae,Bi=an.load,Hi=an.loadAll,Ui=Pi.dump,Ki=E,qi={binary:Xe,float:He,map:je,null:$e,pairs:ze,set:Je,timestamp:Qe,bool:Ge,int:Be,merge:Ve,omap:Ze,seq:De,str:Me},Wi=de("safeLoad","load"),Qi=de("safeLoadAll","loadAll"),Vi=de("safeDump","dump"),wn={Type:Mi,Schema:Di,FAILSAFE_SCHEMA:ji,JSON_SCHEMA:Yi,CORE_SCHEMA:$i,DEFAULT_SCHEMA:Gi,load:Bi,loadAll:Hi,dump:Ui,YAMLException:Ki,types:qi,safeLoad:Wi,safeLoadAll:Qi,safeDump:Vi};var z=".cligr.yml",N=class extends Error{constructor(n){super(n),this.name="ConfigError"}},k=class{configPath;constructor(n){if(n)this.configPath=U.resolve(n);else{let r=U.join(En.homedir(),z),o=U.resolve(z);Z.existsSync(r)?this.configPath=r:Z.existsSync(o)?this.configPath=o:this.configPath=r}}load(){if(!Z.existsSync(this.configPath))throw new N(`Config file not found. Looking for:
|
|
34
|
+
- ${U.join(En.homedir(),z)}
|
|
35
|
+
- ${U.resolve(z)}`);let n=Z.readFileSync(this.configPath,"utf-8"),r;try{r=wn.load(n)}catch(o){throw new N(`Invalid YAML: ${o.message}`)}return this.validate(r)}validate(n){if(!n||typeof n!="object")throw new N("Config must be an object");let r=n;if(!r.groups||typeof r.groups!="object")throw new N('Config must have a "groups" object');return r}getGroup(n){let r=this.load(),o=r.groups[n];if(!o){let l=Object.keys(r.groups).join(", ");throw new N(`Unknown group: ${n}. Available: ${l}`)}let i=null,t=null;return r.tools&&r.tools[o.tool]?(i=r.tools[o.tool].cmd,t=o.tool):(t=null,i=null),{config:o,tool:t,toolTemplate:i}}listGroups(){let n=this.load();return Object.keys(n.groups)}};var J=class{static expand(n,r,o){let i=r.split(",").map(u=>u.trim()),t=i[0]||`item-${o}`,l=n;for(let u=0;u<i.length;u++){let c=`$${u+1}`;l=l.replaceAll(c,i[u])}return{name:t,args:i,fullCmd:l}}static parseItem(n,r,o,i){if(r)return this.expand(r,o,i);{let t=o.split(",").map(c=>c.trim()),l=t[0]||`item-${i}`,u=n?`${n} ${o}`:o;return{name:l,args:t,fullCmd:u}}}};import{spawn as Xi}from"child_process";var me=class{constructor(n,r,o="running"){this.item=n;this.process=r;this.status=o}},ee=class{groups=new Map;restartTimestamps=new Map;maxRestarts=3;restartWindow=1e4;spawnGroup(n,r,o){if(this.groups.has(n))throw new Error(`Group ${n} is already running`);let i=[];for(let t of r){let l=this.spawnProcess(t,n,o);i.push(new me(t,l))}this.groups.set(n,i)}spawnProcess(n,r,o){let{cmd:i,args:t}=this.parseCommand(n.fullCmd),l=Xi(i,t,{stdio:["inherit","pipe","pipe"],shell:process.platform==="win32"});return l.stdout&&l.stdout.on("data",u=>{process.stdout.write(`[${n.name}] ${u}`)}),l.stderr&&l.stderr.on("data",u=>{process.stderr.write(`[${n.name}] ${u}`)}),l.on("exit",(u,c)=>{this.handleExit(r,n,o,u,c)}),l}parseCommand(n){let r=[],o="",i=!1,t="";for(let l=0;l<n.length;l++){let u=n[l],c=n[l+1];(u==='"'||u==="'")&&!i?(i=!0,t=u):u===t&&i?(i=!1,t=""):u===" "&&!i?o&&(r.push(o),o=""):o+=u}return o&&r.push(o),{cmd:r[0]||"",args:r.slice(1)}}handleExit(n,r,o,i,t){if(o==="unless-stopped"&&t==="SIGTERM"||o==="no")return;let l=`${n}-${r.name}`,u=Date.now(),f=(this.restartTimestamps.get(l)||[]).filter(s=>u-s<this.restartWindow);if(f.push(u),this.restartTimestamps.set(l,f),f.length>this.maxRestarts){console.error(`[${r.name}] Crash loop detected. Stopping restarts.`);return}setTimeout(()=>{console.log(`[${r.name}] Restarting... (exit code: ${i})`);let s=this.spawnProcess(r,n,o),a=this.groups.get(n);if(a){let h=a.find(d=>d.item.name===r.name);h&&(h.process=s)}},1e3)}killGroup(n){let r=this.groups.get(n);if(!r)return Promise.resolve();let o=r.map(i=>this.killProcess(i.process));return this.groups.delete(n),Promise.all(o).then(()=>{})}killProcess(n){return new Promise(r=>{n.kill("SIGTERM");let o=setTimeout(()=>{n.killed||n.kill("SIGKILL")},5e3);n.on("exit",()=>{clearTimeout(o),r()}),(n.killed||n.exitCode!==null)&&(clearTimeout(o),r())})}killAll(){let n=[];for(let r of this.groups.keys())n.push(this.killGroup(r));return Promise.all(n).then(()=>{})}getGroupStatus(n){let r=this.groups.get(n);return r?r.map(o=>o.status):[]}isGroupRunning(n){return this.groups.has(n)}getRunningGroups(){return Array.from(this.groups.keys())}};async function Sn(e){let n=new k,r=new ee,{config:o,tool:i,toolTemplate:t}=n.getGroup(e),l=o.items.map((u,c)=>J.parseItem(i,t,u,c));return r.spawnGroup(e,l,o.restart),console.log(`Started group ${e} with ${l.length} process(es)`),console.log("Press Ctrl+C to stop..."),new Promise(u=>{let c=async()=>{console.log(`
|
|
36
|
+
Shutting down...`),process.removeListener("SIGINT",c),process.removeListener("SIGTERM",c),await r.killAll(),u(0)};process.on("SIGINT",c),process.on("SIGTERM",c)})}async function _n(e){let n=new k;try{let{config:r}=n.getGroup(e);console.log(`
|
|
37
|
+
Group: ${e}`),console.log(`Tool: ${r.tool}`),console.log(`Restart: ${r.restart}`),console.log(`
|
|
38
|
+
Items:`);for(let o of r.items){let i=o.split(","),t=i[0];console.log(` - ${t} (args: ${i.slice(1).join(", ")})`)}return console.log(""),0}catch(r){return console.error(r.message),1}}async function bn(e){return console.log(`Command 'down ${e}' - group will stop when cligr exits`),0}import{spawn as Zi,spawnSync as In}from"child_process";import j from"fs";import zi from"os";import ge from"path";var Tn=".cligr.yml",Ji=`# Cligr Configuration
|
|
39
|
+
|
|
40
|
+
groups:
|
|
41
|
+
web:
|
|
42
|
+
tool: docker
|
|
43
|
+
restart: false
|
|
44
|
+
items:
|
|
45
|
+
- "nginx,8080" # $1=nginx (name), $2=8080 (port)
|
|
46
|
+
- "nginx,3000"
|
|
47
|
+
|
|
48
|
+
simple:
|
|
49
|
+
tool: node
|
|
50
|
+
items:
|
|
51
|
+
- "server" # $1=server (name only)
|
|
52
|
+
|
|
53
|
+
tools:
|
|
54
|
+
docker:
|
|
55
|
+
cmd: "docker run -p $2:$2 nginx" # $1=name, $2=port
|
|
56
|
+
node:
|
|
57
|
+
cmd: "node $1.js" # $1=file name
|
|
58
|
+
|
|
59
|
+
# Syntax:
|
|
60
|
+
# - Items are comma-separated: "name,arg2,arg3"
|
|
61
|
+
# - $1 = name (first value)
|
|
62
|
+
# - $2, $3... = additional arguments
|
|
63
|
+
# - If no tool specified, executes directly
|
|
64
|
+
`;function eo(){let e=process.platform;return In(e==="win32"?"where":"which",["code"],{stdio:"ignore"}).status===0?"code":process.env.EDITOR?process.env.EDITOR:e==="win32"?"notepad.exe":"vim"}function no(e,n){let r=process.platform;if(In(r==="win32"?"where":"which",[n],{stdio:"ignore"}).status!==0&&n!==process.env.EDITOR)throw new Error(`Editor '${n}' not found.
|
|
65
|
+
Install VS Code or set EDITOR environment variable.
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
export EDITOR=vim
|
|
69
|
+
cligr config`);Zi(n,[e],{detached:!0,stdio:"ignore",shell:r==="win32"}).unref()}function ro(e){let n=ge.dirname(e);j.existsSync(n)||j.mkdirSync(n,{recursive:!0}),j.writeFileSync(e,Ji,"utf-8")}async function Fn(){try{let e=ge.join(zi.homedir(),Tn),n=ge.resolve(Tn),r;j.existsSync(e)?r=e:j.existsSync(n)?r=n:r=e,j.existsSync(r)||ro(r);let o=eo();return no(r,o),console.log(`Opening ${r} in ${o}...`),0}catch(e){return console.error(`Error: ${e.message}`),1}}async function kn(e){let n=new k;try{let r=n.listGroups();if(r.length===0)return 0;if(e){let o=n.load(),i=[];for(let f of r){let s=o.groups[f];i.push({name:f,tool:s.tool||"(none)",restart:s.restart,itemCount:s.items.length})}let t=Math.max(5,...i.map(f=>f.name.length)),l=Math.max(4,...i.map(f=>f.tool.length)),u=Math.max(7,...i.map(f=>f.restart.length)),c="GROUP".padEnd(t)+" "+"TOOL".padEnd(l)+" "+"RESTART".padEnd(u)+" ITEMS";console.log(c);for(let f of i){let s=f.name.padEnd(t)+" "+f.tool.padEnd(l)+" "+f.restart.padEnd(u)+" "+String(f.itemCount);console.log(s)}}else for(let o of r)console.log(o);return 0}catch(r){return console.error(r.message),1}}async function io(){let e=process.argv.slice(2);if(e.length===0){xe(),process.exit(1);return}let[n,...r]=e,o,i=!1;if(n==="groups"){let l=r.findIndex(u=>u==="-v"||u==="--verbose");l!==-1&&(i=!0,r.splice(l,1))}if(o=r[0],n!=="config"&&n!=="groups"&&!o){console.error("Error: group name required"),xe(),process.exit(1);return}let t=0;switch(n){case"config":t=await Fn();break;case"up":t=await Sn(o);break;case"ls":t=await _n(o);break;case"down":t=await bn(o);break;case"groups":t=await kn(i);break;default:console.error(`Error: unknown command '${n}'`),xe(),t=1}process.exit(t)}function xe(){console.log(`
|
|
70
|
+
Usage: cligr <command> [options] [group]
|
|
71
|
+
|
|
72
|
+
Commands:
|
|
73
|
+
config Open config file in editor
|
|
74
|
+
up <group> Start all processes in the group
|
|
75
|
+
ls <group> List all items in the group
|
|
76
|
+
down <group> Stop the group (Ctrl+C also works)
|
|
77
|
+
groups [-v|--verbose] List all groups
|
|
78
|
+
|
|
79
|
+
Options:
|
|
80
|
+
-v, --verbose Show detailed group information
|
|
81
|
+
|
|
82
|
+
Examples:
|
|
83
|
+
cligr config
|
|
84
|
+
cligr up test1
|
|
85
|
+
cligr ls test1
|
|
86
|
+
cligr down test1
|
|
87
|
+
cligr groups
|
|
88
|
+
cligr groups -v
|
|
89
|
+
`)}io().catch(e=>{console.error(e),process.exit(2)});
|
|
90
|
+
/*! Bundled license information:
|
|
91
|
+
|
|
92
|
+
js-yaml/dist/js-yaml.mjs:
|
|
93
|
+
(*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT *)
|
|
94
|
+
*/
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cligr",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"bin": {
|
|
6
|
+
"cligr": "./dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"author": "zerr",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "node scripts/build.js",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
14
|
+
"test": "node scripts/test.js",
|
|
15
|
+
"test:verbose": "node scripts/test.js --verbose"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@types/js-yaml": "^4.0.9",
|
|
19
|
+
"@types/node": "^22.10.5",
|
|
20
|
+
"esbuild": "^0.24.2",
|
|
21
|
+
"typescript": "^5.7.3"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"js-yaml": "^4.1.1"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/scripts/build.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as esbuild from 'esbuild';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
|
|
5
|
+
// Ensure dist directory exists
|
|
6
|
+
const distDir = path.resolve('dist');
|
|
7
|
+
fs.mkdirSync(distDir, { recursive: true });
|
|
8
|
+
|
|
9
|
+
// Build with esbuild
|
|
10
|
+
await esbuild.build({
|
|
11
|
+
entryPoints: ['src/index.ts'],
|
|
12
|
+
bundle: true,
|
|
13
|
+
format: 'esm',
|
|
14
|
+
platform: 'node',
|
|
15
|
+
outfile: 'dist/index.js',
|
|
16
|
+
minify: true,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
console.log('Build complete!');
|
|
20
|
+
console.log(` dist/index.js (${fs.statSync('dist/index.js').size} bytes)`);
|
package/scripts/test.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Test runner script that compiles TypeScript tests with esbuild
|
|
5
|
+
* and runs them with Node.js built-in test runner
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { build } from 'esbuild';
|
|
9
|
+
import { exec } from 'child_process';
|
|
10
|
+
import { promisify } from 'util';
|
|
11
|
+
import fs from 'fs';
|
|
12
|
+
import path from 'path';
|
|
13
|
+
import { fileURLToPath } from 'url';
|
|
14
|
+
|
|
15
|
+
const execAsync = promisify(exec);
|
|
16
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
17
|
+
const __dirname = path.dirname(__filename);
|
|
18
|
+
|
|
19
|
+
const PROJECT_ROOT = path.resolve(__dirname, '..');
|
|
20
|
+
const TESTS_DIR = path.join(PROJECT_ROOT, 'tests/integration');
|
|
21
|
+
const DIST_DIR = path.join(PROJECT_ROOT, 'tests-dist');
|
|
22
|
+
const SRC_DIR = path.join(PROJECT_ROOT, 'src');
|
|
23
|
+
|
|
24
|
+
async function buildSourceModules() {
|
|
25
|
+
console.log('Building source modules...');
|
|
26
|
+
|
|
27
|
+
// Build source modules directly to src directory (as .js files alongside .ts)
|
|
28
|
+
const dirs = ['config', 'process', 'commands'];
|
|
29
|
+
|
|
30
|
+
for (const dir of dirs) {
|
|
31
|
+
const dirPath = path.join(SRC_DIR, dir);
|
|
32
|
+
if (!fs.existsSync(dirPath)) continue;
|
|
33
|
+
|
|
34
|
+
const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.ts'));
|
|
35
|
+
|
|
36
|
+
for (const file of files) {
|
|
37
|
+
const inFile = path.join(dirPath, file);
|
|
38
|
+
const outFile = path.join(dirPath, file.replace('.ts', '.js'));
|
|
39
|
+
|
|
40
|
+
await build({
|
|
41
|
+
entryPoints: [inFile],
|
|
42
|
+
bundle: false,
|
|
43
|
+
platform: 'node',
|
|
44
|
+
target: 'es2022',
|
|
45
|
+
format: 'esm',
|
|
46
|
+
outfile: outFile,
|
|
47
|
+
absWorkingDir: PROJECT_ROOT,
|
|
48
|
+
logLevel: 'silent',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log('Built source modules');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function buildTests(skipBlocking = false) {
|
|
57
|
+
console.log('Building TypeScript tests...');
|
|
58
|
+
|
|
59
|
+
// Clean dist directory
|
|
60
|
+
if (fs.existsSync(DIST_DIR)) {
|
|
61
|
+
fs.rmSync(DIST_DIR, { recursive: true, force: true });
|
|
62
|
+
}
|
|
63
|
+
fs.mkdirSync(DIST_DIR, { recursive: true });
|
|
64
|
+
|
|
65
|
+
// Also create tests/integration subdirectory to match original structure
|
|
66
|
+
const outputSubDir = path.join(DIST_DIR, 'integration');
|
|
67
|
+
fs.mkdirSync(outputSubDir, { recursive: true });
|
|
68
|
+
|
|
69
|
+
// Find all test files
|
|
70
|
+
let testFiles = fs.readdirSync(TESTS_DIR)
|
|
71
|
+
.filter(f => f.endsWith('.test.ts'))
|
|
72
|
+
.map(f => path.join(TESTS_DIR, f));
|
|
73
|
+
|
|
74
|
+
// Skip blocking-processes tests by default (they have infinite loops)
|
|
75
|
+
if (skipBlocking) {
|
|
76
|
+
testFiles = testFiles.filter(f => !f.includes('blocking-processes'));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Build each test file
|
|
80
|
+
for (const testFile of testFiles) {
|
|
81
|
+
const outputFile = path.join(
|
|
82
|
+
outputSubDir,
|
|
83
|
+
path.basename(testFile).replace('.ts', '.js')
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
await build({
|
|
87
|
+
entryPoints: [testFile],
|
|
88
|
+
bundle: false,
|
|
89
|
+
platform: 'node',
|
|
90
|
+
target: 'es2022',
|
|
91
|
+
format: 'esm',
|
|
92
|
+
outfile: outputFile,
|
|
93
|
+
absWorkingDir: PROJECT_ROOT,
|
|
94
|
+
logLevel: 'error',
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log(`Built ${testFiles.length} test files`);
|
|
99
|
+
return testFiles.length;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function runTests(verbose = false) {
|
|
103
|
+
const testFiles = fs.readdirSync(path.join(DIST_DIR, 'integration'))
|
|
104
|
+
.filter(f => f.endsWith('.test.js'))
|
|
105
|
+
.map(f => path.join(DIST_DIR, 'integration', f))
|
|
106
|
+
.join(' ');
|
|
107
|
+
|
|
108
|
+
const verboseFlag = verbose ? '--verbose' : '';
|
|
109
|
+
const command = `node --test ${verboseFlag} ${testFiles}`;
|
|
110
|
+
|
|
111
|
+
console.log('\nRunning tests...\n');
|
|
112
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
113
|
+
stdio: 'inherit',
|
|
114
|
+
cwd: PROJECT_ROOT
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return { stdout, stderr };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async function cleanupSourceModules() {
|
|
121
|
+
// Remove generated .js files from src directory
|
|
122
|
+
const dirs = ['config', 'process', 'commands'];
|
|
123
|
+
|
|
124
|
+
for (const dir of dirs) {
|
|
125
|
+
const dirPath = path.join(SRC_DIR, dir);
|
|
126
|
+
if (!fs.existsSync(dirPath)) continue;
|
|
127
|
+
|
|
128
|
+
const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.js'));
|
|
129
|
+
|
|
130
|
+
for (const file of files) {
|
|
131
|
+
const filePath = path.join(dirPath, file);
|
|
132
|
+
fs.unlinkSync(filePath);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async function main() {
|
|
138
|
+
const args = process.argv.slice(2);
|
|
139
|
+
const verbose = args.includes('--verbose') || args.includes('-v');
|
|
140
|
+
const includeBlocking = args.includes('--include-blocking') || args.includes('-b');
|
|
141
|
+
|
|
142
|
+
try {
|
|
143
|
+
await buildSourceModules();
|
|
144
|
+
await buildTests(!includeBlocking);
|
|
145
|
+
await runTests(verbose);
|
|
146
|
+
|
|
147
|
+
// Clean up
|
|
148
|
+
cleanupSourceModules();
|
|
149
|
+
if (fs.existsSync(DIST_DIR)) {
|
|
150
|
+
fs.rmSync(DIST_DIR, { recursive: true, force: true });
|
|
151
|
+
}
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.error('Test failed:', error.message);
|
|
154
|
+
// Still try to clean up on error
|
|
155
|
+
try {
|
|
156
|
+
cleanupSourceModules();
|
|
157
|
+
} catch (e) {
|
|
158
|
+
// Ignore cleanup errors
|
|
159
|
+
}
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
main();
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { spawn, spawnSync } from 'child_process';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
const CONFIG_FILENAME = '.cligr.yml';
|
|
7
|
+
const TEMPLATE = `# Cligr Configuration
|
|
8
|
+
|
|
9
|
+
groups:
|
|
10
|
+
web:
|
|
11
|
+
tool: docker
|
|
12
|
+
restart: false
|
|
13
|
+
items:
|
|
14
|
+
- "nginx,8080" # $1=nginx (name), $2=8080 (port)
|
|
15
|
+
- "nginx,3000"
|
|
16
|
+
|
|
17
|
+
simple:
|
|
18
|
+
tool: node
|
|
19
|
+
items:
|
|
20
|
+
- "server" # $1=server (name only)
|
|
21
|
+
|
|
22
|
+
tools:
|
|
23
|
+
docker:
|
|
24
|
+
cmd: "docker run -p $2:$2 nginx" # $1=name, $2=port
|
|
25
|
+
node:
|
|
26
|
+
cmd: "node $1.js" # $1=file name
|
|
27
|
+
|
|
28
|
+
# Syntax:
|
|
29
|
+
# - Items are comma-separated: "name,arg2,arg3"
|
|
30
|
+
# - $1 = name (first value)
|
|
31
|
+
# - $2, $3... = additional arguments
|
|
32
|
+
# - If no tool specified, executes directly
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
function detectEditor(): string {
|
|
36
|
+
const platform = process.platform;
|
|
37
|
+
|
|
38
|
+
// Try VS Code first
|
|
39
|
+
const whichCmd = platform === 'win32' ? 'where' : 'which';
|
|
40
|
+
const codeCheck = spawnSync(whichCmd, ['code'], { stdio: 'ignore' });
|
|
41
|
+
if (codeCheck.status === 0) {
|
|
42
|
+
return 'code';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Try EDITOR environment variable
|
|
46
|
+
if (process.env.EDITOR) {
|
|
47
|
+
return process.env.EDITOR;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Platform defaults
|
|
51
|
+
if (platform === 'win32') {
|
|
52
|
+
return 'notepad.exe';
|
|
53
|
+
}
|
|
54
|
+
return 'vim';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function spawnEditor(filePath: string, editorCmd: string): void {
|
|
58
|
+
// Check if editor exists before spawning
|
|
59
|
+
const platform = process.platform;
|
|
60
|
+
const whichCmd = platform === 'win32' ? 'where' : 'which';
|
|
61
|
+
const editorCheck = spawnSync(whichCmd, [editorCmd], { stdio: 'ignore' });
|
|
62
|
+
|
|
63
|
+
if (editorCheck.status !== 0 && editorCmd !== process.env.EDITOR) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Editor '${editorCmd}' not found.\n` +
|
|
66
|
+
`Install VS Code or set EDITOR environment variable.\n\n` +
|
|
67
|
+
`Example:\n` +
|
|
68
|
+
` export EDITOR=vim\n` +
|
|
69
|
+
` cligr config`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Spawn detached so terminal is not blocked
|
|
74
|
+
const child = spawn(editorCmd, [filePath], {
|
|
75
|
+
detached: true,
|
|
76
|
+
stdio: 'ignore',
|
|
77
|
+
shell: platform === 'win32',
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
child.unref();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function createTemplate(filePath: string): void {
|
|
84
|
+
const dir = path.dirname(filePath);
|
|
85
|
+
if (!fs.existsSync(dir)) {
|
|
86
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
87
|
+
}
|
|
88
|
+
fs.writeFileSync(filePath, TEMPLATE, 'utf-8');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export async function configCommand(): Promise<number> {
|
|
92
|
+
try {
|
|
93
|
+
// Determine config path (same logic as ConfigLoader)
|
|
94
|
+
const homeDirConfig = path.join(os.homedir(), CONFIG_FILENAME);
|
|
95
|
+
const currentDirConfig = path.resolve(CONFIG_FILENAME);
|
|
96
|
+
|
|
97
|
+
let configPath: string;
|
|
98
|
+
if (fs.existsSync(homeDirConfig)) {
|
|
99
|
+
configPath = homeDirConfig;
|
|
100
|
+
} else if (fs.existsSync(currentDirConfig)) {
|
|
101
|
+
configPath = currentDirConfig;
|
|
102
|
+
} else {
|
|
103
|
+
configPath = homeDirConfig;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Create template if doesn't exist
|
|
107
|
+
if (!fs.existsSync(configPath)) {
|
|
108
|
+
createTemplate(configPath);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Detect and open editor
|
|
112
|
+
const editor = detectEditor();
|
|
113
|
+
spawnEditor(configPath, editor);
|
|
114
|
+
|
|
115
|
+
console.log(`Opening ${configPath} in ${editor}...`);
|
|
116
|
+
return 0;
|
|
117
|
+
} catch (err: any) {
|
|
118
|
+
console.error(`Error: ${err.message}`);
|
|
119
|
+
return 1;
|
|
120
|
+
}
|
|
121
|
+
}
|