mirror of
https://git.bits.team/Bits/mod-manager.git
synced 2024-11-13 18:08:22 -05:00
Added downloading mods from Modrinth
This commit is contained in:
parent
7774386385
commit
765920f80c
335
package-lock.json
generated
335
package-lock.json
generated
@ -12,7 +12,10 @@
|
||||
"axios": "^0.27.2",
|
||||
"chalk": "^5.0.1",
|
||||
"commander": "^9.4.0",
|
||||
"ora": "^6.1.2"
|
||||
"error": "^10.4.0",
|
||||
"ora": "^6.1.2",
|
||||
"pretty-error": "^4.0.0",
|
||||
"string-format": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.6.3",
|
||||
@ -79,6 +82,11 @@
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||
},
|
||||
"node_modules/buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
@ -165,6 +173,32 @@
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/css-select": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
|
||||
"integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^6.0.1",
|
||||
"domhandler": "^4.3.1",
|
||||
"domutils": "^2.8.0",
|
||||
"nth-check": "^2.0.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/css-what": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
},
|
||||
"node_modules/defaults": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
|
||||
@ -181,6 +215,78 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-converter": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
|
||||
"integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
|
||||
"dependencies": {
|
||||
"utila": "~0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/error": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/error/-/error-10.4.0.tgz",
|
||||
"integrity": "sha512-YxIFEJuhgcICugOUvRx5th0UM+ActZ9sjY0QJmeVwsQdvosZ7kYzc9QqS0Da3R5iUmgU5meGIxh0xBeZpMVeLw=="
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
|
||||
@ -213,6 +319,24 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.0.0",
|
||||
"domutils": "^2.5.2",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
@ -259,6 +383,11 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/log-symbols": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz",
|
||||
@ -301,6 +430,17 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||
"dependencies": {
|
||||
"boolbase": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/nth-check?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
@ -337,6 +477,15 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-error": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
|
||||
"integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.20",
|
||||
"renderkid": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
@ -350,6 +499,37 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/renderkid": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
|
||||
"integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==",
|
||||
"dependencies": {
|
||||
"css-select": "^4.1.3",
|
||||
"dom-converter": "^0.2.0",
|
||||
"htmlparser2": "^6.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"strip-ansi": "^6.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/renderkid/node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/renderkid/node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
|
||||
@ -397,6 +577,11 @@
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/string-format": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz",
|
||||
"integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA=="
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
|
||||
@ -429,6 +614,11 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"node_modules/utila": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
|
||||
"integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA=="
|
||||
},
|
||||
"node_modules/wcwidth": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||
@ -479,6 +669,11 @@
|
||||
"readable-stream": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
|
||||
},
|
||||
"buffer": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
|
||||
@ -524,6 +719,23 @@
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz",
|
||||
"integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw=="
|
||||
},
|
||||
"css-select": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
|
||||
"integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^6.0.1",
|
||||
"domhandler": "^4.3.1",
|
||||
"domutils": "^2.8.0",
|
||||
"nth-check": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"css-what": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
|
||||
},
|
||||
"defaults": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
|
||||
@ -537,6 +749,57 @@
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="
|
||||
},
|
||||
"dom-converter": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
|
||||
"integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
|
||||
"requires": {
|
||||
"utila": "~0.4"
|
||||
}
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.2.0",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||
"requires": {
|
||||
"dom-serializer": "^1.0.1",
|
||||
"domelementtype": "^2.2.0",
|
||||
"domhandler": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
|
||||
},
|
||||
"error": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/error/-/error-10.4.0.tgz",
|
||||
"integrity": "sha512-YxIFEJuhgcICugOUvRx5th0UM+ActZ9sjY0QJmeVwsQdvosZ7kYzc9QqS0Da3R5iUmgU5meGIxh0xBeZpMVeLw=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.1",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
|
||||
@ -552,6 +815,17 @@
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^4.0.0",
|
||||
"domutils": "^2.5.2",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"ieee754": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
|
||||
@ -572,6 +846,11 @@
|
||||
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.2.0.tgz",
|
||||
"integrity": "sha512-wH+U77omcRzevfIG8dDhTS0V9zZyweakfD01FULl97+0EHiJTTZtJqxPSkIIo/SDPv/i07k/C9jAPY+jwLLeUQ=="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"log-symbols": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz",
|
||||
@ -599,6 +878,14 @@
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"onetime": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
|
||||
@ -623,6 +910,15 @@
|
||||
"wcwidth": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"pretty-error": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
|
||||
"integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==",
|
||||
"requires": {
|
||||
"lodash": "^4.17.20",
|
||||
"renderkid": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||
@ -633,6 +929,33 @@
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"renderkid": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
|
||||
"integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==",
|
||||
"requires": {
|
||||
"css-select": "^4.1.3",
|
||||
"dom-converter": "^0.2.0",
|
||||
"htmlparser2": "^6.1.0",
|
||||
"lodash": "^4.17.21",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
|
||||
@ -660,6 +983,11 @@
|
||||
"safe-buffer": "~5.2.0"
|
||||
}
|
||||
},
|
||||
"string-format": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz",
|
||||
"integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA=="
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
|
||||
@ -679,6 +1007,11 @@
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"utila": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
|
||||
"integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA=="
|
||||
},
|
||||
"wcwidth": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
|
||||
|
@ -14,7 +14,10 @@
|
||||
"axios": "^0.27.2",
|
||||
"chalk": "^5.0.1",
|
||||
"commander": "^9.4.0",
|
||||
"ora": "^6.1.2"
|
||||
"error": "^10.4.0",
|
||||
"ora": "^6.1.2",
|
||||
"pretty-error": "^4.0.0",
|
||||
"string-format": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^18.6.3",
|
||||
|
19
src/commands/install_command.ts
Normal file
19
src/commands/install_command.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Command } from "commander";
|
||||
import Subcommand from "./subcommand.js"
|
||||
import ModManager from "../mod-manager.js";
|
||||
import Mods from "../mods/mods.js";
|
||||
|
||||
export default class InstallCommand implements Subcommand {
|
||||
registerCommand(program: Command): void {
|
||||
program.command("install")
|
||||
.description("Installs the provided mods")
|
||||
.argument("<mods...>", "The mods to install")
|
||||
.action((mods) => {
|
||||
ModManager.execute(async () => {
|
||||
for (const mod of mods) {
|
||||
await Mods.install(mod);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
import { Command } from "commander";
|
||||
|
||||
export default abstract class Subcommand {
|
||||
abstract registerCommand(program: Command): void;
|
||||
abstract execute(): void;
|
||||
export default interface Subcommand {
|
||||
registerCommand(program: Command): void;
|
||||
}
|
7
src/errors/download_error.ts
Normal file
7
src/errors/download_error.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export default class DownloadError extends Error {
|
||||
constructor(message: string | undefined) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
7
src/errors/mod_not_found_error.ts
Normal file
7
src/errors/mod_not_found_error.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export default class ModNotFoundError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
}
|
||||
}
|
8
src/io/download_task.d.ts
vendored
Normal file
8
src/io/download_task.d.ts
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
declare global {
|
||||
type DownloadTask = {
|
||||
fileName: string,
|
||||
url: string
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
21
src/io/file_downloder.ts
Normal file
21
src/io/file_downloder.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import path from "path";
|
||||
import * as https from "https";
|
||||
import {createWriteStream} from "fs";
|
||||
import DownloadError from "../errors/download_error.js";
|
||||
|
||||
|
||||
export default class FileDownloader {
|
||||
private static readonly MODS_FOLDER_PATH: string = path.join("mods");
|
||||
|
||||
static downloadMod(task: DownloadTask): void {
|
||||
https.get(task.url, res => {
|
||||
const filePath = path.join(this.MODS_FOLDER_PATH, task.fileName);
|
||||
const writeStream = createWriteStream(filePath);
|
||||
res.pipe(writeStream);
|
||||
writeStream.on("finish", () => writeStream.close());
|
||||
writeStream.on('error', () => {
|
||||
throw new DownloadError(`Failed to download ${task.fileName} from ${task.url}`)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
@ -1,25 +1,31 @@
|
||||
#!/usr/bin/env node
|
||||
import { Command } from "commander";
|
||||
import InitCommand from "./commands/init_command.js";
|
||||
import InstallCommand from "./commands/install_command.js";
|
||||
import Subcommand from "./commands/subcommand.js";
|
||||
import Initialiser from "./util/initialiser.js";
|
||||
import PrintUtils from "./util/print_utils.js";
|
||||
//import PrettyError from "pretty-error";
|
||||
|
||||
export default class ModManager {
|
||||
private static program: Command = new Command();
|
||||
|
||||
private static subcommands: Array<Subcommand> = [
|
||||
new InitCommand()
|
||||
new InitCommand(),
|
||||
new InstallCommand()
|
||||
];
|
||||
|
||||
static init() {
|
||||
//const pe = new PrettyError();
|
||||
//pe.start();
|
||||
|
||||
this.program
|
||||
.name('mod-manager')
|
||||
.description('A package (mod) manager for Fabric Minecraft Servers');
|
||||
|
||||
this.subcommands.forEach(command => {
|
||||
command.registerCommand(ModManager.program);
|
||||
});
|
||||
for (const command of this.subcommands) {
|
||||
command.registerCommand(this.program);
|
||||
}
|
||||
|
||||
this.program.parse();
|
||||
}
|
||||
@ -30,10 +36,9 @@ export default class ModManager {
|
||||
} else {
|
||||
PrintUtils.error("Mod Manager is not initialised");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ModManager.init();
|
||||
|
||||
|
||||
|
51
src/mods/mods.ts
Normal file
51
src/mods/mods.ts
Normal file
@ -0,0 +1,51 @@
|
||||
|
||||
import path from "path";
|
||||
import Initialiser from "../util/initialiser.js";
|
||||
import PrintUtils from "../util/print_utils.js";
|
||||
import ModrinthSource from "./sources/modrinth_source.js";
|
||||
import ModSource from "./sources/mod_source.js";
|
||||
import ModNotFoundError from "../errors/mod_not_found_error.js";
|
||||
|
||||
|
||||
export default class Mods {
|
||||
public static readonly MOD_FILE = "mods.json";
|
||||
private static readonly MOD_SOURCES: Array<ModSource> = [
|
||||
new ModrinthSource()
|
||||
];
|
||||
|
||||
public static async install(mod: string): Promise<void> {
|
||||
let success: boolean = false;
|
||||
|
||||
// Go through each mod source
|
||||
for (const source of this.MOD_SOURCES) {
|
||||
// If we have not yet successfully installed the queried mod
|
||||
if (!success) {
|
||||
PrintUtils.info(`Searching for ${mod}...`);
|
||||
// Search for the mod
|
||||
let id;
|
||||
try {
|
||||
id = await source.search(mod);
|
||||
} catch (e) {
|
||||
if (e instanceof ModNotFoundError) {
|
||||
PrintUtils.info(`Mod not found on ${source.getName()}`);
|
||||
}
|
||||
}
|
||||
|
||||
// If a mod is found, install it
|
||||
if (id != undefined) {
|
||||
PrintUtils.info(`Installing ${mod}...`);
|
||||
try {
|
||||
await source.install(id);
|
||||
PrintUtils.success(`Successfully installed ${mod}`);
|
||||
} catch (e) {
|
||||
PrintUtils.error(`An error occurred downloading ${mod} from ${source.getName()}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static getModFilePath(): string {
|
||||
return path.join(Initialiser.getModManagerFolderPath(), this.MOD_FILE);
|
||||
}
|
||||
}
|
5
src/mods/sources/mod_source.ts
Normal file
5
src/mods/sources/mod_source.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export default interface ModSource {
|
||||
search(query: string): Promise<string>;
|
||||
install(id: string): Promise<void>;
|
||||
getName(): string;
|
||||
}
|
163
src/mods/sources/modrinth_source.ts
Normal file
163
src/mods/sources/modrinth_source.ts
Normal file
@ -0,0 +1,163 @@
|
||||
import ModSource from "./mod_source.js";
|
||||
import "string-format"
|
||||
import {format} from "util";
|
||||
import MinecraftUtils from "../../util/minecraft_utils.js";
|
||||
import axios from "axios";
|
||||
import ModNotFoundError from "../../errors/mod_not_found_error.js";
|
||||
import Util from "../../util/util.js";
|
||||
import FileDownloader from "../../io/file_downloder.js";
|
||||
import DownloadError from "../../errors/download_error.js";
|
||||
|
||||
export default class ModrinthSource implements ModSource {
|
||||
private static readonly BASE_URL: string = "https://api.modrinth.com/v2";
|
||||
private static readonly SEARCH_URL: string = ModrinthSource.BASE_URL + "/search";
|
||||
private static readonly INSTALL_URL: string = ModrinthSource.BASE_URL + "/project/%s/version";
|
||||
|
||||
/**
|
||||
* Searches Modrinth for the specified query
|
||||
* Example shape of data returned by query:
|
||||
* {
|
||||
* "hits": [
|
||||
* {
|
||||
* "project_id": "gvQqBUqZ",
|
||||
* "project_type": "mod",
|
||||
* "slug": "lithium",
|
||||
* "author": "jellysquid3",
|
||||
* "title": "Lithium",
|
||||
* "description": "No-compromises game logic/server optimization mod",
|
||||
* "categories": [
|
||||
* "optimization",
|
||||
* "fabric"
|
||||
* ],
|
||||
* "display_categories": [
|
||||
* "optimization",
|
||||
* "fabric"
|
||||
* ],
|
||||
* "versions": [
|
||||
* "1.16.2",
|
||||
* "1.16.3",
|
||||
* "1.16.4",
|
||||
* "1.16.5",
|
||||
* "1.17",
|
||||
* "1.17.1",
|
||||
* "1.18",
|
||||
* "1.18.1",
|
||||
* "1.18.2",
|
||||
* "1.19",
|
||||
* "1.19.1"
|
||||
* ],
|
||||
* "downloads": 223103,
|
||||
* "follows": 1866,
|
||||
* "icon_url": "https://cdn.modrinth.com/data/gvQqBUqZ/icon.png",
|
||||
* "date_created": "2021-01-03T00:56:52.292581Z",
|
||||
* "date_modified": "2022-07-29T22:18:05.703354Z",
|
||||
* "latest_version": "1.19.1",
|
||||
* "license": "lgpl-3",
|
||||
* "client_side": "optional",
|
||||
* "server_side": "optional",
|
||||
* "gallery": []
|
||||
* }
|
||||
* ],
|
||||
* "offset": 0,
|
||||
* "limit": 1,
|
||||
* "total_hits": 1
|
||||
* }
|
||||
* @param query the query to search for
|
||||
* @throws ModNotFoundError if the query returns no results.
|
||||
* @returns The mod id of the found mod
|
||||
*/
|
||||
async search(query: string): Promise<string> | never {
|
||||
const mcVersion = await MinecraftUtils.getCurrentMinecraftVersion();
|
||||
|
||||
const params = {
|
||||
query: query,
|
||||
limit: 1,
|
||||
facets: format('[["categories:fabric"],["versions:%s"]]', mcVersion)
|
||||
}
|
||||
|
||||
const response = await axios.get(ModrinthSource.SEARCH_URL, {params});
|
||||
const results = await response.data.hits;
|
||||
|
||||
if (Util.isArrayEmpty(results)) {
|
||||
throw new ModNotFoundError(`Mod ${query} could not be found on ${this.getName()}`);
|
||||
}
|
||||
|
||||
return results[0].project_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the mod with the provided mod id
|
||||
* Example shape of data returned by query:
|
||||
* [
|
||||
* {
|
||||
* "id": "ZRR9yqHD",
|
||||
* "project_id": "gvQqBUqZ",
|
||||
* "author_id": "uhPSqlnd",
|
||||
* "featured": false,
|
||||
* "name": "Lithium 0.8.3",
|
||||
* "version_number": "mc1.19.1-0.8.3",
|
||||
* "changelog": "Lithium 0.8.3 is the second release for 1.19.1! It includes a bugfix too!\n\n## Fixes\n- fix: update chunk serialization patch to new mappings\n\nYou can donate on patreon: https://www.patreon.com/2No2Name\n",
|
||||
* "changelog_url": null,
|
||||
* "date_published": "2022-07-29T22:18:09.072973Z",
|
||||
* "downloads": 3592,
|
||||
* "version_type": "release",
|
||||
* "files": [
|
||||
* {
|
||||
* "hashes": {
|
||||
* "sha1": "9ef9f10f62d4c19b736fe493f2a11d737fbe3d7c",
|
||||
* "sha512": "a3b623b4c14f6ba46d1486ffb3d1ba3174e3317b419b2ddfdf7bb572244e706d2e0a37bdce169c94455bec00fd107530ba78d7e611162a632cc6950e6a625433"
|
||||
* },
|
||||
* "url": "https://cdn.modrinth.com/data/gvQqBUqZ/versions/mc1.19.1-0.8.3/lithium-fabric-mc1.19.1-0.8.3.jar",
|
||||
* "filename": "lithium-fabric-mc1.19.1-0.8.3.jar",
|
||||
* "primary": true,
|
||||
* "size": 476619
|
||||
* }
|
||||
* ],
|
||||
* "dependencies": [],
|
||||
* "game_versions": [
|
||||
* "1.19.1"
|
||||
* ],
|
||||
* "loaders": [
|
||||
* "fabric"
|
||||
* ]
|
||||
* }
|
||||
* ]
|
||||
* @param id the id of the mod
|
||||
* @throws DownloadError if an error occurs when downloading
|
||||
* @throws ModNotFoundError if there are no versions available for the current Minecraft Version
|
||||
*/
|
||||
async install(id: string): Promise<void> {
|
||||
const mcVersion = await MinecraftUtils.getCurrentMinecraftVersion();
|
||||
|
||||
const params = {
|
||||
loaders: '["fabric"]',
|
||||
game_versions: format('["%s"]', mcVersion)
|
||||
}
|
||||
|
||||
const response = await axios.get(format(ModrinthSource.INSTALL_URL, id), {params});
|
||||
const results = await response.data;
|
||||
|
||||
if (Util.isArrayEmpty(results)) {
|
||||
throw new ModNotFoundError(`Mod with id ${id} has no available versions on ${this.getName()} for Minecraft version ${mcVersion}`);
|
||||
}
|
||||
|
||||
const latestFile = results[0].files[0];
|
||||
|
||||
const task: DownloadTask = {
|
||||
fileName: latestFile.filename,
|
||||
url: latestFile.url
|
||||
}
|
||||
|
||||
try {
|
||||
FileDownloader.downloadMod(task)
|
||||
} catch (e) {
|
||||
throw new DownloadError(`An error occurred downloading mod with id ${id} from ${this.getName()}`)
|
||||
}
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return "Modrinth";
|
||||
}
|
||||
|
||||
|
||||
}
|
44
src/util/minecraft_utils.ts
Normal file
44
src/util/minecraft_utils.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import {readdirSync} from "fs";
|
||||
import path from "path";
|
||||
import axios from "axios";
|
||||
|
||||
export default class MinecraftUtils {
|
||||
static async getCurrentMinecraftVersion(): Promise<string> {
|
||||
// Get installed versions as strings
|
||||
const installedVersions: Array<string> = readdirSync(this.getVersionsFolderPath(), {withFileTypes: true})
|
||||
.filter(entry => entry.isDirectory())
|
||||
.map(entry => entry.name);
|
||||
|
||||
// Get a list of Minecraft Versions
|
||||
const response = await axios.get("https://meta.fabricmc.net/v2/versions/game");
|
||||
const data = await response.data;
|
||||
|
||||
const minecraftVersions: Array<string> = [];
|
||||
for (const ele of data) {
|
||||
minecraftVersions.push(ele.version);
|
||||
}
|
||||
|
||||
// Find the latest version that is currently installed
|
||||
let index = Number.MAX_VALUE;
|
||||
for (let version of installedVersions) {
|
||||
let currentIndex = minecraftVersions.indexOf(version);
|
||||
|
||||
// If this version, is newer than the previous newest, save it's index
|
||||
if (currentIndex < index) {
|
||||
index = currentIndex;
|
||||
}
|
||||
}
|
||||
|
||||
const latestVersion = minecraftVersions[index];
|
||||
if (latestVersion == undefined) {
|
||||
throw new Error("There are no Minecraft versions available in this server. Is this a valid server installation?");
|
||||
}
|
||||
|
||||
return latestVersion;
|
||||
}
|
||||
|
||||
static getVersionsFolderPath(): string {
|
||||
return path.join("versions")
|
||||
}
|
||||
}
|
||||
|
5
src/util/util.ts
Normal file
5
src/util/util.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export default class Util {
|
||||
static isArrayEmpty(array: Array<any> | undefined): boolean {
|
||||
return array === undefined || array.length == 0;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user