Prepare v1.0.0

This commit is contained in:
Moritz Ruth 2022-08-16 19:16:23 +02:00
parent 6345c7e151
commit 1fbb3e2142
12 changed files with 947 additions and 176 deletions

View file

@ -1,2 +1,91 @@
# Horizr CLI
> A CLI tool for creating Minecraft modpacks, primarily using the Fabric and Quilt loaders.
🎉 Features:
- Search for mods on [Modrinth](https://modrinth.com/)
- Add mods from Modrinth
- View available (compatible) versions of mods from Modrinth
- View dependencies of specific mod versions
- Check for updates and view changelogs before applying them
- Export the pack to the [`packwiz`](https://packwiz.infra.link/) format
- HTTP-serve the `packwiz` export for usage with [`packwiz-installer`](https://packwiz.infra.link/tutorials/installing/packwiz-installer/)
- Export the pack to the [Modrinth format (`.mrpack`)](https://docs.modrinth.com/docs/modpacks/format_definition/)
## Usage
Because both [pkg](https://github.com/vercel/pkg) and [nexe](https://github.com/nexe/nexe) dont support ES modules at the time of writing,
I cant publish executable files.
The only way of installing is therefore `npm`.
```sh
$ npm i -g @horizr/cli
```
Run any command with the `-h` flag to see the available options.
## Examples
- Activate the latest (compatible) version of [Charm](https://modrinth.com/mod/charm)
```sh
$ horizr modrinth mod activate charm
# or short:
$ horizr mr mod a charm
```
- Activate `v4.1.1` of [Charm](https://modrinth.com/mod/charm)
```sh
$ horizr modrinth mod versions charm
# `BT9G1Jjs` is the version code you are looking for.
# This output will be colored in your console.
BT9G1Jjs 4.2.0+1.18.2 (↓ 137)
featured
Name: [1.18.2] 4.2.0
Channel: release
Minecraft versions: 1.18.2
Publication: last week
https://modrinth.com/mod/pOQTcQmj/version/BT9G1Jjs
# … more versions omitted for brevity
$ horizr modrinth version activate BT9G1Jjs
Charm (4.2.0+1.18.2) was successfully activated.
Dependencies
◉ Fabric API (P7dR8mSH): any version
```
- Check for updates
```sh
$ horizr update
# Because Sodium's version string is not a valid SemVer,
# the publication date will instead be used for comparison.
Sodium has no valid semantic version: mc1.18.2-0.4.1. The
publication date will instead be used.
Available updates
- charm Charm: 4.1.0+1.18.2 → 4.2.0+1.18.2
```
```sh
$ horizr update charm
Changelog for 4.2.0+1.18.2
* Added ebony wood.
* Fixed issue with Totems not always spawning or being
carried away by mobs.
# … omitted for brevity
Apply the update? [Y/n] y
Successfully updated Charm to 4.2.0+1.18.2.
```

3
bin/horizr.js Executable file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env node
import('../dist/main.js')

View file

@ -1,26 +1,22 @@
{
"name": "horizr-cli",
"name": "@horizr/cli",
"version": "1.0.0",
"private": true,
"main": "./src/main.ts",
"main": "./dist/main.ts",
"type": "module",
"license": "MIT",
"author": "Moritz Ruth <dev@moritzruth.de>",
"repository": "https://github.com/horizr/cli",
"scripts": {
"start": "tsx .",
"build": "tsc"
},
"oclif": {
"bin": "horizr",
"dirname": "horizr",
"commands": "./dist/commands",
"plugins": [
"@oclif/plugin-plugins"
],
"topicSeparator": " "
"start": "tsx src/main.ts",
"build": "del dist && tsc"
},
"bin": {
"horizr": "./bin/horizr"
"horizr": "bin/horizr.js"
},
"files": [
"dist",
"bin"
],
"dependencies": {
"@root/walk": "^1.1.0",
"address": "^1.2.0",
@ -45,6 +41,7 @@
"serve-handler": "^6.1.3",
"wrap-ansi": "^8.0.1",
"yazl": "^2.5.1",
"yesno": "^0.4.0",
"zod": "^3.18.0"
},
"devDependencies": {
@ -56,6 +53,7 @@
"@types/serve-handler": "^6.1.1",
"@types/wrap-ansi": "^8.0.1",
"@types/yazl": "^2.4.2",
"del-cli": "^5.0.0",
"tsx": "^3.8.2",
"type-fest": "^2.18.0",
"typescript": "^4.7.4"

619
pnpm-lock.yaml generated
View file

@ -13,6 +13,7 @@ specifiers:
address: ^1.2.0
commander: ^9.4.0
dedent: ^0.7.0
del-cli: ^5.0.0
env-paths: ^3.0.0
figures: ^5.0.0
find-up: ^6.3.0
@ -35,6 +36,7 @@ specifiers:
typescript: ^4.7.4
wrap-ansi: ^8.0.1
yazl: ^2.5.1
yesno: ^0.4.0
zod: ^3.18.0
dependencies:
@ -61,6 +63,7 @@ dependencies:
serve-handler: 6.1.3
wrap-ansi: 8.0.1
yazl: 2.5.1
yesno: 0.4.0
zod: 3.18.0
devDependencies:
@ -72,12 +75,34 @@ devDependencies:
'@types/serve-handler': 6.1.1
'@types/wrap-ansi': 8.0.1
'@types/yazl': 2.4.2
del-cli: 5.0.0
tsx: 3.8.2
type-fest: 2.18.0
typescript: 4.7.4
packages:
/@babel/code-frame/7.18.6:
resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.18.6
dev: true
/@babel/helper-validator-identifier/7.18.6:
resolution: {integrity: sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/highlight/7.18.6:
resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.18.6
chalk: 2.4.2
js-tokens: 4.0.0
dev: true
/@esbuild-kit/cjs-loader/2.3.3:
resolution: {integrity: sha512-Rt4O1mXlPEDVxvjsHLgbtHVdUXYK9C1/6ThpQnt7FaXIjUOsI6qhHYMgALhNnlIMZffag44lXd6Dqgx3xALbpQ==}
dependencies:
@ -108,6 +133,27 @@ packages:
dev: true
optional: true
/@nodelib/fs.scandir/2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
dependencies:
'@nodelib/fs.stat': 2.0.5
run-parallel: 1.2.0
dev: true
/@nodelib/fs.stat/2.0.5:
resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
engines: {node: '>= 8'}
dev: true
/@nodelib/fs.walk/1.2.8:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
dependencies:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.13.0
dev: true
/@root/walk/1.1.0:
resolution: {integrity: sha512-FfXPAta9u2dBuaXhPRawBcijNC9rmKVApmbi6lIZyg36VR/7L02ytxoY5K/14PJlHqiBUoYII73cTlekdKTUOw==}
dev: false
@ -167,9 +213,17 @@ packages:
resolution: {integrity: sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==}
dev: true
/@types/minimist/1.2.2:
resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
dev: true
/@types/node/18.7.3:
resolution: {integrity: sha512-LJgzOEwWuMTBxHzgBR/fhhBOWrvBjvO+zPteUgbbuQi80rYIZHrk1mNbRUqPZqSLP2H7Rwt1EFLL/tNLD1Xx/w==}
/@types/normalize-package-data/2.4.1:
resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
dev: true
/@types/responselike/1.0.0:
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
dependencies:
@ -201,11 +255,26 @@ packages:
engines: {node: '>= 10.0.0'}
dev: false
/aggregate-error/4.0.1:
resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==}
engines: {node: '>=12'}
dependencies:
clean-stack: 4.2.0
indent-string: 5.0.0
dev: true
/ansi-regex/6.0.1:
resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
engines: {node: '>=12'}
dev: false
/ansi-styles/3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
dependencies:
color-convert: 1.9.3
dev: true
/ansi-styles/6.1.0:
resolution: {integrity: sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==}
engines: {node: '>=12'}
@ -216,9 +285,13 @@ packages:
engines: {node: '>=0.10.0'}
dev: false
/arrify/1.0.1:
resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==}
engines: {node: '>=0.10.0'}
dev: true
/balanced-match/1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: false
/base64-js/1.5.1:
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
@ -237,7 +310,13 @@ packages:
dependencies:
balanced-match: 1.0.2
concat-map: 0.0.1
dev: false
/braces/3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
dependencies:
fill-range: 7.0.1
dev: true
/buffer-crc32/0.2.13:
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
@ -277,11 +356,42 @@ packages:
responselike: 2.0.1
dev: false
/camelcase-keys/7.0.2:
resolution: {integrity: sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==}
engines: {node: '>=12'}
dependencies:
camelcase: 6.3.0
map-obj: 4.3.0
quick-lru: 5.1.1
type-fest: 1.4.0
dev: true
/camelcase/6.3.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
dev: true
/chalk/2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
dependencies:
ansi-styles: 3.2.1
escape-string-regexp: 1.0.5
supports-color: 5.5.0
dev: true
/chalk/5.0.1:
resolution: {integrity: sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w==}
engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
dev: false
/clean-stack/4.2.0:
resolution: {integrity: sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==}
engines: {node: '>=12'}
dependencies:
escape-string-regexp: 5.0.0
dev: true
/cli-cursor/4.0.0:
resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -305,6 +415,16 @@ packages:
engines: {node: '>=0.8'}
dev: false
/color-convert/1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
color-name: 1.1.3
dev: true
/color-name/1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: true
/commander/9.4.0:
resolution: {integrity: sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==}
engines: {node: ^12.20.0 || >=14}
@ -320,7 +440,6 @@ packages:
/concat-map/0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
dev: false
/content-disposition/0.5.2:
resolution: {integrity: sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==}
@ -346,6 +465,24 @@ packages:
ms: 2.1.2
dev: false
/decamelize-keys/1.1.0:
resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==}
engines: {node: '>=0.10.0'}
dependencies:
decamelize: 1.2.0
map-obj: 1.0.1
dev: true
/decamelize/1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
dev: true
/decamelize/5.0.1:
resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==}
engines: {node: '>=10'}
dev: true
/decompress-response/6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
@ -368,6 +505,36 @@ packages:
engines: {node: '>=10'}
dev: false
/del-cli/5.0.0:
resolution: {integrity: sha512-rENFhUaYcjoMODwFhhlON+ogN7DoG+4+GFN+bsA1XeDt4w2OKQnQadFP1thHSAlK9FAtl88qgP66wOV+eFZZiQ==}
engines: {node: '>=14.16'}
hasBin: true
dependencies:
del: 7.0.0
meow: 10.1.3
dev: true
/del/7.0.0:
resolution: {integrity: sha512-tQbV/4u5WVB8HMJr08pgw0b6nG4RGt/tj+7Numvq+zqcvUFeMaIWWOUFltiU+6go8BSO2/ogsB4EasDaj0y68Q==}
engines: {node: '>=14.16'}
dependencies:
globby: 13.1.2
graceful-fs: 4.2.10
is-glob: 4.0.3
is-path-cwd: 3.0.0
is-path-inside: 4.0.0
p-map: 5.5.0
rimraf: 3.0.2
slash: 4.0.0
dev: true
/dir-glob/3.0.1:
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
engines: {node: '>=8'}
dependencies:
path-type: 4.0.0
dev: true
/eastasianwidth/0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: false
@ -387,6 +554,12 @@ packages:
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: false
/error-ex/1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
dependencies:
is-arrayish: 0.2.1
dev: true
/esbuild-android-64/0.14.54:
resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==}
engines: {node: '>=12'}
@ -596,10 +769,25 @@ packages:
esbuild-windows-arm64: 0.14.54
dev: true
/escape-string-regexp/1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
dev: true
/escape-string-regexp/5.0.0:
resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
engines: {node: '>=12'}
dev: false
/fast-glob/3.2.11:
resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==}
engines: {node: '>=8.6.0'}
dependencies:
'@nodelib/fs.stat': 2.0.5
'@nodelib/fs.walk': 1.2.8
glob-parent: 5.1.2
merge2: 1.4.1
micromatch: 4.0.5
dev: true
/fast-url-parser/1.1.3:
resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==}
@ -607,6 +795,12 @@ packages:
punycode: 1.4.1
dev: false
/fastq/1.13.0:
resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
dependencies:
reusify: 1.0.4
dev: true
/figures/5.0.0:
resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==}
engines: {node: '>=14'}
@ -615,6 +809,21 @@ packages:
is-unicode-supported: 1.2.0
dev: false
/fill-range/7.0.1:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
dependencies:
to-regex-range: 5.0.1
dev: true
/find-up/5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
dependencies:
locate-path: 6.0.0
path-exists: 4.0.0
dev: true
/find-up/6.3.0:
resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -645,6 +854,10 @@ packages:
universalify: 0.1.2
dev: false
/fs.realpath/1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: true
/fsevents/2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@ -653,6 +866,10 @@ packages:
dev: true
optional: true
/function-bind/1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: true
/get-stream/5.2.0:
resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
engines: {node: '>=8'}
@ -669,6 +886,35 @@ packages:
resolution: {integrity: sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==}
dev: true
/glob-parent/5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'}
dependencies:
is-glob: 4.0.3
dev: true
/glob/7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
dev: true
/globby/13.1.2:
resolution: {integrity: sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
dir-glob: 3.0.1
fast-glob: 3.2.11
ignore: 5.2.0
merge2: 1.4.1
slash: 4.0.0
dev: true
/got/12.3.1:
resolution: {integrity: sha512-tS6+JMhBh4iXMSXF6KkIsRxmloPln31QHDlcb6Ec3bzxjjFJFr/8aXdpyuLmVc9I4i2HyBHYw1QU5K1ruUdpkw==}
engines: {node: '>=14.16'}
@ -690,7 +936,23 @@ packages:
/graceful-fs/4.2.10:
resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==}
dev: false
/hard-rejection/2.1.0:
resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
engines: {node: '>=6'}
dev: true
/has-flag/3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'}
dev: true
/has/1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
dependencies:
function-bind: 1.1.1
dev: true
/hasha/5.2.2:
resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==}
@ -700,6 +962,13 @@ packages:
type-fest: 0.8.1
dev: false
/hosted-git-info/4.1.0:
resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
engines: {node: '>=10'}
dependencies:
lru-cache: 6.0.0
dev: true
/http-cache-semantics/4.1.0:
resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==}
dev: false
@ -716,15 +985,73 @@ packages:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
dev: false
/ignore/5.2.0:
resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==}
engines: {node: '>= 4'}
dev: true
/indent-string/5.0.0:
resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==}
engines: {node: '>=12'}
dev: true
/inflight/1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies:
once: 1.4.0
wrappy: 1.0.2
dev: true
/inherits/2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: false
/is-arrayish/0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
dev: true
/is-core-module/2.10.0:
resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==}
dependencies:
has: 1.0.3
dev: true
/is-extglob/2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
dev: true
/is-glob/4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
dependencies:
is-extglob: 2.1.1
dev: true
/is-interactive/2.0.0:
resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==}
engines: {node: '>=12'}
dev: false
/is-number/7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
dev: true
/is-path-cwd/3.0.0:
resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: true
/is-path-inside/4.0.0:
resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==}
engines: {node: '>=12'}
dev: true
/is-plain-obj/1.1.0:
resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
engines: {node: '>=0.10.0'}
dev: true
/is-stream/2.0.1:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
@ -735,10 +1062,18 @@ packages:
engines: {node: '>=12'}
dev: false
/js-tokens/4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true
/json-buffer/3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
dev: false
/json-parse-even-better-errors/2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
dev: true
/jsonfile/4.0.0:
resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
optionalDependencies:
@ -770,11 +1105,27 @@ packages:
json-buffer: 3.0.1
dev: false
/kind-of/6.0.3:
resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
engines: {node: '>=0.10.0'}
dev: true
/kleur/4.1.5:
resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==}
engines: {node: '>=6'}
dev: false
/lines-and-columns/1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true
/locate-path/6.0.0:
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
engines: {node: '>=10'}
dependencies:
p-locate: 5.0.0
dev: true
/locate-path/7.1.1:
resolution: {integrity: sha512-vJXaRMJgRVD3+cUZs3Mncj2mxpt5mP0EmNOsxRSZRMlbqjvxzDEOIUWXGmavo0ZC9+tNZCBLQ66reA11nbpHZg==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -817,7 +1168,47 @@ packages:
engines: {node: '>=10'}
dependencies:
yallist: 4.0.0
dev: false
/map-obj/1.0.1:
resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==}
engines: {node: '>=0.10.0'}
dev: true
/map-obj/4.3.0:
resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
engines: {node: '>=8'}
dev: true
/meow/10.1.3:
resolution: {integrity: sha512-0WL7RMCPPdUTE00+GxJjL4d5Dm6eUbmAzxlzywJWiRUKCW093owmZ7/q74tH9VI91vxw9KJJNxAcvdpxb2G4iA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dependencies:
'@types/minimist': 1.2.2
camelcase-keys: 7.0.2
decamelize: 5.0.1
decamelize-keys: 1.1.0
hard-rejection: 2.1.0
minimist-options: 4.1.0
normalize-package-data: 3.0.3
read-pkg-up: 8.0.0
redent: 4.0.0
trim-newlines: 4.0.2
type-fest: 1.4.0
yargs-parser: 20.2.9
dev: true
/merge2/1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
dev: true
/micromatch/4.0.5:
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
engines: {node: '>=8.6'}
dependencies:
braces: 3.0.2
picomatch: 2.3.1
dev: true
/mime-db/1.33.0:
resolution: {integrity: sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==}
@ -846,12 +1237,32 @@ packages:
engines: {node: '>=10'}
dev: false
/min-indent/1.0.1:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
dev: true
/minimatch/3.0.4:
resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==}
dependencies:
brace-expansion: 1.1.11
dev: false
/minimatch/3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
dependencies:
brace-expansion: 1.1.11
dev: true
/minimist-options/4.1.0:
resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
engines: {node: '>= 6'}
dependencies:
arrify: 1.0.1
is-plain-obj: 1.1.0
kind-of: 6.0.3
dev: true
/ms/2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: false
@ -862,6 +1273,16 @@ packages:
hasBin: true
dev: false
/normalize-package-data/3.0.3:
resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==}
engines: {node: '>=10'}
dependencies:
hosted-git-info: 4.1.0
is-core-module: 2.10.0
semver: 7.3.7
validate-npm-package-license: 3.0.4
dev: true
/normalize-url/6.1.0:
resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
engines: {node: '>=10'}
@ -871,7 +1292,6 @@ packages:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies:
wrappy: 1.0.2
dev: false
/onetime/5.1.2:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
@ -907,6 +1327,13 @@ packages:
p-timeout: 5.1.0
dev: false
/p-limit/3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
dependencies:
yocto-queue: 0.1.0
dev: true
/p-limit/4.0.0:
resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -914,6 +1341,13 @@ packages:
yocto-queue: 1.0.0
dev: false
/p-locate/5.0.0:
resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
engines: {node: '>=10'}
dependencies:
p-limit: 3.1.0
dev: true
/p-locate/6.0.0:
resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@ -921,16 +1355,43 @@ packages:
p-limit: 4.0.0
dev: false
/p-map/5.5.0:
resolution: {integrity: sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==}
engines: {node: '>=12'}
dependencies:
aggregate-error: 4.0.1
dev: true
/p-timeout/5.1.0:
resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==}
engines: {node: '>=12'}
dev: false
/parse-json/5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
dependencies:
'@babel/code-frame': 7.18.6
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
dev: true
/path-exists/4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
dev: true
/path-exists/5.0.0:
resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
dev: false
/path-is-absolute/1.0.1:
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
engines: {node: '>=0.10.0'}
dev: true
/path-is-inside/1.0.2:
resolution: {integrity: sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==}
dev: false
@ -939,6 +1400,16 @@ packages:
resolution: {integrity: sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==}
dev: false
/path-type/4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
dev: true
/picomatch/2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
dev: true
/pump/3.0.0:
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
dependencies:
@ -950,16 +1421,38 @@ packages:
resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==}
dev: false
/queue-microtask/1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true
/quick-lru/5.1.1:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'}
dev: false
/range-parser/1.2.0:
resolution: {integrity: sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==}
engines: {node: '>= 0.6'}
dev: false
/read-pkg-up/8.0.0:
resolution: {integrity: sha512-snVCqPczksT0HS2EC+SxUndvSzn6LRCwpfSvLrIfR5BKDQQZMaI6jPRC9dYvYFDRAuFEAnkwww8kBBNE/3VvzQ==}
engines: {node: '>=12'}
dependencies:
find-up: 5.0.0
read-pkg: 6.0.0
type-fest: 1.4.0
dev: true
/read-pkg/6.0.0:
resolution: {integrity: sha512-X1Fu3dPuk/8ZLsMhEj5f4wFAF0DWoK7qhGJvgaijocXxBmSToKfbFtqbxMO7bVjNA1dmE5huAzjXj/ey86iw9Q==}
engines: {node: '>=12'}
dependencies:
'@types/normalize-package-data': 2.4.1
normalize-package-data: 3.0.3
parse-json: 5.2.0
type-fest: 1.4.0
dev: true
/readable-stream/3.6.0:
resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==}
engines: {node: '>= 6'}
@ -969,6 +1462,14 @@ packages:
util-deprecate: 1.0.2
dev: false
/redent/4.0.0:
resolution: {integrity: sha512-tYkDkVVtYkSVhuQ4zBgfvciymHaeuel+zFKXShfDnFP5SyVEP7qo70Rf1jTOTCx3vGNAbnEi/xFkcfQVMIBWag==}
engines: {node: '>=12'}
dependencies:
indent-string: 5.0.0
strip-indent: 4.0.0
dev: true
/resolve-alpn/1.2.1:
resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
dev: false
@ -987,6 +1488,24 @@ packages:
signal-exit: 3.0.7
dev: false
/reusify/1.0.4:
resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
dev: true
/rimraf/3.0.2:
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
hasBin: true
dependencies:
glob: 7.2.3
dev: true
/run-parallel/1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
dependencies:
queue-microtask: 1.2.3
dev: true
/s-ago/2.2.0:
resolution: {integrity: sha512-t6Q/aFCCJSBf5UUkR/WH0mDHX8EGm2IBQ7nQLobVLsdxOlkryYMbOlwu2D4Cf7jPUp0v1LhfPgvIZNoi9k8lUA==}
dev: false
@ -1001,7 +1520,6 @@ packages:
hasBin: true
dependencies:
lru-cache: 6.0.0
dev: false
/serve-handler/6.1.3:
resolution: {integrity: sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==}
@ -1020,6 +1538,11 @@ packages:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
dev: false
/slash/4.0.0:
resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==}
engines: {node: '>=12'}
dev: true
/source-map-support/0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
dependencies:
@ -1032,6 +1555,28 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/spdx-correct/3.1.1:
resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==}
dependencies:
spdx-expression-parse: 3.0.1
spdx-license-ids: 3.0.11
dev: true
/spdx-exceptions/2.3.0:
resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
dev: true
/spdx-expression-parse/3.0.1:
resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
dependencies:
spdx-exceptions: 2.3.0
spdx-license-ids: 3.0.11
dev: true
/spdx-license-ids/3.0.11:
resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==}
dev: true
/string-width/5.1.2:
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
engines: {node: '>=12'}
@ -1054,6 +1599,32 @@ packages:
ansi-regex: 6.0.1
dev: false
/strip-indent/4.0.0:
resolution: {integrity: sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==}
engines: {node: '>=12'}
dependencies:
min-indent: 1.0.1
dev: true
/supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
dependencies:
has-flag: 3.0.0
dev: true
/to-regex-range/5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
dependencies:
is-number: 7.0.0
dev: true
/trim-newlines/4.0.2:
resolution: {integrity: sha512-GJtWyq9InR/2HRiLZgpIKv+ufIKrVrvjQWEj7PxAXNc5dwbNJkqhAUoAGgzRmULAnoOM5EIpveYd3J2VeSAIew==}
engines: {node: '>=12'}
dev: true
/tslib/1.14.1:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
dev: false
@ -1074,6 +1645,11 @@ packages:
engines: {node: '>=8'}
dev: false
/type-fest/1.4.0:
resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==}
engines: {node: '>=10'}
dev: true
/type-fest/2.18.0:
resolution: {integrity: sha512-pRS+/yrW5TjPPHNOvxhbNZexr2bS63WjrMU8a+VzEBhUi9Tz1pZeD+vQz3ut0svZ46P+SRqMEPnJmk2XnvNzTw==}
engines: {node: '>=12.20'}
@ -1099,6 +1675,13 @@ packages:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
dev: false
/validate-npm-package-license/3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
dependencies:
spdx-correct: 3.1.1
spdx-expression-parse: 3.0.1
dev: true
/wcwidth/1.0.1:
resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==}
dependencies:
@ -1116,11 +1699,14 @@ packages:
/wrappy/1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: false
/yallist/4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
dev: false
/yargs-parser/20.2.9:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
dev: true
/yazl/2.5.1:
resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==}
@ -1128,6 +1714,15 @@ packages:
buffer-crc32: 0.2.13
dev: false
/yesno/0.4.0:
resolution: {integrity: sha512-tdBxmHvbXPBKYIg81bMCB7bVeDmHkRzk5rVJyYYXurwKkHq/MCd8rz4HSJUP7hW0H2NlXiq8IFiWvYKEHhlotA==}
dev: false
/yocto-queue/0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
dev: true
/yocto-queue/1.0.0:
resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
engines: {node: '>=12.20'}

View file

@ -191,7 +191,8 @@ const modrinthVersionCommand = modrinthCommand.command("version")
modrinthVersionCommand.command("info <id>")
.description("Show information about the version.")
.action(async id => {
.option("-c, --changelog", "Show the changelog.")
.action(async (id, options) => {
const pack = await usePack()
const loader = output.startLoading("Fetching version information")
@ -244,6 +245,13 @@ modrinthVersionCommand.command("info <id>")
https://modrinth.com/mod/${modrinthMod.slug}/version/${modrinthVersion.versionString}
`)
if (options.changelog) {
output.println("")
output.println(kleur.underline("Changelog"))
if (modrinthVersion.changelog === null) output.println(kleur.gray("not available"))
else output.printlnWrapping(modrinthVersion.changelog)
}
})
modrinthVersionCommand.command("activate <id>")

View file

@ -1,5 +1,5 @@
import { Command } from "commander"
import { usePack } from "../pack.js"
import { Mod, usePack } from "../pack.js"
import fs from "fs-extra"
import dedent from "dedent"
import kleur from "kleur"
@ -9,12 +9,7 @@ import { Visitor, walk } from "@root/walk"
import { Path } from "../path.js"
const packwizCommand = new Command("packwiz")
interface IndexedFile {
path: string
sha512HashHex: string
isMeta: boolean
}
.alias("pw")
packwizCommand.command("import")
.description("Import a packwiz pack.")
@ -33,135 +28,177 @@ packwizCommand.command("serve")
if (!(await fs.pathExists(directoryPath.toString())))
output.failAndExit(`The ${kleur.yellow("packwiz")} directory does not exist. Generate it by running ${kleur.yellow("horizr packwiz export")}.`)
const lanAddress = await getLANAddress()
httpServeDirectory(directoryPath, options.port, options.expose, () => {
const localAddress = `http://localhost:${options.port}/pack.toml`
if (options.expose) {
output.println(dedent`
${kleur.green("Serving at")}
Local: ${kleur.yellow(localAddress)}
Network: ${kleur.yellow(`http://${lanAddress}:${options.port}/pack.toml`)}
`)
}
else output.println(`${kleur.green("Serving at")} ${kleur.yellow(localAddress)}`)
})
await serveExportOutput(directoryPath, options.port, options.expose)
})
packwizCommand.command("dev")
.description("serve + export with hot-reloading.")
.action(async () => {
output.failAndExit("Not implemented.")
// TODO: serve and export with hot-reloading
})
// packwizCommand.command("dev")
// .description("serve + export with hot-reloading.")
// .option("-s, --server", "Use server overrides instead of client overrides.")
// .option("-p, --port <port>", "The port of the HTTP server.", optionParsePositiveInteger, 8000)
// .option("-e, --expose", "Expose the HTTP server on all interfaces.")
// .action(async options => {
//
// })
packwizCommand.command("export")
.description("Generate a packwiz pack in the packwiz directory.")
.option("-s, --server", "Use server overrides instead of client overrides.")
.action(async options => {
const pack = await usePack()
if (pack.horizrFile.loader !== "fabric")
output.println(kleur.yellow(`packwiz does not yet support the ${kleur.reset(pack.horizrFile.loader)} loader. No loader will be specified.`))
const loader = output.startLoading("Generating")
const outputDirectoryPath = pack.paths.generated.resolve("packwiz")
const modsDirectoryPath = outputDirectoryPath.resolve("mods")
await fs.remove(outputDirectoryPath.toString())
await fs.mkdirp(modsDirectoryPath.toString())
const indexedFiles: IndexedFile[] = []
for (const mod of pack.mods) {
if (!mod.modFile.enabled) output.warn(`${kleur.yellow(mod.modFile.name)} is disabled and will not be included.`)
const innerLoader = output.startLoading(`Generating ${kleur.yellow(mod.id + ".toml")} (${indexedFiles.length + 1}/${pack.mods.length})`)
const content = dedent`
name = ${JSON.stringify(mod.modFile.name)}
filename = ${JSON.stringify(mod.modFile.file.name)}
side = "${mod.modFile.side.replace("client+server", "both")}"
[download]
hash-format = "sha512"
hash = ${JSON.stringify(mod.modFile.file.hashes.sha512)}
url = ${JSON.stringify(mod.modFile.file.downloadUrl)}
`
const path = modsDirectoryPath.resolve(mod.id + ".toml")
await fs.writeFile(path.toString(), content)
indexedFiles.push({
path: outputDirectoryPath.relative(path).toString(),
isMeta: true,
sha512HashHex: await getSha512HexHash(content)
})
innerLoader.stop()
}
loader.setText(`Copying and hashing ${options.server ? "server" : "client"} overrides`)
const createVisitor = (overridesDirectoryPath: Path): Visitor => async (error, path, dirent) => {
const relativePath = overridesDirectoryPath.relative(Path.create(path))
if (error) output.warn(`${kleur.yellow(relativePath.toString())}: ${error.message}`)
else {
if (dirent.name.startsWith(".")) return false
if (dirent.isFile()) {
const outputPath = outputDirectoryPath.resolve(relativePath)
await fs.mkdirp(outputPath.getParent().toString())
await fs.copy(path, outputPath.toString())
indexedFiles.push({
path: relativePath.toString(),
isMeta: false,
sha512HashHex: await getSha512HexHash(await fs.readFile(overridesDirectoryPath.resolve(path).toString()))
})
}
}
}
const specificOverridesDirectoryPath = pack.paths.overrides[options.server ? "server" : "client"]
const universalOverridesDirectoryPath = pack.paths.overrides["client-server"]
if (await fs.pathExists(specificOverridesDirectoryPath.toString())) await walk(specificOverridesDirectoryPath.toString(), createVisitor(specificOverridesDirectoryPath))
if (await fs.pathExists(universalOverridesDirectoryPath.toString())) await walk(universalOverridesDirectoryPath.toString(), createVisitor(universalOverridesDirectoryPath))
loader.setText(`Writing ${kleur.yellow("index.toml")}`)
const index = dedent`
hash-format = "sha512"
${indexedFiles.map(file => dedent`
[[files]]
file = ${JSON.stringify(file.path)}
hash = "${file.sha512HashHex}"
metafile = ${file.isMeta}
`).join("\n\n")}
`
await fs.writeFile(outputDirectoryPath.resolve("index.toml").toString(), index)
const indexHash = await getSha512HexHash(index)
await fs.writeFile(outputDirectoryPath.resolve("pack.toml").toString(), dedent`
name = ${JSON.stringify(pack.horizrFile.meta.name)}
authors = ${JSON.stringify(pack.horizrFile.meta.authors.join(", "))}\
${pack.horizrFile.meta.description === undefined ? "" : "\n" + `description = ${JSON.stringify(pack.horizrFile.meta.description)}`}
pack-format = "packwiz:1.0.0"
[versions]
minecraft = "${pack.horizrFile.versions.minecraft}"\
${pack.horizrFile.loader === "fabric" ? "\n" + `fabric = ${JSON.stringify(pack.horizrFile.versions.loader)}` : ""}
[index]
file = "index.toml"
hash-format = "sha512"
hash = "${indexHash}"
`)
loader.stop()
output.println(kleur.green("Generated packwiz pack"))
await runExport(options.server)
})
async function runExport(forServer: boolean) {
const pack = await usePack()
if (pack.horizrFile.loader !== "fabric")
output.println(kleur.yellow(`packwiz does not yet support the ${kleur.reset(pack.horizrFile.loader)} loader. No loader will be specified.`))
const loader = output.startLoading("Generating")
const outputDirectoryPath = pack.paths.generated.resolve("packwiz")
await fs.remove(outputDirectoryPath.toString())
await fs.mkdirp(outputDirectoryPath.resolve("mods").toString())
const indexedFiles: IndexedFile[] = []
await indexMods(indexedFiles, outputDirectoryPath)
loader.setText(`Copying and hashing ${forServer ? "server" : "client"} overrides`)
await copyOverrides(indexedFiles, outputDirectoryPath, forServer)
loader.setText(`Writing ${kleur.yellow("index.toml")}`)
await writeIndexAndPackManifest(indexedFiles, outputDirectoryPath)
loader.stop()
output.println(kleur.green("Generated packwiz pack"))
return {
indexedFiles
}
}
interface IndexedFile {
path: string
sha512HashHex: string
isMeta: boolean
}
async function writeAndIndexModMetaFile(indexedFiles: IndexedFile[], outputDirectoryPath: Path, mod: Mod) {
const content = dedent`
name = ${JSON.stringify(mod.modFile.name)}
filename = ${JSON.stringify(mod.modFile.file.name)}
side = "${mod.modFile.side.replace("client-server", "both")}"
[download]
hash-format = "sha512"
hash = ${JSON.stringify(mod.modFile.file.hashes.sha512)}
url = ${JSON.stringify(mod.modFile.file.downloadUrl)}
`
const path = outputDirectoryPath.resolve(`mods/${mod.id}.toml`)
await fs.writeFile(path.toString(), content)
indexedFiles.push({
path: `mods/${mod.id}.toml`,
isMeta: true,
sha512HashHex: await getSha512HexHash(content)
})
}
async function indexMods(indexedFiles: IndexedFile[], outputDirectoryPath: Path, warn: boolean = true) {
const pack = await usePack()
for (const mod of pack.mods) {
if (warn && !mod.modFile.enabled) output.warn(`${kleur.yellow(mod.modFile.name)} is disabled and will not be included.`)
await output.withLoading(
writeAndIndexModMetaFile(indexedFiles, outputDirectoryPath, mod),
`Generating ${kleur.yellow(mod.id + ".toml")} (${indexedFiles.length + 1}/${pack.mods.length})`
)
}
}
async function copyOverrides(indexedFiles: IndexedFile[], outputDirectoryPath:Path, forServer: boolean) {
const pack = await usePack()
const createVisitor = (overridesDirectoryPath: Path): Visitor => async (error, path, dirent) => {
const relativePath = overridesDirectoryPath.relative(path)
if (error) output.warn(`${kleur.yellow(relativePath.toString())}: ${error.message}`)
else {
if (dirent.name.startsWith(".")) return false
if (dirent.isFile()) {
const outputPath = outputDirectoryPath.resolve(relativePath)
await fs.mkdirp(outputPath.getParent().toString())
await fs.copy(path, outputPath.toString())
indexedFiles.push({
path: relativePath.toString(),
isMeta: false,
sha512HashHex: await getSha512HexHash(await fs.readFile(overridesDirectoryPath.resolve(path).toString()))
})
}
}
}
const specificOverridesDirectoryPath = pack.paths.overrides[forServer ? "server" : "client"]
const universalOverridesDirectoryPath = pack.paths.overrides["client-server"]
if (await fs.pathExists(specificOverridesDirectoryPath.toString())) await walk(specificOverridesDirectoryPath.toString(), createVisitor(specificOverridesDirectoryPath))
if (await fs.pathExists(universalOverridesDirectoryPath.toString())) await walk(universalOverridesDirectoryPath.toString(), createVisitor(universalOverridesDirectoryPath))
}
async function writeIndexAndPackManifest(indexedFiles: IndexedFile[], outputDirectoryPath: Path) {
const pack = await usePack()
const index = dedent`
hash-format = "sha512"
${indexedFiles.map(file => dedent`
[[files]]
file = ${JSON.stringify(file.path)}
hash = "${file.sha512HashHex}"
metafile = ${file.isMeta}
`).join("\n\n")}
`
await fs.writeFile(outputDirectoryPath.resolve("index.toml").toString(), index)
const indexHash = await getSha512HexHash(index)
await fs.writeFile(outputDirectoryPath.resolve("pack.toml").toString(), dedent`
name = ${JSON.stringify(pack.horizrFile.meta.name)}
authors = ${JSON.stringify(pack.horizrFile.meta.authors.join(", "))}\
${pack.horizrFile.meta.description === undefined ? "" : "\n" + `description = ${JSON.stringify(pack.horizrFile.meta.description)}`}
pack-format = "packwiz:1.0.0"
[versions]
minecraft = "${pack.horizrFile.versions.minecraft}"\
${pack.horizrFile.loader === "fabric" ? "\n" + `fabric = ${JSON.stringify(pack.horizrFile.versions.loader)}` : ""}
[index]
file = "index.toml"
hash-format = "sha512"
hash = "${indexHash}"
`)
}
async function serveExportOutput(path: Path, port: number, expose: boolean) {
const lanAddress = await getLANAddress()
const localAddress = `http://localhost:${port}/pack.toml`
await new Promise<void>(resolve => {
httpServeDirectory(path, port, expose, () => {
if (expose) {
output.println(dedent`
${kleur.green("Serving at")}
Local: ${kleur.yellow(localAddress)}
Network: ${kleur.yellow(`http://${lanAddress}:${port}/pack.toml`)}
`)
} else output.println(`${kleur.green("Serving at")} ${kleur.yellow(localAddress)}`)
resolve()
})
})
}
export { packwizCommand}

View file

@ -9,9 +9,16 @@ import { default as wrapAnsi } from "wrap-ansi"
import { removeModFile } from "./files.js"
import { output } from "./output.js"
import figures from "figures"
import yesno from "yesno"
import { releaseChannelOrder } from "./shared.js"
import fs from "fs-extra"
import { Path } from "./path.js"
const program = new Command("horizr")
.version(
(await fs.readJson(Path.create(import.meta.url.slice(5)).getParent().resolve("../package.json").toString())).version,
"-v, --version"
)
program.command("info", { isDefault: true })
.description("Print information about the pack.")
@ -65,18 +72,31 @@ program.command("update [code]")
`)
}
} else {
const loader = output.startLoading("Checking for an update")
const mod = pack.findModByCodeOrFail(code)
const update = await mod.checkForUpdate(allowedReleaseChannels)
const update = await output.withLoading(mod.checkForUpdate(allowedReleaseChannels), "Checking for an update")
if (update === null) {
loader.stop()
output.println(kleur.green("No update available."))
} else {
loader.setText("Updating")
await update.apply()
loader.stop()
output.println(kleur.green(`Successfully updated ${kleur.yellow(update.mod.modFile.name)} to ${kleur.yellow(update.availableVersion)}.`))
if (update.changelog === null) {
output.println(`No changelog available for ${kleur.bold(update.availableVersion)}.`)
} else {
output.println(`${kleur.underline("Changelog")} for ${kleur.bold().yellow(update.availableVersion)}\n`)
output.printlnWrapping(update.changelog)
}
output.println("")
const confirmed = options.yes || await yesno({
question: "Apply the update? [Y/n]",
defaultValue: true,
invalid: () => {}
})
if (confirmed) {
await output.withLoading(update.apply(), "Updating")
output.println(kleur.green(`Successfully updated ${kleur.yellow(update.mod.modFile.name)} to ${kleur.yellow(update.availableVersion)}.`))
}
}
}
})
@ -85,7 +105,7 @@ loudRejection(stack => {
output.failAndExit(stack)
})
program
await program
.addCommand(packwizCommand)
.addCommand(modrinthCommand)
.addHelpText("after", "\n" + dedent`
@ -95,6 +115,3 @@ program
- The ID of a Modrinth Version, prefixed with ${kleur.yellow("mrv:")}
`)
.parseAsync(process.argv)
.catch(error => {
output.failAndExit(error.message)
})

View file

@ -50,7 +50,7 @@ export async function addModrinthMod(modrinthMod: ModrinthMod, modrinthVersion:
const pack = await usePack()
let id = modrinthMod.slug
if (await pathExists(pack.rootDirectoryPath.resolve("mods", `${id}.json`).toString())) {
if (await pathExists(pack.paths.mods.resolve(`${id}.json`).toString())) {
const oldId = id
id = `${id}-${nanoid(5)}`
@ -67,7 +67,7 @@ export async function addModrinthMod(modrinthMod: ModrinthMod, modrinthVersion:
name: modrinthMod.title,
enabled: true,
ignoreUpdates: false,
side: isClientSupported && isServerSupported ? "client+server" : isClientSupported ? "client" : "server",
side: isClientSupported && isServerSupported ? "client-server" : isClientSupported ? "client" : "server",
file: getModFileDataForModrinthVersion(modrinthMod, modrinthVersion),
source: {
type: "modrinth",

View file

@ -64,8 +64,8 @@ export const output = {
text,
spinner: ora({
spinner: "dots4",
color: "blue",
prefixText: "\n"
// prefixText: "\n"
color: "blue"
}),
fail(message?: string) {
if (this.state !== "running") throw new Error("state is not 'running'")
@ -147,6 +147,7 @@ export const output = {
},
warn(text: string) {
this.printlnWrapping(`${kleur.yellow(figures.pointer)} ${text}`)
this.println("")
},
fail(text: string) {
last(loadersStack)?.fail()

View file

@ -12,12 +12,14 @@ export interface Update {
mod: Mod
activeVersion: string
availableVersion: string
changelog: string | null
apply(): Promise<void>
}
export interface Pack {
paths: {
root: Path,
mods: Path,
generated: Path,
overrides: Record<Side, Path>
},
@ -52,6 +54,7 @@ export async function usePack(): Promise<Pack> {
paths: {
root: rootDirectoryPath,
generated: rootDirectoryPath.resolve("generated"),
mods: rootDirectoryPath.resolve("mods"),
overrides: {
client: overridesDirectoryPath.resolve("client"),
server: overridesDirectoryPath.resolve("server"),
@ -96,6 +99,7 @@ export async function usePack(): Promise<Pack> {
mod,
activeVersion: activeVersionString,
availableVersion: newestVersion.versionString,
changelog: newestVersion.changelog,
async apply() {
const modrinthMod = (await modrinthApi.getMod(newestVersion.projectId))!

View file

@ -22,8 +22,8 @@ export class Path {
/**
* Returns the relative path from this path to the other path.
*/
relative(other: Path) {
return new Path(pathModule.relative(this.value, other.value))
relative(other: Path | string) {
return new Path(pathModule.relative(this.value, typeof other === "string" ? other : other.toString()))
}
getParent() {

View file

@ -11,9 +11,28 @@ import addressWithCallback from "address"
import { promisify } from "util"
const address = promisify(addressWithCallback)
export const getLANAddress = () => address().then(r => r.ip)
export function createSingleConcurrencyWithQueue(fn: () => Promise<void>) {
let state: "inactive" | "running_fresh" | "running_old" = "inactive"
return async () => {
if (state === "inactive") {
const loop = () => {
state = "running_fresh"
fn().then(() => {
if (state === "running_old") loop()
})
}
loop()
} else {
state = "running_old"
}
}
}
export function httpServeDirectory(path: Path, port: number, expose: boolean, onListen: () => void) {
const server = http.createServer((request, response) => {
return serveHandler(request, response, {
@ -46,7 +65,7 @@ export async function zipDirectory(directoryPath: Path, outputFilePath: Path) {
if (directoryPath.toString() === path) return true
if (dirent.name.startsWith(".")) return false
if (dirent.isFile()) zipFile.addFile(path, directoryPath.relative(Path.create(path)).toString(), { compress: true })
if (dirent.isFile()) zipFile.addFile(path, directoryPath.relative(path).toString(), { compress: true })
})
zipFile.end()