new cli command handling

This commit is contained in:
Evert Prants 2021-02-13 14:37:18 +02:00
parent 7554048339
commit 8ff1a795d1
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
3 changed files with 256 additions and 671 deletions

458
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "@squeebot/cli",
"version": "3.0.0-1",
"version": "3.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -31,7 +31,9 @@
}
},
"@squeebot/core": {
"version": "3.0.0",
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@squeebot/core/-/core-3.2.0.tgz",
"integrity": "sha512-GOKjVqtWHrdDgLlXuosUMk42HiqXWlQz5dfuwfNNWDQDjALiVs65hvMAcerFlqXhxL2oKdlw4rWPRCZg6m8GTA==",
"requires": {
"dateformat": "^4.0.0",
"fs-extra": "^9.0.1",
@ -39,352 +41,6 @@
"tar": "^6.0.5"
},
"dependencies": {
"@babel/code-frame": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
"requires": {
"@babel/highlight": "^7.10.4"
}
},
"@babel/helper-validator-identifier": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz",
"integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw=="
},
"@babel/highlight": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"@types/dateformat": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/dateformat/-/dateformat-3.0.1.tgz",
"integrity": "sha512-KlPPdikagvL6ELjWsljbyDIPzNCeliYkqRpI+zea99vBBbCIA5JNshZAwQKTON139c87y9qvTFVgkFd14rtS4g=="
},
"@types/fs-extra": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.4.tgz",
"integrity": "sha512-50GO5ez44lxK5MDH90DYHFFfqxH7+fTqEEnvguQRzJ/tY9qFrMSHLiYHite+F3SNmf7+LHC1eMXojuD+E3Qcyg==",
"requires": {
"@types/node": "*"
}
},
"@types/minipass": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@types/minipass/-/minipass-2.2.0.tgz",
"integrity": "sha512-wuzZksN4w4kyfoOv/dlpov4NOunwutLA/q7uc00xU02ZyUY+aoM5PWIXEKBMnm0NHd4a+N71BMjq+x7+2Af1fg==",
"requires": {
"@types/node": "*"
}
},
"@types/node": {
"version": "14.14.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.9.tgz",
"integrity": "sha512-JsoLXFppG62tWTklIoO4knA+oDTYsmqWxHRvd4lpmfQRNhX6osheUOWETP2jMoV/2bEHuMra8Pp3Dmo/stBFcw=="
},
"@types/semver": {
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.4.tgz",
"integrity": "sha512-+nVsLKlcUCeMzD2ufHEYuJ9a2ovstb6Dp52A5VsoKxDXgvE051XgHI/33I1EymwkRGQkwnA0LkhnUzituGs4EQ=="
},
"@types/tar": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@types/tar/-/tar-4.0.4.tgz",
"integrity": "sha512-0Xv+xcmkTsOZdIF4yCnd7RkOOyfyqPaqJ7RZFKnwdxfDbkN3eAAE9sHl8zJFqBz4VhxolW9EErbjR1oyH7jK2A==",
"requires": {
"@types/minipass": "*",
"@types/node": "*"
}
},
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"requires": {
"color-convert": "^1.9.0"
}
},
"argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"requires": {
"sprintf-js": "~1.0.2"
}
},
"at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
"integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"dateformat": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.0.0.tgz",
"integrity": "sha512-zpKyDYpeePyYGJp2HhRxLHlA+jZQNjt+MwmcVmLxCIECeC4Ks3TI3yk/CSMKylbnCJ5htonfOugYtRRTpyoHow=="
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A=="
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
},
"fs-extra": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.1.tgz",
"integrity": "sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ==",
"requires": {
"at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^1.0.0"
}
},
"fs-minipass": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
"requires": {
"minipass": "^3.0.0"
}
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "^1.1.1"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"is-core-module": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.1.0.tgz",
"integrity": "sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA==",
"requires": {
"has": "^1.0.3"
}
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
},
"js-yaml": {
"version": "3.14.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz",
"integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==",
"requires": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
}
},
"jsonfile": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^2.0.0"
},
"dependencies": {
"universalify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ=="
}
}
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"requires": {
"yallist": "^4.0.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"minipass": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz",
"integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==",
"requires": {
"yallist": "^4.0.0"
}
},
"minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
"requires": {
"minipass": "^3.0.0",
"yallist": "^4.0.0"
}
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"requires": {
"minimist": "^1.2.5"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
"resolve": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
"integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
"requires": {
"is-core-module": "^2.1.0",
"path-parse": "^1.0.6"
}
},
"semver": {
"version": "7.3.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
@ -392,99 +48,6 @@
"requires": {
"lru-cache": "^6.0.0"
}
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"requires": {
"has-flag": "^3.0.0"
}
},
"tar": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz",
"integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==",
"requires": {
"chownr": "^2.0.0",
"fs-minipass": "^2.0.0",
"minipass": "^3.0.0",
"minizlib": "^2.1.1",
"mkdirp": "^1.0.3",
"yallist": "^4.0.0"
},
"dependencies": {
"mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
}
}
},
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"tslint": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz",
"integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==",
"requires": {
"@babel/code-frame": "^7.0.0",
"builtin-modules": "^1.1.1",
"chalk": "^2.3.0",
"commander": "^2.12.1",
"diff": "^4.0.1",
"glob": "^7.1.1",
"js-yaml": "^3.13.1",
"minimatch": "^3.0.4",
"mkdirp": "^0.5.3",
"resolve": "^1.3.2",
"semver": "^5.3.0",
"tslib": "^1.13.0",
"tsutils": "^2.29.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
}
}
},
"tsutils": {
"version": "2.29.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz",
"integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==",
"requires": {
"tslib": "^1.8.1"
}
},
"typescript": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.5.tgz",
"integrity": "sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ=="
},
"universalify": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz",
"integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug=="
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
},
@ -640,6 +203,11 @@
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"dateformat": {
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.5.1.tgz",
"integrity": "sha512-OD0TZ+B7yP7ZgpJf5K2DIbj3FZvFvxgFUuaqA/V5zTjAtAAXZ1E8bktHxmAGs4x5b7PflqA9LeQ84Og7wYtF7Q=="
},
"diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
@ -800,6 +368,14 @@
}
}
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"requires": {
"yallist": "^4.0.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",

View File

@ -1,6 +1,6 @@
{
"name": "@squeebot/cli",
"version": "3.0.2",
"version": "3.1.0",
"description": "Squeebot v3 runtime, environments and configuration",
"main": "dist/squeebot.js",
"bin": {
@ -29,7 +29,7 @@
"typescript": "^4.0.5"
},
"dependencies": {
"@squeebot/core": "^3.1.0",
"@squeebot/core": "^3.2.0",
"fs-extra": "^9.0.1",
"node-watch": "^0.7.0",
"tar": "^6.0.5",

View File

@ -3,59 +3,76 @@ import { IRepository } from '@squeebot/core/lib/plugin/repository';
import { ReadLine } from 'readline';
import { Squeebot } from './core';
export class SqueebotCLI {
constructor(private bot: Squeebot) {}
declare type Executable = (...args: string[]) => Promise<any>;
private async checkUpdate(repo: IRepository): Promise<void> {
const updatable = await this.bot.repositoryManager.checkForUpdates(repo);
if (updatable.length) {
logger.log('[%s] The following plugins can be updated:', repo.name,
updatable.map((u) => u.name).join(', '));
} else {
logger.log('[%s] All plugins are up-to-date!', repo.name);
}
class CLICommand {
constructor(
public name: string,
public func: Executable,
public sub: CLICommand[],
public after?: (returned: any, ...args: string[]) => Promise<any>) {}
public getSub(name: string): CLICommand | undefined {
return this.sub.find(c => c.name.startsWith(name));
}
private async repositoryCommand(...args: any[]): Promise<void> {
const help = 'repository add <url> | update <name> | remove <name> | plugins <name> | list';
if (!args[0] || (args[0] === 'help' && args[0] !== 'list')) {
logger.log(help);
return;
/**
* Executes a sub-command or, if not found, the current one.
* @param args Command arguments
*/
public async execute(args: string[]): Promise<any> {
if (args[0]) {
const subl = this.getSub(args[0]);
if (subl) {
const rv1 = await subl.execute(args.slice(1));
if (this.after) {
return this.after.call(this, rv1, ...args);
}
return rv1;
}
}
switch (args[0]) {
case 'a':
case 'i':
case 'add':
case 'install':
if (!args[1]) {
logger.error('URL is required');
return;
const rv2 = await this.func.call(this, ...args);
if (this.after) {
return this.after.call(this, rv2, ...args);
}
return rv2;
}
}
function cmd(name: string, func: Executable, sub: CLICommand[] = []): CLICommand {
return new CLICommand(name, func, sub);
}
export class SqueebotCLI {
private inspector = false;
private cmds: CLICommand[] = [
// Repository management
cmd('repository', async (...args: string[]): Promise<void> => {
logger.log('Usage: repository add <url> | update <name> | remove <name> | plugins <name> | list');
}, [
cmd('install', async (...args: string[]): Promise<void> => {
if (!args.length) {
throw new Error('URL is required');
}
for (const urlp of args.slice(1)) {
for (const urlp of args) {
const repo = await this.bot.repositoryManager.installRepository(urlp);
logger.log('Installed repository %s!', repo.name);
}
break;
case 'r':
case 'rem':
case 'remove':
case 'uninstall':
if (!args[1]) {
logger.error('Name is required');
return;
}),
cmd('remove', async (...args: string[]): Promise<void> => {
if (!args.length) {
throw new Error('Name is required');
}
for (const namep of args.slice(1)) {
for (const namep of args) {
await this.bot.repositoryManager.uninstallRepository(namep);
logger.log('Installed repository %s.', namep);
}
break;
case 'u':
case 'upd':
case 'update':
if (!args[1]) {
}),
cmd('update', async (...args: string[]): Promise<void> => {
if (!args.length) {
const repolist = this.bot.repositoryManager.getAll();
for (const repo of repolist) {
await this.checkUpdate(repo);
@ -63,124 +80,93 @@ export class SqueebotCLI {
return;
}
for (const namep of args.slice(1)) {
for (const namep of args) {
const repo = this.bot.repositoryManager.getRepoByName(namep);
if (!repo) {
logger.error('No such repository "%s" found.', namep);
return;
throw new Error(`No such repository "${namep}" found.`);
}
await this.checkUpdate(repo);
}
break;
case 'list':
}),
cmd('plugins', async (...args: string[]): Promise<void> => {
if (!args.length) {
throw new Error('Name is required');
}
const repo = this.bot.repositoryManager.getRepoByName(args[0]);
if (!repo) {
throw new Error(`No such repository "${args[0]}" found.`);
}
logger.log('List of plugins in %s:', args[0],
repo.plugins.map(x => `${x.name}@${x.version}`).join(', '));
}),
cmd('list', async (...args: string[]): Promise<void> => {
const repos = this.bot.repositoryManager.getAll();
logger.log('List of installed repositories:');
for (const repo of repos) {
logger.log('%s: (%s) with %d plugins | Date: %s',
repo.name, repo.url, repo.plugins.length, new Date(repo.created * 1000).toDateString());
}
break;
case 'plugins': {
if (!args[1]) {
logger.error('Name is required');
return;
}
const repo = this.bot.repositoryManager.getRepoByName(args[1]);
if (!repo) {
logger.error('No such repository "%s" found.', args[1]);
return;
}
logger.log('List of plugins in %s:', args[1],
repo.plugins.map(x => `${x.name}@${x.version}`).join(', '));
break;
}
default:
logger.log(help);
}
}
private async pluginCommand(...args: any[]): Promise<void> {
const help = 'plugin install | update | uninstall | enable | disable | start | restart | stop | list | running [<name>]';
if (!args[0] || args[0] === 'help' || (!args[1] && args[0] !== 'list' && args[0] !== 'running')) {
logger.log(help);
return;
}
switch (args[0]) {
case 'i':
case 'u':
case 'install':
case 'update':
for (const name of args.slice(1)) {
}),
]),
// Plugin management
cmd('plugin', async (...args: string[]): Promise<void> => {
logger.log('Usage: plugin install | update | remove | enable | disable | load | restart | kill | list | running [<name>]');
}, [
cmd('update', async (...args: string[]): Promise<void> => {
for (const name of args) {
const mf = await this.bot.repositoryManager.installPlugin(name);
logger.log('Installed plugin %s version %s!', mf.name, mf.version);
}
break;
case 'uninst':
case 'remove':
case 'uninstall':
for (const name of args.slice(1)) {
await this.bot.repositoryManager.uninstallPlugin(name);
logger.log('Uninstalled plugin %s.', name);
}
break;
case 'list':
logger.log('Installed plugins:',
this.bot.pluginManager.availablePlugins.map((mf) => mf.name).join(', '));
break;
case 'running':
logger.log('Currently running plugins:',
this.bot.pluginManager.getLoaded().map((p) => p.manifest.name).join(', '));
break;
case 's':
case 'run':
case 'load':
case 'start':
for (const name of args.slice(1)) {
}),
cmd('restart', async (...args: string[]): Promise<void> => {
for (const name of args) {
const plugin = this.bot.pluginManager.getAvailableByName(name);
if (!plugin) {
logger.error('"%s" is not available. Maybe try installing it? plugin install', name, name);
return;
}
await this.bot.pluginManager.load(plugin);
logger.log('Started plugin "%s" successfully.', name);
}
break;
case 'restart':
case 'reload':
for (const name of args.slice(1)) {
const plugin = this.bot.pluginManager.getAvailableByName(name);
if (!plugin) {
logger.error('"%s" is not available. Maybe try installing it? plugin install', name, name);
return;
throw new Error(`"${name}" is not available. Maybe try installing it? plugin install ${name}`);
}
logger.log('Scheduling restart for', name);
await this.bot.pluginManager.restart(plugin);
}
break;
case 'stop':
case 'kill':
case 'unload':
for (const name of args.slice(1)) {
}),
cmd('remove', async (...args: string[]): Promise<void> => {
for (const name of args) {
await this.bot.repositoryManager.uninstallPlugin(name);
logger.log('Uninstalled plugin %s.', name);
}
}),
cmd('running', async (...args: string[]): Promise<void> => {
logger.log('Currently running plugins:',
this.bot.pluginManager.getLoaded().map((p) => p.manifest.name).join(', '));
}),
cmd('load', async (...args: string[]): Promise<void> => {
for (const name of args) {
const plugin = this.bot.pluginManager.getAvailableByName(name);
if (!plugin) {
throw new Error(`"${name}" is not available. Maybe try installing it? plugin install`);
}
await this.bot.pluginManager.load(plugin);
logger.log('Loaded plugin "%s" successfully.', name);
}
}),
cmd('kill', async (...args: string[]): Promise<void> => {
for (const name of args) {
if (!this.bot.pluginManager.getAvailableByName(name)) {
logger.error('No such plugin is available.');
return;
throw new Error('No such plugin is available.');
}
logger.log('Stopping plugin', name);
this.bot.stream.emitTo(name, 'pluginUnload', name);
}
break;
case 'enable':
for (const name of args.slice(1)) {
}),
cmd('enable', async (...args: string[]): Promise<void> => {
for (const name of args) {
if (!this.bot.pluginManager.getAvailableByName(name)) {
logger.error('No such plugin "%s" is available.', name);
return;
throw new Error(`No such plugin "${name}" found.`);
}
logger.log('Enabling plugin', name);
@ -196,12 +182,11 @@ export class SqueebotCLI {
}
await this.bot.config.save();
break;
case 'disable':
for (const name of args.slice(1)) {
}),
cmd('disable', async (...args: string[]): Promise<void> => {
for (const name of args) {
if (!this.bot.pluginManager.getAvailableByName(name)) {
logger.error('No such plugin "%s" is available.', name);
return;
throw new Error(`No such plugin "${name}" found.`);
}
logger.log('Disabling plugin', name);
@ -217,163 +202,187 @@ export class SqueebotCLI {
}
await this.bot.config.save();
break;
default:
logger.log(help);
}
}
private async channelCommand(...args: any[]): Promise<void> {
const help = 'channel new | del | list | addplugin | delplugin [<name>] [<plugin>]';
if (!args[0] || args[0] === 'help' || (!args[1] && args[0] !== 'list')) {
logger.log(help);
return;
}
switch (args[0]) {
case 'new':
if (this.bot.channelManager.getChannelByName(args[1])) {
logger.error('A channel by that name already exists!');
break;
}),
cmd('list', async (...args: string[]): Promise<void> => {
logger.log('Installed plugins:',
this.bot.pluginManager.availablePlugins.map((mf) => mf.name).join(', '));
}),
]),
// Channel management, with an "after" handler
new CLICommand('channel', async (...args: string[]): Promise<void> => {
logger.log('Usage: channel new | del | list | addplugin | delplugin [<name>] [<plugin>]');
}, [
cmd('new', async (...args: string[]): Promise<void> => {
if (this.bot.channelManager.getChannelByName(args[0])) {
throw new Error('A channel by that name already exists!');
}
this.bot.channelManager.addChannel({
name: args[1],
name: args[0],
plugins: [],
enabled: true,
});
logger.log('Channel added!');
break;
case 'del':
case 'delete':
case 'remove':
for (const name of args.slice(1)) {
}),
cmd('remove', async (...args: string[]): Promise<void> => {
for (const name of args) {
const chan = this.bot.channelManager.getChannelByName(name);
if (!chan) {
logger.error('No such channel "%s" exists!', name);
return;
throw new Error(`No such channel "${name}" found.`);
}
this.bot.channelManager.removeChannel(chan);
logger.log('Channel "%s" removed!', name);
}
break;
case 'addp':
case 'addplugin':
const chan1 = this.bot.channelManager.getChannelByName(args[1]);
}),
cmd('addplugin', async (...args: string[]): Promise<void> => {
const chan1 = this.bot.channelManager.getChannelByName(args[0]);
if (!chan1) {
logger.error('No such channel exists!');
return;
throw new Error('No such channel exists!');
}
if (!args[2]) {
logger.error('A plugin name is required.');
return;
if (!args[1]) {
throw new Error('A plugin name is required.');
}
for (const name of args.slice(2)) {
for (const name of args.slice(1)) {
if (chan1.plugins.indexOf(name) === -1) {
chan1.plugins.push(name);
}
logger.log('Plugin "%s" added to channel!', name);
}
break;
case 'list':
logger.log('Channels:\n', this.bot.channelManager.getAll().map((chan) => {
return ` => ${chan.name}: ${chan.plugins.join(', ')} (${chan.enabled ? 'enabled' : 'disabled'})`;
}).join('\n'));
break;
case 'remp':
case 'delp':
case 'remplugin':
case 'delplugin':
const chan2 = this.bot.channelManager.getChannelByName(args[1]);
}),
cmd('delplugin', async (...args: string[]): Promise<void> => {
const chan2 = this.bot.channelManager.getChannelByName(args[0]);
if (!chan2) {
logger.error('No such channel exists!');
return;
throw new Error('No such channel exists!');
}
if (!args[2]) {
logger.error('A plugin name is required.');
return;
if (!args[1]) {
throw new Error('A plugin name is required.');
}
for (const name of args.slice(2)) {
const idx = chan2.plugins.indexOf(args[2]);
for (const name of args.slice(1)) {
const idx = chan2.plugins.indexOf(name);
if (idx !== -1) {
chan2.plugins.splice(idx, 1);
}
logger.log('Plugin "%s" removed from channel!', name);
}
break;
case 'enable':
for (const name of args.slice(1)) {
}),
cmd('enable', async (...args: string[]): Promise<void> => {
for (const name of args) {
const chan = this.bot.channelManager.getChannelByName(name);
if (!chan) {
logger.error('No such channel "%s" exists!', name);
return;
throw new Error(`No such channel "${name}" found.`);
}
chan.enabled = true;
logger.log('Channel "%s" enabled!', name);
}
break;
case 'disable':
for (const name of args.slice(1)) {
}),
cmd('disable', async (...args: string[]): Promise<void> => {
for (const name of args) {
const chan = this.bot.channelManager.getChannelByName(name);
if (!chan) {
logger.error('No such channel "%s" exists!', name);
return;
throw new Error(`No such channel "${name}" found.`);
}
chan.enabled = false;
logger.log('Channel "%s" disabled!', name);
}
break;
}
}),
cmd('list', async (...args: string[]): Promise<void> => {
logger.log('Channels:\n', this.bot.channelManager.getAll().map((chan) => {
return ` => ${chan.name}: ${chan.plugins.join(', ')} (${chan.enabled ? 'enabled' : 'disabled'})`;
}).join('\n'));
}),
], async (r: any, ...args: string[]): Promise<any> => {
// Don't save when we just printed help or a list
if (!args.length || 'list'.startsWith(args[0])) {
return r;
}
// Save current channel configuration
this.bot.config.config.channels = this.bot.channelManager.getAll();
await this.bot.config.save();
return r;
}),
// Enter inspector mode. Every line entered will be executed as JavaScript.
cmd('inspector', async (...args: string[]): Promise<void> => {
this.inspector = true;
logger.warn('You have entered the JavaScript Inspector!');
console.log('Squeebot is available via "sb" or "this.bot".');
console.log('Type "exit" or "quit" to leave the inspector mode.');
}),
];
this.bot.config.config.channels = this.bot.channelManager.getAll();
await this.bot.config.save();
constructor(private bot: Squeebot) {}
private getCommand(name: string): CLICommand | undefined {
return this.cmds.find(c => c.name.startsWith(name));
}
private async checkUpdate(repo: IRepository): Promise<void> {
const updatable = await this.bot.repositoryManager.checkForUpdates(repo);
if (updatable.length) {
logger.log('[%s] The following plugins can be updated:', repo.name,
updatable.map((u) => u.name).join(', '));
} else {
logger.log('[%s] All plugins are up-to-date!', repo.name);
}
}
private async sequentialExecute(cmds: string[][]): Promise<void> {
for (const argv of cmds) {
if (!argv[0]) {
logger.log('Available CLI Commands:', this.cmds
.map(c => `(${c.name.charAt(0)})${c.name.substr(1)}`)
.join(', '));
continue;
}
const clicmd = this.getCommand(argv[0]);
if (!clicmd) {
continue;
}
await clicmd.execute(argv.slice(1));
}
}
public attach(rl: ReadLine): void {
rl.on('line', (line: string) => {
const split = line.split(' ');
if (!split[0]) {
// Inspector mode
if (this.inspector) {
if (line.startsWith('exit') || line.startsWith('quit')) {
this.inspector = false;
logger.warn('You have exited the JavaScript Inspector!');
return;
}
const sb = this.bot;
try {
// tslint:disable-next-line: no-eval
console.log(eval(line));
} catch (e) {
console.error(e.stack);
}
return;
}
switch (split[0]) {
case 'r':
case 'repo':
case 'repository':
this.repositoryCommand(...split.slice(1)).catch(
e => logger.error(e.message));
break;
case 'p':
case 'pl':
case 'plugin':
this.pluginCommand(...split.slice(1)).catch(
e => logger.error(e.message));
break;
case 'c':
case 'chan':
case 'channel':
this.channelCommand(...split.slice(1)).catch(
e => logger.error(e.message));
break;
case 'stop':
case 'exit':
case 'quit':
case 'shutdown':
this.bot.shutdown();
break;
}
// Executing commands in order. If previous command fails, the rest won't execute.
const executeList = line.split('&&');
const toRun = executeList.map(subline => {
return subline
.replace(/\s+/g, ' ')
.replace(/^\s+|\s+$/, '')
.split(' ')
.map(l => l.replace(',', ''));
});
this.sequentialExecute(toRun).catch(e => logger.error(e.message));
});
}
}