From 7efae84110088970c3c32edad052e4092510a03b Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 27 Feb 2024 22:19:00 +0300 Subject: [PATCH 01/97] Testing conditions --- .gitignore | 4 +++- test.js | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 test.js diff --git a/.gitignore b/.gitignore index 5537496..06d119a 100644 --- a/.gitignore +++ b/.gitignore @@ -64,4 +64,6 @@ typings/ .vscode/ # IntelliJ Files -.idea/ \ No newline at end of file +.idea/ + +minecraft/ \ No newline at end of file diff --git a/test.js b/test.js new file mode 100644 index 0000000..d4777e0 --- /dev/null +++ b/test.js @@ -0,0 +1,18 @@ +const { Client, Authenticator } = require("."); +const launcher = new Client(); + +launcher.launch({ + authorization: Authenticator.getAuth("username"), + root: "./minecraft", + version: { + number: "1.7.10", + type: "release", + }, + memory: { + max: "4G", + min: "2G", + }, +}); + +launcher.on("debug", (e) => console.log(e)); +launcher.on("data", (e) => console.log(e)); From d2bc16f63bde3ffc07f1788a1ccfbf21f60d7807 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 27 Feb 2024 22:25:22 +0300 Subject: [PATCH 02/97] Multiple initial changes - Use yarn - Reconfigure eslint - Install prettier and format the code --- .eslintrc.js | 27 + .eslintrc.json | 21 - .prettierignore | 1 + .prettierrc.json | 10 + .travis.yml | 2 +- README.md | 172 +-- components/authenticator.js | 302 ++--- components/handler.js | 1442 ++++++++++---------- components/launcher.js | 397 +++--- index.d.ts | 576 ++++---- index.js | 6 +- package-lock.json | 2464 ----------------------------------- package.json | 82 +- test.js | 26 +- yarn.lock | 1675 ++++++++++++++++++++++++ 15 files changed, 3284 insertions(+), 3919 deletions(-) create mode 100644 .eslintrc.js delete mode 100644 .eslintrc.json create mode 100644 .prettierignore create mode 100644 .prettierrc.json delete mode 100644 package-lock.json create mode 100644 yarn.lock diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..0e60326 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,27 @@ +/** @type {import('eslint').Linter.Config} */ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { + jsx: true, + }, + project: './tsconfig.json', + tsconfigRootDir: './', + }, + env: { + browser: true, + es6: true, + }, + plugins: ['prettier', '@typescript-eslint'], + extends: ['plugin:prettier/recommended', 'eslint:recommended', 'plugin:@typescript-eslint/recommended'], + rules: { + eqeqeq: 'error', + 'prettier/prettier': ['error', {}, { usePrettierrc: true }], + '@typescript-eslint/no-explicit-any': 0, + 'no-use-before-define': 0, + '@typescript-eslint/no-use-before-define': 'warn', + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + '@typescript-eslint/ban-ts-comment': ['error', { 'ts-expect-error': 'allow-with-description' }], + }, +}; diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 8f88750..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "env": { - "browser": true, - "commonjs": true, - "es6": true - }, - "extends": [ - "standard" - ], - "globals": { - "Atomics": "readonly", - "SharedArrayBuffer": "readonly" - }, - "parserOptions": { - "ecmaVersion": 2018 - }, - "rules": { - "camelcase": "off", - "no-template-curly-in-string": "off" - } -} \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6d2eaaa --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +.github/ \ No newline at end of file diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..0514d38 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,10 @@ +{ + "printWidth": 120, + "tabWidth": 4, + "useTabs": false, + "semi": true, + "singleQuote": true, + "jsxSingleQuote": true, + "endOfLine": "lf", + "plugins": ["@ianvs/prettier-plugin-sort-imports"] +} diff --git a/.travis.yml b/.travis.yml index 92436f7..93f3350 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,2 @@ language: node_js -script: echo "npm test temporarily disabled" \ No newline at end of file +script: echo "npm test temporarily disabled" diff --git a/README.md b/README.md index dd9aa13..301e700 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ ![logo](https://owo.whats-th.is/8mT5kxc.png) + ##### Project rewrite coming soon™ + [![Build Status](https://travis-ci.com/Pierce01/MinecraftLauncher-core.svg?branch=master)](https://travis-ci.com/Pierce01/MinecraftLauncher-core) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![version](https://img.shields.io/badge/stable_version-3.18.0-blue) @@ -8,7 +10,9 @@ MCLC (Minecraft Launcher Core) is a NodeJS solution for launching modded and van Basically a core for your Electron or script based launchers. ### Getting support + I've created a Discord server for anyone who needs to get in contact with me or get help! +

console.log(e)); launcher.on('data', (e) => console.log(e)); ``` + ### Documentation #### Client Functions -| Function | Type | Description | -|----------|---------|-----------------------------------------------------------------------------------------| -| `launch` | Promise | Launches the client with the specified `options` as a parameter. Returns child the process | +| Function | Type | Description | +| -------- | ------- | ------------------------------------------------------------------------------------------ | +| `launch` | Promise | Launches the client with the specified `options` as a parameter. Returns child the process | ##### launch -| Parameter | Type | Description | Required | -|--------------------------|----------|-------------------------------------------------------------------------------------------|----------| -| `options.clientPackage` | String | Path or URL to a zip file, which will be extracted to the root directory. (Not recommended for production use)| False | -| `options.removePackage` | Boolean | Option to remove the client package zip file after its finished extracting. | False | -| `options.root` | String | Path where you want the launcher to work in. `C:/Users/user/AppData/Roaming/.mc` | True | -| `options.cache` | String | Path where launcher files will be cached in. `C:/Users/user/AppData/Roaming/.mc/cache` | False | -| `options.os` | String | windows, osx or linux. MCLC will auto determine the OS if this field isn't provided. | False | -| `options.customLaunchArgs`| Array | Array of custom Minecraft arguments you want to add. | False | -| `options.customArgs` | Array | Array of custom Java arguments you want to add. | False | -| `options.features` | Array | Array of game argument feature flags. ex: `is_demo_user` or `has_custom_resolution` | False | -| `options.version.number` | String | Minecraft version that is going to be launched. | True | -| `options.version.type` | String | Any string. The actual Minecraft launcher uses `release` and `snapshot`. | True | -| `options.version.custom` | String | The name of the folder, jar file, and version json in the version folder. | False | -| `options.memory.max` | String | Max amount of memory being used by Minecraft. | True | -| `options.memory.min` | String | Min amount of memory being used by Minecraft. | True | -| `options.forge` | String | Path to Forge Jar. (Versions below 1.12.2 should be the "universal" jar while versions above 1.13 should be the "installer" jar) | False | -| `options.javaPath` | String | Path to the JRE executable file, will default to `java` if not entered. | False | -| `options.quickPlay.type` | String | The type of the quickPlay session. `singleplayer`, `multiplayer`, `realms`, `legacy` | False | -| `options.quickPlay.identifier` | String | The folder name, server address, or realm ID, relating to the specified type. `legacy` follows `multiplayer` format. | False | -| `options.quickPlay.path` | String | The specified path for logging (relative to the run directory) | False | -| `options.proxy.host` | String | Host url to the proxy, don't include the port. | False | -| `options.proxy.port` | String | Port of the host proxy, will default to `8080` if not entered. | False | -| `options.proxy.username` | String | Username for the proxy. | False | -| `options.proxy.password` | String | Password for the proxy. | False | -| `options.timeout` | Integer | Timeout on download requests. | False | -| `options.window.width` | String | Width of the Minecraft Client. | False | -| `options.window.height` | String | Height of the Minecraft Client. | False | -| `options.window.fullscreen`| Boolean| Fullscreen the Minecraft Client. | False | -| `options.overrides` | Object | Json object redefining paths for better customization. Example below. | False | +| Parameter | Type | Description | Required | +| ------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- | -------- | +| `options.clientPackage` | String | Path or URL to a zip file, which will be extracted to the root directory. (Not recommended for production use) | False | +| `options.removePackage` | Boolean | Option to remove the client package zip file after its finished extracting. | False | +| `options.root` | String | Path where you want the launcher to work in. `C:/Users/user/AppData/Roaming/.mc` | True | +| `options.cache` | String | Path where launcher files will be cached in. `C:/Users/user/AppData/Roaming/.mc/cache` | False | +| `options.os` | String | windows, osx or linux. MCLC will auto determine the OS if this field isn't provided. | False | +| `options.customLaunchArgs` | Array | Array of custom Minecraft arguments you want to add. | False | +| `options.customArgs` | Array | Array of custom Java arguments you want to add. | False | +| `options.features` | Array | Array of game argument feature flags. ex: `is_demo_user` or `has_custom_resolution` | False | +| `options.version.number` | String | Minecraft version that is going to be launched. | True | +| `options.version.type` | String | Any string. The actual Minecraft launcher uses `release` and `snapshot`. | True | +| `options.version.custom` | String | The name of the folder, jar file, and version json in the version folder. | False | +| `options.memory.max` | String | Max amount of memory being used by Minecraft. | True | +| `options.memory.min` | String | Min amount of memory being used by Minecraft. | True | +| `options.forge` | String | Path to Forge Jar. (Versions below 1.12.2 should be the "universal" jar while versions above 1.13 should be the "installer" jar) | False | +| `options.javaPath` | String | Path to the JRE executable file, will default to `java` if not entered. | False | +| `options.quickPlay.type` | String | The type of the quickPlay session. `singleplayer`, `multiplayer`, `realms`, `legacy` | False | +| `options.quickPlay.identifier` | String | The folder name, server address, or realm ID, relating to the specified type. `legacy` follows `multiplayer` format. | False | +| `options.quickPlay.path` | String | The specified path for logging (relative to the run directory) | False | +| `options.proxy.host` | String | Host url to the proxy, don't include the port. | False | +| `options.proxy.port` | String | Port of the host proxy, will default to `8080` if not entered. | False | +| `options.proxy.username` | String | Username for the proxy. | False | +| `options.proxy.password` | String | Password for the proxy. | False | +| `options.timeout` | Integer | Timeout on download requests. | False | +| `options.window.width` | String | Width of the Minecraft Client. | False | +| `options.window.height` | String | Height of the Minecraft Client. | False | +| `options.window.fullscreen` | Boolean | Fullscreen the Minecraft Client. | False | +| `options.overrides` | Object | Json object redefining paths for better customization. Example below. | False | + #### IF YOU'RE NEW TO MCLC, LET IT HANDLE EVERYTHING! DO NOT USE OVERRIDES! + ```js let opts = { otherOps..., @@ -127,11 +135,15 @@ let opts = { ``` #### Notes + ##### Custom + If you are loading up a client outside of vanilla Minecraft or Forge (Optifine and for an example), you'll need to download the needed files yourself if you don't provide downloads url downloads like Forge and Fabric. If no version jar is specified, MCLC will default back to the normal MC jar so mods like Fabric work. #### Authentication (Deprecated) + MCLC's authenticator module does not support Microsoft authentication. You will need to use a library like [MSMC](https://github.com/Hanro50/MSMC). If you want to create your own solution, the following is the authorization JSON object format. + ```js { access_token: '', @@ -141,7 +153,7 @@ MCLC's authenticator module does not support Microsoft authentication. You will user_properties: '{}', meta: { type: 'mojang' || 'msa', - demo: true || false, // Demo can also be specified by adding 'is_demo_user' to the options.feature array + demo: true || false, // Demo can also be specified by adding 'is_demo_user' to the options.feature array // properties only exists for specific Minecraft versions. xuid: '', clientId: '' @@ -149,72 +161,74 @@ MCLC's authenticator module does not support Microsoft authentication. You will } ``` -#### Authenticator Functions +#### Authenticator Functions ##### getAuth -| Parameter | Type | Description | Required | -|-----------|--------|--------------------------------------------------------------|----------| -| `username`| String | Email or username | True | -| `password`| String | Password for the Mojang account being used if online mode. | False | -| `client_token`| String | Client token that will be used. If one is not specified, one will be generated | False | +| Parameter | Type | Description | Required | +| -------------- | ------ | ------------------------------------------------------------------------------ | -------- | +| `username` | String | Email or username | True | +| `password` | String | Password for the Mojang account being used if online mode. | False | +| `client_token` | String | Client token that will be used. If one is not specified, one will be generated | False | ##### validate -| Parameter | Type | Description | Required | -|--------------|--------|-------------------------------------------------------------------|----------| -| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | +| Parameter | Type | Description | Required | +| -------------- | ------ | -------------------------------------------------------------------------------- | -------- | +| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | | `client_token` | String | Client token being checked to see if there was a change of client (online mode). | True | -##### refreshAuth +##### refreshAuth -| Parameter | Type | Description | Required | -|--------------------|--------|-------------------------------------------------------------------------------------|----------| -| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | -| `client_token` | String | Token being checked if it's the same client that the access_token was created from. | True | +| Parameter | Type | Description | Required | +| -------------- | ------ | ----------------------------------------------------------------------------------- | -------- | +| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | +| `client_token` | String | Token being checked if it's the same client that the access_token was created from. | True | ##### invalidate -| Parameter | Type | Description | Required | -|--------------|--------|-------------------------------------------------------------------|----------| -| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | +| Parameter | Type | Description | Required | +| -------------- | ------ | ----------------------------------------------------------------------------------- | -------- | +| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | | `client_token` | String | Token being checked if it's the same client that the access_token was created from. | True | ##### signOut -| Parameter | Type | Description | Required | -|--------------|--------|--------------------------------------|----------| +| Parameter | Type | Description | Required | +| ---------- | ------ | --------------------------- | -------- | | `username` | String | Username used to login with | True | | `password` | String | Password used to login with | True | ##### changeApiUrl | Parameter | Type | Description | Required | -|-----------|--------|--------------------------------------------------------------|----------| +| --------- | ------ | ------------------------------------------------------------ | -------- | | `url` | String | New URL that MCLC will make calls to authenticate the login. | True | #### Events -| Event Name | Type | Description | -|-------------------|---------|---------------------------------------------------------------------------------------| -| `arguments` | Object | Emitted when launch arguments are set for the Minecraft Jar. | -| `data` | String | Emitted when information is returned from the Minecraft Process | -| `close` | Integer | Code number that is returned by the Minecraft Process | -| `package-extract` | null | Emitted when `clientPackage` finishes being extracted | -| `download` | String | Emitted when a file successfully downloads | -| `download-status` | Object | Emitted when data is received while downloading | -| `debug` | String | Emitted when functions occur, made to help debug if errors occur | -| `progress` | Object | Emitted when files are being downloaded in order. (Assets, Forge, Natives, Classes) | - +| Event Name | Type | Description | +| ----------------- | ------- | ----------------------------------------------------------------------------------- | +| `arguments` | Object | Emitted when launch arguments are set for the Minecraft Jar. | +| `data` | String | Emitted when information is returned from the Minecraft Process | +| `close` | Integer | Code number that is returned by the Minecraft Process | +| `package-extract` | null | Emitted when `clientPackage` finishes being extracted | +| `download` | String | Emitted when a file successfully downloads | +| `download-status` | Object | Emitted when data is received while downloading | +| `debug` | String | Emitted when functions occur, made to help debug if errors occur | +| `progress` | Object | Emitted when files are being downloaded in order. (Assets, Forge, Natives, Classes) | #### What should it look like running from console? -The `pid` is printed in console after the process is launched. + +The `pid` is printed in console after the process is launched. ![gif](https://owo.whats-th.is/3N3PMC4.gif) ## Contributors + These are the people that helped out that aren't listed [here](https://github.com/Pierce01/MinecraftLauncher-core/graphs/contributors)! -* [Pyker](https://github.com/Pyker) - Forge dependency parsing. -* [Khionu](https://github.com/khionu) - Research on how Minecraft's`natives` are handled. -* [Coding-Kiwi](https://github.com/Coding-Kiwi) - Pointed out I didn't pass `clientToken` in initial authentication function. -* maxbsoft - Pointed out that a certain JVM option causes OSX Minecraft to bug out. -* [Noé](https://github.com/NoXeDev) - Pointed out launch args weren't being passed for Forge 1.13+. + +- [Pyker](https://github.com/Pyker) - Forge dependency parsing. +- [Khionu](https://github.com/khionu) - Research on how Minecraft's`natives` are handled. +- [Coding-Kiwi](https://github.com/Coding-Kiwi) - Pointed out I didn't pass `clientToken` in initial authentication function. +- maxbsoft - Pointed out that a certain JVM option causes OSX Minecraft to bug out. +- [Noé](https://github.com/NoXeDev) - Pointed out launch args weren't being passed for Forge 1.13+. diff --git a/components/authenticator.js b/components/authenticator.js index d3e7b52..8654740 100644 --- a/components/authenticator.js +++ b/components/authenticator.js @@ -1,168 +1,168 @@ -const request = require('request') -const { v3 } = require('uuid') +const request = require('request'); +const { v3 } = require('uuid'); -let uuid -let api_url = 'https://authserver.mojang.com' +let uuid; +let api_url = 'https://authserver.mojang.com'; module.exports.getAuth = function (username, password, client_token = null) { - return new Promise((resolve, reject) => { - getUUID(username) - if (!password) { - const user = { - access_token: uuid, - client_token: client_token || uuid, - uuid, - name: username, - user_properties: '{}' - } - - return resolve(user) - } - - const requestObject = { - url: api_url + '/authenticate', - json: { - agent: { - name: 'Minecraft', - version: 1 - }, - username, - password, - clientToken: uuid, - requestUser: true - } - } - - request.post(requestObject, function (error, response, body) { - if (error) return reject(error) - if (!body || !body.selectedProfile) { - return reject(new Error('Validation error: ' + response.statusMessage)) - } - - const userProfile = { - access_token: body.accessToken, - client_token: body.clientToken, - uuid: body.selectedProfile.id, - name: body.selectedProfile.name, - selected_profile: body.selectedProfile, - user_properties: parsePropts(body.user.properties) - } - - resolve(userProfile) - }) - }) -} + return new Promise((resolve, reject) => { + getUUID(username); + if (!password) { + const user = { + access_token: uuid, + client_token: client_token || uuid, + uuid, + name: username, + user_properties: '{}', + }; + + return resolve(user); + } + + const requestObject = { + url: api_url + '/authenticate', + json: { + agent: { + name: 'Minecraft', + version: 1, + }, + username, + password, + clientToken: uuid, + requestUser: true, + }, + }; + + request.post(requestObject, function (error, response, body) { + if (error) return reject(error); + if (!body || !body.selectedProfile) { + return reject(new Error('Validation error: ' + response.statusMessage)); + } + + const userProfile = { + access_token: body.accessToken, + client_token: body.clientToken, + uuid: body.selectedProfile.id, + name: body.selectedProfile.name, + selected_profile: body.selectedProfile, + user_properties: parsePropts(body.user.properties), + }; + + resolve(userProfile); + }); + }); +}; module.exports.validate = function (accessToken, clientToken) { - return new Promise((resolve, reject) => { - const requestObject = { - url: api_url + '/validate', - json: { - accessToken, - clientToken - } - } - - request.post(requestObject, async function (error, response, body) { - if (error) return reject(error) - - if (!body) resolve(true) - else reject(body) - }) - }) -} + return new Promise((resolve, reject) => { + const requestObject = { + url: api_url + '/validate', + json: { + accessToken, + clientToken, + }, + }; + + request.post(requestObject, async function (error, response, body) { + if (error) return reject(error); + + if (!body) resolve(true); + else reject(body); + }); + }); +}; module.exports.refreshAuth = function (accessToken, clientToken) { - return new Promise((resolve, reject) => { - const requestObject = { - url: api_url + '/refresh', - json: { - accessToken, - clientToken, - requestUser: true - } - } - - request.post(requestObject, function (error, response, body) { - if (error) return reject(error) - if (!body || !body.selectedProfile) { - return reject(new Error('Validation error: ' + response.statusMessage)) - } - - const userProfile = { - access_token: body.accessToken, - client_token: getUUID(body.selectedProfile.name), - uuid: body.selectedProfile.id, - name: body.selectedProfile.name, - user_properties: parsePropts(body.user.properties) - } - - return resolve(userProfile) - }) - }) -} + return new Promise((resolve, reject) => { + const requestObject = { + url: api_url + '/refresh', + json: { + accessToken, + clientToken, + requestUser: true, + }, + }; + + request.post(requestObject, function (error, response, body) { + if (error) return reject(error); + if (!body || !body.selectedProfile) { + return reject(new Error('Validation error: ' + response.statusMessage)); + } + + const userProfile = { + access_token: body.accessToken, + client_token: getUUID(body.selectedProfile.name), + uuid: body.selectedProfile.id, + name: body.selectedProfile.name, + user_properties: parsePropts(body.user.properties), + }; + + return resolve(userProfile); + }); + }); +}; module.exports.invalidate = function (accessToken, clientToken) { - return new Promise((resolve, reject) => { - const requestObject = { - url: api_url + '/invalidate', - json: { - accessToken, - clientToken - } - } - - request.post(requestObject, function (error, response, body) { - if (error) return reject(error) - - if (!body) return resolve(true) - else return reject(body) - }) - }) -} + return new Promise((resolve, reject) => { + const requestObject = { + url: api_url + '/invalidate', + json: { + accessToken, + clientToken, + }, + }; + + request.post(requestObject, function (error, response, body) { + if (error) return reject(error); + + if (!body) return resolve(true); + else return reject(body); + }); + }); +}; module.exports.signOut = function (username, password) { - return new Promise((resolve, reject) => { - const requestObject = { - url: api_url + '/signout', - json: { - username, - password - } - } - - request.post(requestObject, function (error, response, body) { - if (error) return reject(error) - - if (!body) return resolve(true) - else return reject(body) - }) - }) -} + return new Promise((resolve, reject) => { + const requestObject = { + url: api_url + '/signout', + json: { + username, + password, + }, + }; + + request.post(requestObject, function (error, response, body) { + if (error) return reject(error); + + if (!body) return resolve(true); + else return reject(body); + }); + }); +}; module.exports.changeApiUrl = function (url) { - api_url = url -} - -function parsePropts (array) { - if (array) { - const newObj = {} - for (const entry of array) { - if (newObj[entry.name]) { - newObj[entry.name].push(entry.value) - } else { - newObj[entry.name] = [entry.value] - } + api_url = url; +}; + +function parsePropts(array) { + if (array) { + const newObj = {}; + for (const entry of array) { + if (newObj[entry.name]) { + newObj[entry.name].push(entry.value); + } else { + newObj[entry.name] = [entry.value]; + } + } + return JSON.stringify(newObj); + } else { + return '{}'; } - return JSON.stringify(newObj) - } else { - return '{}' - } } -function getUUID (value) { - if (!uuid) { - uuid = v3(value, v3.DNS) - } - return uuid +function getUUID(value) { + if (!uuid) { + uuid = v3(value, v3.DNS); + } + return uuid; } diff --git a/components/handler.js b/components/handler.js index 532d825..92270f3 100644 --- a/components/handler.js +++ b/components/handler.js @@ -1,732 +1,830 @@ -const fs = require('fs') -const path = require('path') -const request = require('request') -const checksum = require('checksum') -const Zip = require('adm-zip') -const child = require('child_process') -let counter = 0 +const fs = require('fs'); +const path = require('path'); +const request = require('request'); +const checksum = require('checksum'); +const Zip = require('adm-zip'); +const child = require('child_process'); +let counter = 0; class Handler { - constructor (client) { - this.client = client - this.options = client.options - this.baseRequest = request.defaults({ - pool: { maxSockets: this.options.overrides.maxSockets || 2 }, - timeout: this.options.timeout || 50000 - }) - } - - checkJava (java) { - return new Promise(resolve => { - child.exec(`"${java}" -version`, (error, stdout, stderr) => { - if (error) { - resolve({ - run: false, - message: error - }) - } else { - this.client.emit('debug', `[MCLC]: Using Java version ${stderr.match(/"(.*?)"/).pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`) - resolve({ - run: true - }) - } - }) - }) - } - - downloadAsync (url, directory, name, retry, type) { - return new Promise(resolve => { - fs.mkdirSync(directory, { recursive: true }) + constructor(client) { + this.client = client; + this.options = client.options; + this.baseRequest = request.defaults({ + pool: { maxSockets: this.options.overrides.maxSockets || 2 }, + timeout: this.options.timeout || 50000, + }); + } - const _request = this.baseRequest(url) + checkJava(java) { + return new Promise((resolve) => { + child.exec(`"${java}" -version`, (error, stdout, stderr) => { + if (error) { + resolve({ + run: false, + message: error, + }); + } else { + this.client.emit( + 'debug', + `[MCLC]: Using Java version ${stderr.match(/"(.*?)"/).pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`, + ); + resolve({ + run: true, + }); + } + }); + }); + } - let receivedBytes = 0 - let totalBytes = 0 + downloadAsync(url, directory, name, retry, type) { + return new Promise((resolve) => { + fs.mkdirSync(directory, { recursive: true }); + + const _request = this.baseRequest(url); + + let receivedBytes = 0; + let totalBytes = 0; + + _request.on('response', (data) => { + if (data.statusCode === 404) { + this.client.emit('debug', `[MCLC]: Failed to download ${url} due to: File not found...`); + return resolve(false); + } + + totalBytes = parseInt(data.headers['content-length']); + }); + + _request.on('error', async (error) => { + this.client.emit( + 'debug', + `[MCLC]: Failed to download asset to ${path.join(directory, name)} due to\n${error}.` + + ` Retrying... ${retry}`, + ); + if (retry) await this.downloadAsync(url, directory, name, false, type); + resolve(); + }); + + _request.on('data', (data) => { + receivedBytes += data.length; + this.client.emit('download-status', { + name: name, + type: type, + current: receivedBytes, + total: totalBytes, + }); + }); + + const file = fs.createWriteStream(path.join(directory, name)); + _request.pipe(file); + + file.once('finish', () => { + this.client.emit('download', name); + resolve({ + failed: false, + asset: null, + }); + }); + + file.on('error', async (e) => { + this.client.emit( + 'debug', + `[MCLC]: Failed to download asset to ${path.join(directory, name)} due to\n${e}.` + + ` Retrying... ${retry}`, + ); + if (fs.existsSync(path.join(directory, name))) fs.unlinkSync(path.join(directory, name)); + if (retry) await this.downloadAsync(url, directory, name, false, type); + resolve(); + }); + }); + } - _request.on('response', (data) => { - if (data.statusCode === 404) { - this.client.emit('debug', `[MCLC]: Failed to download ${url} due to: File not found...`) - return resolve(false) - } + checkSum(hash, file) { + return new Promise((resolve, reject) => { + checksum.file(file, (err, sum) => { + if (err) { + this.client.emit('debug', `[MCLC]: Failed to check file hash due to ${err}`); + return resolve(false); + } + return resolve(hash === sum); + }); + }); + } - totalBytes = parseInt(data.headers['content-length']) - }) - - _request.on('error', async (error) => { - this.client.emit('debug', `[MCLC]: Failed to download asset to ${path.join(directory, name)} due to\n${error}.` + - ` Retrying... ${retry}`) - if (retry) await this.downloadAsync(url, directory, name, false, type) - resolve() - }) - - _request.on('data', (data) => { - receivedBytes += data.length - this.client.emit('download-status', { - name: name, - type: type, - current: receivedBytes, - total: totalBytes - }) - }) - - const file = fs.createWriteStream(path.join(directory, name)) - _request.pipe(file) - - file.once('finish', () => { - this.client.emit('download', name) - resolve({ - failed: false, - asset: null - }) - }) - - file.on('error', async (e) => { - this.client.emit('debug', `[MCLC]: Failed to download asset to ${path.join(directory, name)} due to\n${e}.` + - ` Retrying... ${retry}`) - if (fs.existsSync(path.join(directory, name))) fs.unlinkSync(path.join(directory, name)) - if (retry) await this.downloadAsync(url, directory, name, false, type) - resolve() - }) - }) - } - - checkSum (hash, file) { - return new Promise((resolve, reject) => { - checksum.file(file, (err, sum) => { - if (err) { - this.client.emit('debug', `[MCLC]: Failed to check file hash due to ${err}`) - return resolve(false) - } - return resolve(hash === sum) - }) - }) - } - - getVersion () { - return new Promise(resolve => { - const versionJsonPath = this.options.overrides.versionJson || path.join(this.options.directory, `${this.options.version.number}.json`) - if (fs.existsSync(versionJsonPath)) { - this.version = JSON.parse(fs.readFileSync(versionJsonPath)) - return resolve(this.version) - } - - const manifest = `${this.options.overrides.url.meta}/mc/game/version_manifest.json` - const cache = this.options.cache ? `${this.options.cache}/json` : `${this.options.root}/cache/json` - request.get(manifest, (error, response, body) => { - if (error && error.code !== 'ENOTFOUND') return resolve(error) - if (!error) { - if (!fs.existsSync(cache)) { - fs.mkdirSync(cache, { recursive: true }) - this.client.emit('debug', '[MCLC]: Cache directory created.') - } - fs.writeFile(path.join(`${cache}/version_manifest.json`), body, (err) => { - if (err) return resolve(err) - this.client.emit('debug', '[MCLC]: Cached version_manifest.json') - }) - } - const parsed = (error && error.code === 'ENOTFOUND') - ? JSON.parse(fs.readFileSync(`${cache}/version_manifest.json`)) - : JSON.parse(body) - const desiredVersion = Object.values(parsed.versions).find(version => version.id === this.options.version.number) - if (desiredVersion) { - request.get(desiredVersion.url, (error, response, body) => { - if (error && error.code !== 'ENOTFOUND') throw Error(error) - if (!error) { - fs.writeFile(path.join(`${cache}/${this.options.version.number}.json`), body, (err) => { - if (err) throw Error(err) - this.client.emit('debug', `[MCLC]: Cached ${this.options.version.number}.json`) - }) + getVersion() { + return new Promise((resolve) => { + const versionJsonPath = + this.options.overrides.versionJson || + path.join(this.options.directory, `${this.options.version.number}.json`); + if (fs.existsSync(versionJsonPath)) { + this.version = JSON.parse(fs.readFileSync(versionJsonPath)); + return resolve(this.version); } - this.client.emit('debug', '[MCLC]: Parsed version from version manifest') - this.version = error && error.code === 'ENOTFOUND' - ? JSON.parse(fs.readFileSync(`${cache}/${this.options.version.number}.json`)) - : JSON.parse(body) - return resolve(this.version) - }) - } else { - throw Error(`Failed to find version ${this.options.version.number} in version_manifest.json`) - } - }) - }) - } - - async getJar () { - await this.downloadAsync(this.version.downloads.client.url, this.options.directory, `${this.options.version.custom ? this.options.version.custom : this.options.version.number}.jar`, true, 'version-jar') - fs.writeFileSync(path.join(this.options.directory, `${this.options.version.number}.json`), JSON.stringify(this.version, null, 4)) - return this.client.emit('debug', '[MCLC]: Downloaded version jar and wrote version json') - } - - async getAssets () { - const assetDirectory = path.resolve(this.options.overrides.assetRoot || path.join(this.options.root, 'assets')) - const assetId = this.options.version.custom || this.options.version.number - if (!fs.existsSync(path.join(assetDirectory, 'indexes', `${assetId}.json`))) { - await this.downloadAsync(this.version.assetIndex.url, path.join(assetDirectory, 'indexes'), `${assetId}.json`, true, 'asset-json') + const manifest = `${this.options.overrides.url.meta}/mc/game/version_manifest.json`; + const cache = this.options.cache ? `${this.options.cache}/json` : `${this.options.root}/cache/json`; + request.get(manifest, (error, response, body) => { + if (error && error.code !== 'ENOTFOUND') return resolve(error); + if (!error) { + if (!fs.existsSync(cache)) { + fs.mkdirSync(cache, { recursive: true }); + this.client.emit('debug', '[MCLC]: Cache directory created.'); + } + fs.writeFile(path.join(`${cache}/version_manifest.json`), body, (err) => { + if (err) return resolve(err); + this.client.emit('debug', '[MCLC]: Cached version_manifest.json'); + }); + } + const parsed = + error && error.code === 'ENOTFOUND' + ? JSON.parse(fs.readFileSync(`${cache}/version_manifest.json`)) + : JSON.parse(body); + const desiredVersion = Object.values(parsed.versions).find( + (version) => version.id === this.options.version.number, + ); + if (desiredVersion) { + request.get(desiredVersion.url, (error, response, body) => { + if (error && error.code !== 'ENOTFOUND') throw Error(error); + if (!error) { + fs.writeFile(path.join(`${cache}/${this.options.version.number}.json`), body, (err) => { + if (err) throw Error(err); + this.client.emit('debug', `[MCLC]: Cached ${this.options.version.number}.json`); + }); + } + + this.client.emit('debug', '[MCLC]: Parsed version from version manifest'); + this.version = + error && error.code === 'ENOTFOUND' + ? JSON.parse(fs.readFileSync(`${cache}/${this.options.version.number}.json`)) + : JSON.parse(body); + return resolve(this.version); + }); + } else { + throw Error(`Failed to find version ${this.options.version.number} in version_manifest.json`); + } + }); + }); } - const index = JSON.parse(fs.readFileSync(path.join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' })) - - this.client.emit('progress', { - type: 'assets', - task: 0, - total: Object.keys(index.objects).length - }) - - await Promise.all(Object.keys(index.objects).map(async asset => { - const hash = index.objects[asset].hash - const subhash = hash.substring(0, 2) - const subAsset = path.join(assetDirectory, 'objects', subhash) - - if (!fs.existsSync(path.join(subAsset, hash)) || !await this.checkSum(hash, path.join(subAsset, hash))) { - await this.downloadAsync(`${this.options.overrides.url.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets') - } - counter++ - this.client.emit('progress', { - type: 'assets', - task: counter, - total: Object.keys(index.objects).length - }) - })) - counter = 0 - - // Copy assets to legacy if it's an older Minecraft version. - if (this.isLegacy()) { - if (fs.existsSync(path.join(assetDirectory, 'legacy'))) { - this.client.emit('debug', '[MCLC]: The \'legacy\' directory is no longer used as Minecraft looks ' + - 'for the resouces folder regardless of what is passed in the assetDirecotry launch option. I\'d ' + - `recommend removing the directory (${path.join(assetDirectory, 'legacy')})`) - } - - const legacyDirectory = path.join(this.options.root, 'resources') - this.client.emit('debug', `[MCLC]: Copying assets over to ${legacyDirectory}`) - - this.client.emit('progress', { - type: 'assets-copy', - task: 0, - total: Object.keys(index.objects).length - }) - - await Promise.all(Object.keys(index.objects).map(async asset => { - const hash = index.objects[asset].hash - const subhash = hash.substring(0, 2) - const subAsset = path.join(assetDirectory, 'objects', subhash) - - const legacyAsset = asset.split('/') - legacyAsset.pop() - - if (!fs.existsSync(path.join(legacyDirectory, legacyAsset.join('/')))) { - fs.mkdirSync(path.join(legacyDirectory, legacyAsset.join('/')), { recursive: true }) - } + async getJar() { + await this.downloadAsync( + this.version.downloads.client.url, + this.options.directory, + `${this.options.version.custom ? this.options.version.custom : this.options.version.number}.jar`, + true, + 'version-jar', + ); + fs.writeFileSync( + path.join(this.options.directory, `${this.options.version.number}.json`), + JSON.stringify(this.version, null, 4), + ); + return this.client.emit('debug', '[MCLC]: Downloaded version jar and wrote version json'); + } - if (!fs.existsSync(path.join(legacyDirectory, asset))) { - fs.copyFileSync(path.join(subAsset, hash), path.join(legacyDirectory, asset)) + async getAssets() { + const assetDirectory = path.resolve(this.options.overrides.assetRoot || path.join(this.options.root, 'assets')); + const assetId = this.options.version.custom || this.options.version.number; + if (!fs.existsSync(path.join(assetDirectory, 'indexes', `${assetId}.json`))) { + await this.downloadAsync( + this.version.assetIndex.url, + path.join(assetDirectory, 'indexes'), + `${assetId}.json`, + true, + 'asset-json', + ); } - counter++ - this.client.emit('progress', { - type: 'assets-copy', - task: counter, - total: Object.keys(index.objects).length - }) - })) - } - counter = 0 - this.client.emit('debug', '[MCLC]: Downloaded assets') - } + const index = JSON.parse( + fs.readFileSync(path.join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' }), + ); + + this.client.emit('progress', { + type: 'assets', + task: 0, + total: Object.keys(index.objects).length, + }); + + await Promise.all( + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = path.join(assetDirectory, 'objects', subhash); + + if ( + !fs.existsSync(path.join(subAsset, hash)) || + !(await this.checkSum(hash, path.join(subAsset, hash))) + ) { + await this.downloadAsync( + `${this.options.overrides.url.resource}/${subhash}/${hash}`, + subAsset, + hash, + true, + 'assets', + ); + } + counter++; + this.client.emit('progress', { + type: 'assets', + task: counter, + total: Object.keys(index.objects).length, + }); + }), + ); + counter = 0; + + // Copy assets to legacy if it's an older Minecraft version. + if (this.isLegacy()) { + if (fs.existsSync(path.join(assetDirectory, 'legacy'))) { + this.client.emit( + 'debug', + "[MCLC]: The 'legacy' directory is no longer used as Minecraft looks " + + "for the resouces folder regardless of what is passed in the assetDirecotry launch option. I'd " + + `recommend removing the directory (${path.join(assetDirectory, 'legacy')})`, + ); + } - parseRule (lib) { - if (lib.rules) { - if (lib.rules.length > 1) { - if (lib.rules[0].action === 'allow' && lib.rules[1].action === 'disallow' && lib.rules[1].os.name === 'osx') { - return this.getOS() === 'osx' + const legacyDirectory = path.join(this.options.root, 'resources'); + this.client.emit('debug', `[MCLC]: Copying assets over to ${legacyDirectory}`); + + this.client.emit('progress', { + type: 'assets-copy', + task: 0, + total: Object.keys(index.objects).length, + }); + + await Promise.all( + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = path.join(assetDirectory, 'objects', subhash); + + const legacyAsset = asset.split('/'); + legacyAsset.pop(); + + if (!fs.existsSync(path.join(legacyDirectory, legacyAsset.join('/')))) { + fs.mkdirSync(path.join(legacyDirectory, legacyAsset.join('/')), { recursive: true }); + } + + if (!fs.existsSync(path.join(legacyDirectory, asset))) { + fs.copyFileSync(path.join(subAsset, hash), path.join(legacyDirectory, asset)); + } + counter++; + this.client.emit('progress', { + type: 'assets-copy', + task: counter, + total: Object.keys(index.objects).length, + }); + }), + ); } - return true - } else { - if (lib.rules[0].action === 'allow' && lib.rules[0].os) return lib.rules[0].os.name !== this.getOS() - } - } else { - return false + counter = 0; + + this.client.emit('debug', '[MCLC]: Downloaded assets'); } - } - - async getNatives () { - const nativeDirectory = path.resolve(this.options.overrides.natives || path.join(this.options.root, 'natives', this.version.id)) - - if (parseInt(this.version.id.split('.')[1]) >= 19) return this.options.overrides.cwd || this.options.root - - if (!fs.existsSync(nativeDirectory) || !fs.readdirSync(nativeDirectory).length) { - fs.mkdirSync(nativeDirectory, { recursive: true }) - - const natives = async () => { - const natives = [] - await Promise.all(this.version.libraries.map(async (lib) => { - if (!lib.downloads || !lib.downloads.classifiers) return - if (this.parseRule(lib)) return - - const native = this.getOS() === 'osx' - ? lib.downloads.classifiers['natives-osx'] || lib.downloads.classifiers['natives-macos'] - : lib.downloads.classifiers[`natives-${this.getOS()}`] - - natives.push(native) - })) - return natives - } - const stat = await natives() - - this.client.emit('progress', { - type: 'natives', - task: 0, - total: stat.length - }) - - await Promise.all(stat.map(async (native) => { - if (!native) return - const name = native.path.split('/').pop() - await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives') - if (!await this.checkSum(native.sha1, path.join(nativeDirectory, name))) { - await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives') - } - try { - new Zip(path.join(nativeDirectory, name)).extractAllTo(nativeDirectory, true) - } catch (e) { - // Only doing a console.warn since a stupid error happens. You can basically ignore this. - // if it says Invalid file name, just means two files were downloaded and both were deleted. - // All is well. - console.warn(e) + + parseRule(lib) { + if (lib.rules) { + if (lib.rules.length > 1) { + if ( + lib.rules[0].action === 'allow' && + lib.rules[1].action === 'disallow' && + lib.rules[1].os.name === 'osx' + ) { + return this.getOS() === 'osx'; + } + return true; + } else { + if (lib.rules[0].action === 'allow' && lib.rules[0].os) return lib.rules[0].os.name !== this.getOS(); + } + } else { + return false; } - fs.unlinkSync(path.join(nativeDirectory, name)) - counter++ - this.client.emit('progress', { - type: 'natives', - task: counter, - total: stat.length - }) - })) - this.client.emit('debug', '[MCLC]: Downloaded and extracted natives') } - counter = 0 - this.client.emit('debug', `[MCLC]: Set native path to ${nativeDirectory}`) - - return nativeDirectory - } - - fwAddArgs () { - const forgeWrapperAgrs = [ - `-Dforgewrapper.librariesDir=${path.resolve(this.options.overrides.libraryRoot || path.join(this.options.root, 'libraries'))}`, - `-Dforgewrapper.installer=${this.options.forge}`, - `-Dforgewrapper.minecraft=${this.options.mcPath}` - ] - this.options.customArgs - ? this.options.customArgs = this.options.customArgs.concat(forgeWrapperAgrs) - : this.options.customArgs = forgeWrapperAgrs - } - - isModernForge (json) { - return json.inheritsFrom && json.inheritsFrom.split('.')[1] >= 12 && !(json.inheritsFrom === '1.12.2' && (json.id.split('.')[json.id.split('.').length - 1]) === '2847') - } - - async getForgedWrapped () { - let json = null - let installerJson = null - const versionPath = path.join(this.options.root, 'forge', `${this.version.id}`, 'version.json') - // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not - // be re-generated on the next run. - if (fs.existsSync(versionPath)) { - try { - json = JSON.parse(fs.readFileSync(versionPath)) - if (!json.forgeWrapperVersion || !(json.forgeWrapperVersion === this.options.overrides.fw.version)) { - this.client.emit('debug', '[MCLC]: Old ForgeWrapper has generated this version JSON, re-generating') - } else { - // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. - if (this.isModernForge(json)) { - this.fwAddArgs() - this.options.forge = null - } - return json + async getNatives() { + const nativeDirectory = path.resolve( + this.options.overrides.natives || path.join(this.options.root, 'natives', this.version.id), + ); + + if (parseInt(this.version.id.split('.')[1]) >= 19) return this.options.overrides.cwd || this.options.root; + + if (!fs.existsSync(nativeDirectory) || !fs.readdirSync(nativeDirectory).length) { + fs.mkdirSync(nativeDirectory, { recursive: true }); + + const natives = async () => { + const natives = []; + await Promise.all( + this.version.libraries.map(async (lib) => { + if (!lib.downloads || !lib.downloads.classifiers) return; + if (this.parseRule(lib)) return; + + const native = + this.getOS() === 'osx' + ? lib.downloads.classifiers['natives-osx'] || lib.downloads.classifiers['natives-macos'] + : lib.downloads.classifiers[`natives-${this.getOS()}`]; + + natives.push(native); + }), + ); + return natives; + }; + const stat = await natives(); + + this.client.emit('progress', { + type: 'natives', + task: 0, + total: stat.length, + }); + + await Promise.all( + stat.map(async (native) => { + if (!native) return; + const name = native.path.split('/').pop(); + await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); + if (!(await this.checkSum(native.sha1, path.join(nativeDirectory, name)))) { + await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); + } + try { + new Zip(path.join(nativeDirectory, name)).extractAllTo(nativeDirectory, true); + } catch (e) { + // Only doing a console.warn since a stupid error happens. You can basically ignore this. + // if it says Invalid file name, just means two files were downloaded and both were deleted. + // All is well. + console.warn(e); + } + fs.unlinkSync(path.join(nativeDirectory, name)); + counter++; + this.client.emit('progress', { + type: 'natives', + task: counter, + total: stat.length, + }); + }), + ); + this.client.emit('debug', '[MCLC]: Downloaded and extracted natives'); } - } catch (e) { - console.warn(e) - this.client.emit('debug', '[MCLC]: Failed to parse Forge version JSON, re-generating') - } + + counter = 0; + this.client.emit('debug', `[MCLC]: Set native path to ${nativeDirectory}`); + + return nativeDirectory; } - this.client.emit('debug', '[MCLC]: Generating Forge version json, this might take a bit') - const zipFile = new Zip(this.options.forge) - json = zipFile.readAsText('version.json') - if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json') - - try { - json = JSON.parse(json) - if (installerJson) installerJson = JSON.parse(installerJson) - } catch (e) { - this.client.emit('debug', '[MCLC]: Failed to load json files for ForgeWrapper, using Vanilla instead') - return null + fwAddArgs() { + const forgeWrapperAgrs = [ + `-Dforgewrapper.librariesDir=${path.resolve(this.options.overrides.libraryRoot || path.join(this.options.root, 'libraries'))}`, + `-Dforgewrapper.installer=${this.options.forge}`, + `-Dforgewrapper.minecraft=${this.options.mcPath}`, + ]; + this.options.customArgs + ? (this.options.customArgs = this.options.customArgs.concat(forgeWrapperAgrs)) + : (this.options.customArgs = forgeWrapperAgrs); } - // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. - if (installerJson) { - json.mavenFiles - ? json.mavenFiles = json.mavenFiles.concat(installerJson.libraries) - : json.mavenFiles = installerJson.libraries + + isModernForge(json) { + return ( + json.inheritsFrom && + json.inheritsFrom.split('.')[1] >= 12 && + !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') + ); } - // Holder for the specifc jar ending which depends on the specifc forge version. - let jarEnding = 'universal' - // We need to handle modern forge differently than legacy. - if (this.isModernForge(json)) { - // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. - if (json.inheritsFrom !== '1.12.2') { - this.fwAddArgs() - const fwName = `ForgeWrapper-${this.options.overrides.fw.version}.jar` - const fwPathArr = ['io', 'github', 'zekerzhayard', 'ForgeWrapper', this.options.overrides.fw.version] - json.libraries.push({ - name: fwPathArr.join(':'), - downloads: { - artifact: { - path: [...fwPathArr, fwName].join('/'), - url: `${this.options.overrides.fw.baseUrl}${this.options.overrides.fw.version}/${fwName}`, - sha1: this.options.overrides.fw.sh1, - size: this.options.overrides.fw.size + async getForgedWrapped() { + let json = null; + let installerJson = null; + const versionPath = path.join(this.options.root, 'forge', `${this.version.id}`, 'version.json'); + // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not + // be re-generated on the next run. + if (fs.existsSync(versionPath)) { + try { + json = JSON.parse(fs.readFileSync(versionPath)); + if (!json.forgeWrapperVersion || !(json.forgeWrapperVersion === this.options.overrides.fw.version)) { + this.client.emit( + 'debug', + '[MCLC]: Old ForgeWrapper has generated this version JSON, re-generating', + ); + } else { + // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. + if (this.isModernForge(json)) { + this.fwAddArgs(); + this.options.forge = null; + } + return json; + } + } catch (e) { + console.warn(e); + this.client.emit('debug', '[MCLC]: Failed to parse Forge version JSON, re-generating'); } - } - }) - json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main' - jarEnding = 'launcher' - - // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. - for (const library of json.mavenFiles) { - const lib = library.name.split(':') - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - library.downloads.artifact.url = this.options.overrides.url.mavenForge + library.downloads.artifact.path - break - } } - } else { - // Remove the forge dependent since we're going to overwrite the first entry anyways. - for (const library in json.mavenFiles) { - const lib = json.mavenFiles[library].name.split(':') - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - delete json.mavenFiles[library] - break - } + + this.client.emit('debug', '[MCLC]: Generating Forge version json, this might take a bit'); + const zipFile = new Zip(this.options.forge); + json = zipFile.readAsText('version.json'); + if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); + + try { + json = JSON.parse(json); + if (installerJson) installerJson = JSON.parse(installerJson); + } catch (e) { + this.client.emit('debug', '[MCLC]: Failed to load json files for ForgeWrapper, using Vanilla instead'); + return null; } - } - } else { - // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. - await Promise.all(json.libraries.map(async library => { - const lib = library.name.split(':') - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return - - let url = this.options.overrides.url.mavenForge - const name = `${lib[1]}-${lib[2]}.jar` - - if (!library.url) { - if (library.serverreq || library.clientreq) { - url = this.options.overrides.url.defaultRepoForge - } else { - return - } + // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. + if (installerJson) { + json.mavenFiles + ? (json.mavenFiles = json.mavenFiles.concat(installerJson.libraries)) + : (json.mavenFiles = installerJson.libraries); } - library.url = url - const downloadLink = `${url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}` - // Checking if the file still exists on Forge's server, if not, replace it with the fallback. - // Not checking for sucess, only if it 404s. - this.baseRequest(downloadLink, (error, response, body) => { - if (error) { - this.client.emit('debug', `[MCLC]: Failed checking request for ${downloadLink}`) - } else { - if (response.statusCode === 404) library.url = this.options.overrides.url.fallbackMaven - } - }) - })) - } - // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. - // If it doesn't, we simply remove it since we're already providing the universal jar. - if (json.libraries[0].downloads) { - const name = json.libraries[0].name - if (name.includes('minecraftforge:forge') && !name.includes('universal')) { - json.libraries[0].name = name + `:${jarEnding}` - json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.path.replace('.jar', `-${jarEnding}.jar`) - json.libraries[0].downloads.artifact.url = this.options.overrides.url.mavenForge + json.libraries[0].downloads.artifact.path - } - } else { - delete json.libraries[0] - } - // Removing duplicates and null types - json.libraries = this.cleanUp(json.libraries) - if (json.mavenFiles) json.mavenFiles = this.cleanUp(json.mavenFiles) + // Holder for the specifc jar ending which depends on the specifc forge version. + let jarEnding = 'universal'; + // We need to handle modern forge differently than legacy. + if (this.isModernForge(json)) { + // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. + if (json.inheritsFrom !== '1.12.2') { + this.fwAddArgs(); + const fwName = `ForgeWrapper-${this.options.overrides.fw.version}.jar`; + const fwPathArr = ['io', 'github', 'zekerzhayard', 'ForgeWrapper', this.options.overrides.fw.version]; + json.libraries.push({ + name: fwPathArr.join(':'), + downloads: { + artifact: { + path: [...fwPathArr, fwName].join('/'), + url: `${this.options.overrides.fw.baseUrl}${this.options.overrides.fw.version}/${fwName}`, + sha1: this.options.overrides.fw.sh1, + size: this.options.overrides.fw.size, + }, + }, + }); + json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main'; + jarEnding = 'launcher'; + + // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. + for (const library of json.mavenFiles) { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { + library.downloads.artifact.url = + this.options.overrides.url.mavenForge + library.downloads.artifact.path; + break; + } + } + } else { + // Remove the forge dependent since we're going to overwrite the first entry anyways. + for (const library in json.mavenFiles) { + const lib = json.mavenFiles[library].name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { + delete json.mavenFiles[library]; + break; + } + } + } + } else { + // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. + await Promise.all( + json.libraries.map(async (library) => { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; + + let url = this.options.overrides.url.mavenForge; + const name = `${lib[1]}-${lib[2]}.jar`; + + if (!library.url) { + if (library.serverreq || library.clientreq) { + url = this.options.overrides.url.defaultRepoForge; + } else { + return; + } + } + library.url = url; + const downloadLink = `${url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; + // Checking if the file still exists on Forge's server, if not, replace it with the fallback. + // Not checking for sucess, only if it 404s. + this.baseRequest(downloadLink, (error, response, body) => { + if (error) { + this.client.emit('debug', `[MCLC]: Failed checking request for ${downloadLink}`); + } else { + if (response.statusCode === 404) library.url = this.options.overrides.url.fallbackMaven; + } + }); + }), + ); + } + // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. + // If it doesn't, we simply remove it since we're already providing the universal jar. + if (json.libraries[0].downloads) { + const name = json.libraries[0].name; + if (name.includes('minecraftforge:forge') && !name.includes('universal')) { + json.libraries[0].name = name + `:${jarEnding}`; + json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.path.replace( + '.jar', + `-${jarEnding}.jar`, + ); + json.libraries[0].downloads.artifact.url = + this.options.overrides.url.mavenForge + json.libraries[0].downloads.artifact.path; + } + } else { + delete json.libraries[0]; + } - json.forgeWrapperVersion = this.options.overrides.fw.version + // Removing duplicates and null types + json.libraries = this.cleanUp(json.libraries); + if (json.mavenFiles) json.mavenFiles = this.cleanUp(json.mavenFiles); - // Saving file for next run! - if (!fs.existsSync(path.join(this.options.root, 'forge', this.version.id))) { - fs.mkdirSync(path.join(this.options.root, 'forge', this.version.id), { recursive: true }) - } - fs.writeFileSync(versionPath, JSON.stringify(json, null, 4)) - - // Make MCLC treat modern forge as a custom version json rather then legacy forge. - if (this.isModernForge(json)) this.options.forge = null - - return json - } - - async downloadToDirectory (directory, libraries, eventName) { - const libs = [] - - await Promise.all(libraries.map(async library => { - if (!library) return - if (this.parseRule(library)) return - const lib = library.name.split(':') - - let jarPath - let name - if (library.downloads && library.downloads.artifact && library.downloads.artifact.path) { - name = library.downloads.artifact.path.split('/')[library.downloads.artifact.path.split('/').length - 1] - jarPath = path.join(directory, this.popString(library.downloads.artifact.path)) - } else { - name = `${lib[1]}-${lib[2]}${lib[3] ? '-' + lib[3] : ''}.jar` - jarPath = path.join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`) - } - - const downloadLibrary = async library => { - if (library.url) { - const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}` - await this.downloadAsync(url, jarPath, name, true, eventName) - } else if (library.downloads && library.downloads.artifact && library.downloads.artifact.url) { - // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. - await this.downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName) + json.forgeWrapperVersion = this.options.overrides.fw.version; + + // Saving file for next run! + if (!fs.existsSync(path.join(this.options.root, 'forge', this.version.id))) { + fs.mkdirSync(path.join(this.options.root, 'forge', this.version.id), { recursive: true }); } - } - - if (!fs.existsSync(path.join(jarPath, name))) await downloadLibrary(library) - if (library.downloads && library.downloads.artifact) { - if (!this.checkSum(library.downloads.artifact.sha1, path.join(jarPath, name))) await downloadLibrary(library) - } - - counter++ - this.client.emit('progress', { - type: eventName, - task: counter, - total: libraries.length - }) - libs.push(`${jarPath}${path.sep}${name}`) - })) - counter = 0 - - return libs - } - - async getClasses (classJson) { - let libs = [] - - const libraryDirectory = path.resolve(this.options.overrides.libraryRoot || path.join(this.options.root, 'libraries')) - - if (classJson) { - if (classJson.mavenFiles) { - await this.downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom') - } - libs = await this.downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom') + fs.writeFileSync(versionPath, JSON.stringify(json, null, 4)); + + // Make MCLC treat modern forge as a custom version json rather then legacy forge. + if (this.isModernForge(json)) this.options.forge = null; + + return json; } - const parsed = this.version.libraries.map(lib => { - if (lib.downloads && lib.downloads.artifact && !this.parseRule(lib)) return lib - }) + async downloadToDirectory(directory, libraries, eventName) { + const libs = []; + + await Promise.all( + libraries.map(async (library) => { + if (!library) return; + if (this.parseRule(library)) return; + const lib = library.name.split(':'); + + let jarPath; + let name; + if (library.downloads && library.downloads.artifact && library.downloads.artifact.path) { + name = + library.downloads.artifact.path.split('/')[ + library.downloads.artifact.path.split('/').length - 1 + ]; + jarPath = path.join(directory, this.popString(library.downloads.artifact.path)); + } else { + name = `${lib[1]}-${lib[2]}${lib[3] ? '-' + lib[3] : ''}.jar`; + jarPath = path.join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); + } + + const downloadLibrary = async (library) => { + if (library.url) { + const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; + await this.downloadAsync(url, jarPath, name, true, eventName); + } else if (library.downloads && library.downloads.artifact && library.downloads.artifact.url) { + // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. + await this.downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); + } + }; + + if (!fs.existsSync(path.join(jarPath, name))) await downloadLibrary(library); + if (library.downloads && library.downloads.artifact) { + if (!this.checkSum(library.downloads.artifact.sha1, path.join(jarPath, name))) + await downloadLibrary(library); + } + + counter++; + this.client.emit('progress', { + type: eventName, + task: counter, + total: libraries.length, + }); + libs.push(`${jarPath}${path.sep}${name}`); + }), + ); + counter = 0; + + return libs; + } - libs = libs.concat((await this.downloadToDirectory(libraryDirectory, parsed, 'classes'))) - counter = 0 + async getClasses(classJson) { + let libs = []; - // Temp Quilt support - if (classJson) libs.sort() + const libraryDirectory = path.resolve( + this.options.overrides.libraryRoot || path.join(this.options.root, 'libraries'), + ); - this.client.emit('debug', '[MCLC]: Collected class paths') - return libs - } + if (classJson) { + if (classJson.mavenFiles) { + await this.downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom'); + } + libs = await this.downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom'); + } - popString (path) { - return path.split('/').slice(0, -1).join('/') - } + const parsed = this.version.libraries.map((lib) => { + if (lib.downloads && lib.downloads.artifact && !this.parseRule(lib)) return lib; + }); - cleanUp (array) { - return [...new Set(Object.values(array).filter(value => value !== null))] - } + libs = libs.concat(await this.downloadToDirectory(libraryDirectory, parsed, 'classes')); + counter = 0; - formatQuickPlay () { - const types = { - singleplayer: '--quickPlaySingleplayer', - multiplayer: '--quickPlayMultiplayer', - realms: '--quickPlayRealms', - legacy: null - } - const { type, identifier, path } = this.options.quickPlay - const keys = Object.keys(types) - if (!keys.includes(type)) { - this.client.emit('debug', `[MCLC]: quickPlay type is not valid. Valid types are: ${keys.join(', ')}`) - return null + // Temp Quilt support + if (classJson) libs.sort(); + + this.client.emit('debug', '[MCLC]: Collected class paths'); + return libs; } - const returnArgs = type === 'legacy' - ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] - : [types[type], identifier] - if (path) returnArgs.push('--quickPlayPath', path) - return returnArgs - } - - async getLaunchOptions (modification) { - const type = Object.assign({}, this.version, modification) - - let args = type.minecraftArguments - ? type.minecraftArguments.split(' ') - : type.arguments.game - const assetRoot = path.resolve(this.options.overrides.assetRoot || path.join(this.options.root, 'assets')) - const assetPath = this.isLegacy() - ? path.join(this.options.root, 'resources') - : path.join(assetRoot) - - const minArgs = this.options.overrides.minArgs || this.isLegacy() ? 5 : 11 - if (args.length < minArgs) args = args.concat(this.version.minecraftArguments ? this.version.minecraftArguments.split(' ') : this.version.arguments.game) - if (this.options.customLaunchArgs) args = args.concat(this.options.customLaunchArgs) - - this.options.authorization = await Promise.resolve(this.options.authorization) - this.options.authorization.meta = this.options.authorization.meta ? this.options.authorization.meta : { type: 'mojang' } - const fields = { - '${auth_access_token}': this.options.authorization.access_token, - '${auth_session}': this.options.authorization.access_token, - '${auth_player_name}': this.options.authorization.name, - '${auth_uuid}': this.options.authorization.uuid, - '${auth_xuid}': this.options.authorization.meta.xuid || this.options.authorization.access_token, - '${user_properties}': this.options.authorization.user_properties, - '${user_type}': this.options.authorization.meta.type, - '${version_name}': this.options.version.number || this.options.overrides.versionName, - '${assets_index_name}': this.options.overrides.assetIndex || this.options.version.custom || this.options.version.number, - '${game_directory}': this.options.overrides.gameDirectory || this.options.root, - '${assets_root}': assetPath, - '${game_assets}': assetPath, - '${version_type}': this.options.version.type, - '${clientid}': this.options.authorization.meta.clientId || (this.options.authorization.client_token || this.options.authorization.access_token), - '${resolution_width}': this.options.window ? this.options.window.width : 856, - '${resolution_height}': this.options.window ? this.options.window.height : 482 + + popString(path) { + return path.split('/').slice(0, -1).join('/'); } - if (this.options.authorization.meta.demo && (this.options.features ? !this.options.features.includes('is_demo_user') : true)) { - args.push('--demo') + cleanUp(array) { + return [...new Set(Object.values(array).filter((value) => value !== null))]; } - const replaceArg = (obj, index) => { - if (Array.isArray(obj.value)) { - for (const arg of obj.value) { - args.push(arg) + formatQuickPlay() { + const types = { + singleplayer: '--quickPlaySingleplayer', + multiplayer: '--quickPlayMultiplayer', + realms: '--quickPlayRealms', + legacy: null, + }; + const { type, identifier, path } = this.options.quickPlay; + const keys = Object.keys(types); + if (!keys.includes(type)) { + this.client.emit('debug', `[MCLC]: quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); + return null; } - } else { - args.push(obj.value) - } - delete args[index] + const returnArgs = + type === 'legacy' + ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] + : [types[type], identifier]; + if (path) returnArgs.push('--quickPlayPath', path); + return returnArgs; } - for (let index = 0; index < args.length; index++) { - if (typeof args[index] === 'object') { - if (args[index].rules) { - if (!this.options.features) continue - const featureFlags = [] - for (const rule of args[index].rules) { - featureFlags.push(...Object.keys(rule.features)) - } - let hasAllRules = true - for (const feature of this.options.features) { - if (!featureFlags.includes(feature)) { - hasAllRules = false + async getLaunchOptions(modification) { + const type = Object.assign({}, this.version, modification); + + let args = type.minecraftArguments ? type.minecraftArguments.split(' ') : type.arguments.game; + const assetRoot = path.resolve(this.options.overrides.assetRoot || path.join(this.options.root, 'assets')); + const assetPath = this.isLegacy() ? path.join(this.options.root, 'resources') : path.join(assetRoot); + + const minArgs = this.options.overrides.minArgs || this.isLegacy() ? 5 : 11; + if (args.length < minArgs) + args = args.concat( + this.version.minecraftArguments + ? this.version.minecraftArguments.split(' ') + : this.version.arguments.game, + ); + if (this.options.customLaunchArgs) args = args.concat(this.options.customLaunchArgs); + + this.options.authorization = await Promise.resolve(this.options.authorization); + this.options.authorization.meta = this.options.authorization.meta + ? this.options.authorization.meta + : { type: 'mojang' }; + const fields = { + '${auth_access_token}': this.options.authorization.access_token, + '${auth_session}': this.options.authorization.access_token, + '${auth_player_name}': this.options.authorization.name, + '${auth_uuid}': this.options.authorization.uuid, + '${auth_xuid}': this.options.authorization.meta.xuid || this.options.authorization.access_token, + '${user_properties}': this.options.authorization.user_properties, + '${user_type}': this.options.authorization.meta.type, + '${version_name}': this.options.version.number || this.options.overrides.versionName, + '${assets_index_name}': + this.options.overrides.assetIndex || this.options.version.custom || this.options.version.number, + '${game_directory}': this.options.overrides.gameDirectory || this.options.root, + '${assets_root}': assetPath, + '${game_assets}': assetPath, + '${version_type}': this.options.version.type, + '${clientid}': + this.options.authorization.meta.clientId || + this.options.authorization.client_token || + this.options.authorization.access_token, + '${resolution_width}': this.options.window ? this.options.window.width : 856, + '${resolution_height}': this.options.window ? this.options.window.height : 482, + }; + + if ( + this.options.authorization.meta.demo && + (this.options.features ? !this.options.features.includes('is_demo_user') : true) + ) { + args.push('--demo'); + } + + const replaceArg = (obj, index) => { + if (Array.isArray(obj.value)) { + for (const arg of obj.value) { + args.push(arg); + } + } else { + args.push(obj.value); + } + delete args[index]; + }; + + for (let index = 0; index < args.length; index++) { + if (typeof args[index] === 'object') { + if (args[index].rules) { + if (!this.options.features) continue; + const featureFlags = []; + for (const rule of args[index].rules) { + featureFlags.push(...Object.keys(rule.features)); + } + let hasAllRules = true; + for (const feature of this.options.features) { + if (!featureFlags.includes(feature)) { + hasAllRules = false; + } + } + if (hasAllRules) replaceArg(args[index], index); + } else { + replaceArg(args[index], index); + } + } else { + if (Object.keys(fields).includes(args[index])) { + args[index] = fields[args[index]]; + } } - } - if (hasAllRules) replaceArg(args[index], index) - } else { - replaceArg(args[index], index) } - } else { - if (Object.keys(fields).includes(args[index])) { - args[index] = fields[args[index]] + if (this.options.window) { + if (this.options.window.fullscreen) { + args.push('--fullscreen'); + } else { + if (this.options.window.width) args.push('--width', this.options.window.width); + if (this.options.window.height) args.push('--height', this.options.window.height); + } } - } - } - if (this.options.window) { - if (this.options.window.fullscreen) { - args.push('--fullscreen') - } else { - if (this.options.window.width) args.push('--width', this.options.window.width) - if (this.options.window.height) args.push('--height', this.options.window.height) - } - } - if (this.options.server) this.client.emit('debug', '[MCLC]: server and port are deprecated launch flags. Use the quickPlay field.') - if (this.options.quickPlay) args = args.concat(this.formatQuickPlay()) - if (this.options.proxy) { - args.push( - '--proxyHost', - this.options.proxy.host, - '--proxyPort', - this.options.proxy.port || '8080', - '--proxyUser', - this.options.proxy.username, - '--proxyPass', - this.options.proxy.password - ) + if (this.options.server) + this.client.emit('debug', '[MCLC]: server and port are deprecated launch flags. Use the quickPlay field.'); + if (this.options.quickPlay) args = args.concat(this.formatQuickPlay()); + if (this.options.proxy) { + args.push( + '--proxyHost', + this.options.proxy.host, + '--proxyPort', + this.options.proxy.port || '8080', + '--proxyUser', + this.options.proxy.username, + '--proxyPass', + this.options.proxy.password, + ); + } + args = args.filter((value) => typeof value === 'string' || typeof value === 'number'); + this.client.emit('debug', '[MCLC]: Set launch options'); + return args; } - args = args.filter(value => typeof value === 'string' || typeof value === 'number') - this.client.emit('debug', '[MCLC]: Set launch options') - return args - } - - async getJVM () { - const opts = { - windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', - osx: '-XstartOnFirstThread', - linux: '-Xss1M' + + async getJVM() { + const opts = { + windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', + osx: '-XstartOnFirstThread', + linux: '-Xss1M', + }; + return opts[this.getOS()]; } - return opts[this.getOS()] - } - - isLegacy () { - return this.version.assets === 'legacy' || this.version.assets === 'pre-1.6' - } - - getOS () { - if (this.options.os) { - return this.options.os - } else { - switch (process.platform) { - case 'win32': return 'windows' - case 'darwin': return 'osx' - default: return 'linux' - } + + isLegacy() { + return this.version.assets === 'legacy' || this.version.assets === 'pre-1.6'; } - } - - // To prevent launchers from breaking when they update. Will be reworked with rewrite. - getMemory () { - if (!this.options.memory) { - this.client.emit('debug', '[MCLC]: Memory not set! Setting 1GB as MAX!') - this.options.memory = { - min: 512, - max: 1023 - } + + getOS() { + if (this.options.os) { + return this.options.os; + } else { + switch (process.platform) { + case 'win32': + return 'windows'; + case 'darwin': + return 'osx'; + default: + return 'linux'; + } + } } - if (!isNaN(this.options.memory.max) && !isNaN(this.options.memory.min)) { - if (this.options.memory.max < this.options.memory.min) { - this.client.emit('debug', '[MCLC]: MIN memory is higher then MAX! Resetting!') - this.options.memory.max = 1023 - this.options.memory.min = 512 - } - return [`${this.options.memory.max}M`, `${this.options.memory.min}M`] - } else { return [`${this.options.memory.max}`, `${this.options.memory.min}`] } - } - - async extractPackage (options = this.options) { - if (options.clientPackage.startsWith('http')) { - await this.downloadAsync(options.clientPackage, options.root, 'clientPackage.zip', true, 'client-package') - options.clientPackage = path.join(options.root, 'clientPackage.zip') + + // To prevent launchers from breaking when they update. Will be reworked with rewrite. + getMemory() { + if (!this.options.memory) { + this.client.emit('debug', '[MCLC]: Memory not set! Setting 1GB as MAX!'); + this.options.memory = { + min: 512, + max: 1023, + }; + } + if (!isNaN(this.options.memory.max) && !isNaN(this.options.memory.min)) { + if (this.options.memory.max < this.options.memory.min) { + this.client.emit('debug', '[MCLC]: MIN memory is higher then MAX! Resetting!'); + this.options.memory.max = 1023; + this.options.memory.min = 512; + } + return [`${this.options.memory.max}M`, `${this.options.memory.min}M`]; + } else { + return [`${this.options.memory.max}`, `${this.options.memory.min}`]; + } } - new Zip(options.clientPackage).extractAllTo(options.root, true) - if (options.removePackage) fs.unlinkSync(options.clientPackage) - return this.client.emit('package-extract', true) - } + async extractPackage(options = this.options) { + if (options.clientPackage.startsWith('http')) { + await this.downloadAsync(options.clientPackage, options.root, 'clientPackage.zip', true, 'client-package'); + options.clientPackage = path.join(options.root, 'clientPackage.zip'); + } + new Zip(options.clientPackage).extractAllTo(options.root, true); + if (options.removePackage) fs.unlinkSync(options.clientPackage); + + return this.client.emit('package-extract', true); + } } -module.exports = Handler +module.exports = Handler; diff --git a/components/launcher.js b/components/launcher.js index 2492281..a0008c5 100644 --- a/components/launcher.js +++ b/components/launcher.js @@ -1,192 +1,231 @@ -const child = require('child_process') -const path = require('path') -const Handler = require('./handler') -const fs = require('fs') -const EventEmitter = require('events').EventEmitter +const child = require('child_process'); +const path = require('path'); +const Handler = require('./handler'); +const fs = require('fs'); +const EventEmitter = require('events').EventEmitter; class MCLCore extends EventEmitter { - async launch (options) { - try { - this.options = { ...options } - this.options.root = path.resolve(this.options.root) - this.options.overrides = { - detached: true, - ...this.options.overrides, - url: { - meta: 'https://launchermeta.mojang.com', - resource: 'https://resources.download.minecraft.net', - mavenForge: 'https://files.minecraftforge.net/maven/', - defaultRepoForge: 'https://libraries.minecraft.net/', - fallbackMaven: 'https://search.maven.org/remotecontent?filepath=', - ...this.options.overrides - ? this.options.overrides.url - : undefined - }, - fw: { - baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', - version: '1.5.7', - sh1: '155ac9f4e5f65288eaacae19025ac4d9da1f0ef2', - size: 34910, - ...this.options.overrides - ? this.options.overrides.fw - : undefined + async launch(options) { + try { + this.options = { ...options }; + this.options.root = path.resolve(this.options.root); + this.options.overrides = { + detached: true, + ...this.options.overrides, + url: { + meta: 'https://launchermeta.mojang.com', + resource: 'https://resources.download.minecraft.net', + mavenForge: 'https://files.minecraftforge.net/maven/', + defaultRepoForge: 'https://libraries.minecraft.net/', + fallbackMaven: 'https://search.maven.org/remotecontent?filepath=', + ...(this.options.overrides ? this.options.overrides.url : undefined), + }, + fw: { + baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', + version: '1.5.7', + sh1: '155ac9f4e5f65288eaacae19025ac4d9da1f0ef2', + size: 34910, + ...(this.options.overrides ? this.options.overrides.fw : undefined), + }, + }; + + this.handler = new Handler(this); + + this.printVersion(); + + const java = await this.handler.checkJava(this.options.javaPath || 'java'); + if (!java.run) { + this.emit('debug', `[MCLC]: Couldn't start Minecraft due to: ${java.message}`); + this.emit('close', 1); + return null; + } + + this.createRootDirectory(); + this.createGameDirectory(); + + await this.extractPackage(); + + const directory = + this.options.overrides.directory || + path.join( + this.options.root, + 'versions', + this.options.version.custom ? this.options.version.custom : this.options.version.number, + ); + this.options.directory = directory; + + const versionFile = await this.handler.getVersion(); + const mcPath = + this.options.overrides.minecraftJar || + (this.options.version.custom + ? path.join( + this.options.root, + 'versions', + this.options.version.custom, + `${this.options.version.custom}.jar`, + ) + : path.join(directory, `${this.options.version.number}.jar`)); + this.options.mcPath = mcPath; + const nativePath = await this.handler.getNatives(); + + if (!fs.existsSync(mcPath)) { + this.emit('debug', '[MCLC]: Attempting to download Minecraft version jar'); + await this.handler.getJar(); + } + + const modifyJson = await this.getModifyJson(); + + const args = []; + + let jvm = [ + '-XX:-UseAdaptiveSizePolicy', + '-XX:-OmitStackTraceInFastThrow', + '-Dfml.ignorePatchDiscrepancies=true', + '-Dfml.ignoreInvalidMinecraftCertificates=true', + `-Djava.library.path=${nativePath}`, + `-Xmx${this.handler.getMemory()[0]}`, + `-Xms${this.handler.getMemory()[1]}`, + ]; + if (this.handler.getOS() === 'osx') { + if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()); + } else jvm.push(await this.handler.getJVM()); + + if (this.options.customArgs) jvm = jvm.concat(this.options.customArgs); + if (this.options.overrides.logj4ConfigurationFile) { + jvm.push(`-Dlog4j.configurationFile=${path.resolve(this.options.overrides.logj4ConfigurationFile)}`); + } + // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition + if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) + jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) < 17) { + if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { + const configPath = path.resolve(this.options.overrides.cwd || this.options.root); + const intVersion = parseInt(versionFile.id.split('.')[1]); + if (intVersion >= 12) { + await this.handler.downloadAsync( + 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', + configPath, + 'log4j2_112-116.xml', + true, + 'log4j', + ); + jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml'); + } else if (intVersion >= 7) { + await this.handler.downloadAsync( + 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', + configPath, + 'log4j2_17-111.xml', + true, + 'log4j', + ); + jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml'); + } + } + } + + const classes = + this.options.overrides.classes || this.handler.cleanUp(await this.handler.getClasses(modifyJson)); + const classPaths = ['-cp']; + const separator = this.handler.getOS() === 'windows' ? ';' : ':'; + this.emit('debug', `[MCLC]: Using ${separator} to separate class paths`); + // Handling launch arguments. + const file = modifyJson || versionFile; + // So mods like fabric work. + const jar = fs.existsSync(mcPath) + ? `${separator}${mcPath}` + : `${separator}${path.join(directory, `${this.options.version.number}.jar`)}`; + classPaths.push( + `${this.options.forge ? this.options.forge + separator : ''}${classes.join(separator)}${jar}`, + ); + classPaths.push(file.mainClass); + + this.emit('debug', '[MCLC]: Attempting to download assets'); + await this.handler.getAssets(); + + // Forge -> Custom -> Vanilla + const launchOptions = await this.handler.getLaunchOptions(modifyJson); + + const launchArguments = args.concat(jvm, classPaths, launchOptions); + this.emit('arguments', launchArguments); + this.emit('debug', `[MCLC]: Launching with arguments ${launchArguments.join(' ')}`); + + return this.startMinecraft(launchArguments); + } catch (e) { + this.emit('debug', `[MCLC]: Failed to start due to ${e}, closing...`); + return null; } - } - - this.handler = new Handler(this) - - this.printVersion() - - const java = await this.handler.checkJava(this.options.javaPath || 'java') - if (!java.run) { - this.emit('debug', `[MCLC]: Couldn't start Minecraft due to: ${java.message}`) - this.emit('close', 1) - return null - } - - this.createRootDirectory() - this.createGameDirectory() - - await this.extractPackage() - - const directory = this.options.overrides.directory || path.join(this.options.root, 'versions', this.options.version.custom ? this.options.version.custom : this.options.version.number) - this.options.directory = directory - - const versionFile = await this.handler.getVersion() - const mcPath = this.options.overrides.minecraftJar || (this.options.version.custom - ? path.join(this.options.root, 'versions', this.options.version.custom, `${this.options.version.custom}.jar`) - : path.join(directory, `${this.options.version.number}.jar`)) - this.options.mcPath = mcPath - const nativePath = await this.handler.getNatives() - - if (!fs.existsSync(mcPath)) { - this.emit('debug', '[MCLC]: Attempting to download Minecraft version jar') - await this.handler.getJar() - } - - const modifyJson = await this.getModifyJson() - - const args = [] - - let jvm = [ - '-XX:-UseAdaptiveSizePolicy', - '-XX:-OmitStackTraceInFastThrow', - '-Dfml.ignorePatchDiscrepancies=true', - '-Dfml.ignoreInvalidMinecraftCertificates=true', - `-Djava.library.path=${nativePath}`, - `-Xmx${this.handler.getMemory()[0]}`, - `-Xms${this.handler.getMemory()[1]}` - ] - if (this.handler.getOS() === 'osx') { - if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()) - } else jvm.push(await this.handler.getJVM()) - - if (this.options.customArgs) jvm = jvm.concat(this.options.customArgs) - if (this.options.overrides.logj4ConfigurationFile) { - jvm.push(`-Dlog4j.configurationFile=${path.resolve(this.options.overrides.logj4ConfigurationFile)}`) - } - // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition - if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) jvm.push('-Dlog4j2.formatMsgNoLookups=true') - if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true') - if (parseInt(versionFile.id.split('.')[1]) < 17) { - if (!jvm.find(arg => arg.includes('Dlog4j.configurationFile'))) { - const configPath = path.resolve(this.options.overrides.cwd || this.options.root) - const intVersion = parseInt(versionFile.id.split('.')[1]) - if (intVersion >= 12) { - await this.handler.downloadAsync('https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', - configPath, 'log4j2_112-116.xml', true, 'log4j') - jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml') - } else if (intVersion >= 7) { - await this.handler.downloadAsync('https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', - configPath, 'log4j2_17-111.xml', true, 'log4j') - jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml') - } + } + + printVersion() { + if (fs.existsSync(path.join(__dirname, '..', 'package.json'))) { + const { version } = require('../package.json'); + this.emit('debug', `[MCLC]: MCLC version ${version}`); + } else { + this.emit('debug', '[MCLC]: Package JSON not found, skipping MCLC version check.'); } - } - - const classes = this.options.overrides.classes || this.handler.cleanUp(await this.handler.getClasses(modifyJson)) - const classPaths = ['-cp'] - const separator = this.handler.getOS() === 'windows' ? ';' : ':' - this.emit('debug', `[MCLC]: Using ${separator} to separate class paths`) - // Handling launch arguments. - const file = modifyJson || versionFile - // So mods like fabric work. - const jar = fs.existsSync(mcPath) - ? `${separator}${mcPath}` - : `${separator}${path.join(directory, `${this.options.version.number}.jar`)}` - classPaths.push(`${this.options.forge ? this.options.forge + separator : ''}${classes.join(separator)}${jar}`) - classPaths.push(file.mainClass) - - this.emit('debug', '[MCLC]: Attempting to download assets') - await this.handler.getAssets() - - // Forge -> Custom -> Vanilla - const launchOptions = await this.handler.getLaunchOptions(modifyJson) - - const launchArguments = args.concat(jvm, classPaths, launchOptions) - this.emit('arguments', launchArguments) - this.emit('debug', `[MCLC]: Launching with arguments ${launchArguments.join(' ')}`) - - return this.startMinecraft(launchArguments) - } catch (e) { - this.emit('debug', `[MCLC]: Failed to start due to ${e}, closing...`) - return null } - } - - printVersion () { - if (fs.existsSync(path.join(__dirname, '..', 'package.json'))) { - const { version } = require('../package.json') - this.emit('debug', `[MCLC]: MCLC version ${version}`) - } else { this.emit('debug', '[MCLC]: Package JSON not found, skipping MCLC version check.') } - } - - createRootDirectory () { - if (!fs.existsSync(this.options.root)) { - this.emit('debug', '[MCLC]: Attempting to create root folder') - fs.mkdirSync(this.options.root) + + createRootDirectory() { + if (!fs.existsSync(this.options.root)) { + this.emit('debug', '[MCLC]: Attempting to create root folder'); + fs.mkdirSync(this.options.root); + } } - } - - createGameDirectory () { - if (this.options.overrides.gameDirectory) { - this.options.overrides.gameDirectory = path.resolve(this.options.overrides.gameDirectory) - if (!fs.existsSync(this.options.overrides.gameDirectory)) { - fs.mkdirSync(this.options.overrides.gameDirectory, { recursive: true }) - } + + createGameDirectory() { + if (this.options.overrides.gameDirectory) { + this.options.overrides.gameDirectory = path.resolve(this.options.overrides.gameDirectory); + if (!fs.existsSync(this.options.overrides.gameDirectory)) { + fs.mkdirSync(this.options.overrides.gameDirectory, { recursive: true }); + } + } } - } - async extractPackage () { - if (this.options.clientPackage) { - this.emit('debug', `[MCLC]: Extracting client package to ${this.options.root}`) - await this.handler.extractPackage() + async extractPackage() { + if (this.options.clientPackage) { + this.emit('debug', `[MCLC]: Extracting client package to ${this.options.root}`); + await this.handler.extractPackage(); + } } - } - - async getModifyJson () { - let modifyJson = null - - if (this.options.forge) { - this.options.forge = path.resolve(this.options.forge) - this.emit('debug', '[MCLC]: Detected Forge in options, getting dependencies') - modifyJson = await this.handler.getForgedWrapped() - } else if (this.options.version.custom) { - this.emit('debug', '[MCLC]: Detected custom in options, setting custom version file') - modifyJson = modifyJson || JSON.parse(fs.readFileSync(path.join(this.options.root, 'versions', this.options.version.custom, `${this.options.version.custom}.json`), { encoding: 'utf8' })) + + async getModifyJson() { + let modifyJson = null; + + if (this.options.forge) { + this.options.forge = path.resolve(this.options.forge); + this.emit('debug', '[MCLC]: Detected Forge in options, getting dependencies'); + modifyJson = await this.handler.getForgedWrapped(); + } else if (this.options.version.custom) { + this.emit('debug', '[MCLC]: Detected custom in options, setting custom version file'); + modifyJson = + modifyJson || + JSON.parse( + fs.readFileSync( + path.join( + this.options.root, + 'versions', + this.options.version.custom, + `${this.options.version.custom}.json`, + ), + { encoding: 'utf8' }, + ), + ); + } + + return modifyJson; } - return modifyJson - } - - startMinecraft (launchArguments) { - const minecraft = child.spawn(this.options.javaPath ? this.options.javaPath : 'java', launchArguments, - { cwd: this.options.overrides.cwd || this.options.root, detached: this.options.overrides.detached }) - minecraft.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))) - minecraft.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))) - minecraft.on('close', (code) => this.emit('close', code)) - return minecraft - } + startMinecraft(launchArguments) { + const minecraft = child.spawn(this.options.javaPath ? this.options.javaPath : 'java', launchArguments, { + cwd: this.options.overrides.cwd || this.options.root, + detached: this.options.overrides.detached, + }); + minecraft.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))); + minecraft.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))); + minecraft.on('close', (code) => this.emit('close', code)); + return minecraft; + } } -module.exports = MCLCore +module.exports = MCLCore; diff --git a/index.d.ts b/index.d.ts index f440e7f..a5080e3 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,308 +1,292 @@ /// -declare module "minecraft-launcher-core" { - type OS = "windows" | "osx" | "linux"; +declare module 'minecraft-launcher-core' { + interface IOverrides { + /** + * The amount of launch arguments specified in the version file before it adds the default again + */ + minArgs?: number; + minecraftJar?: string; + versionJson?: string; + versionName?: string; + /** + * Folder, where the game process generates folders like saves and resource packs. + */ + gameDirectory?: string; + /** + * Folder, where the Minecraft jar and version json are located. + */ + directory?: string; + natives?: string; + assetRoot?: string; + assetIndex?: string; + libraryRoot?: string; + /** + * Working directory of the java process. + */ + cwd?: string; + /** + * Whether or not the client is detached from the parent / launcher. + */ + detached?: boolean; + /** + * List of classes. + * All class paths are required if you use this. + */ + classes?: Array; + /** + * Max sockets for downloadAsync. + */ + maxSockets?: number; + /** + * Urls to the Minecraft and Forge resource servers + * + * This is for launcher developers located in countries that have the Minecraft and Forge resource servers + * blocked for what ever reason. They obviously need to mirror the formatting of the original JSONs / file structures. + */ + url?: { + /** + * List of versions. + */ + meta?: string; + /** + * Minecraft resources. + */ + resource?: string; + /** + * Forge resources. + */ + mavenForge?: string; + /** + * for Forge only, you need to redefine the library url in the version json. + */ + defaultRepoForge?: string; + /** + * + */ + fallbackMaven?: string; + }; + /** + * Version of the ForgeWrapper which MCLC uses. This allows us to launch modern Forge. + */ + fw?: { + baseUrl?: string; + version?: string; + sh1?: string; + size?: number; + }; + logj4ConfigurationFile?: string; + } - interface IOverrides { - /** - * The amount of launch arguments specified in the version file before it adds the default again - */ - minArgs?: number; - minecraftJar?: string; - versionJson?: string; - versionName?: string; - /** - * Folder, where the game process generates folders like saves and resource packs. - */ - gameDirectory?: string; - /** - * Folder, where the Minecraft jar and version json are located. - */ - directory?: string; - natives?: string; - assetRoot?: string; - assetIndex?: string; - libraryRoot?: string; - /** - * Working directory of the java process. - */ - cwd?: string; - /** - * Whether or not the client is detached from the parent / launcher. - */ - detached?: boolean; - /** - * List of classes. - * All class paths are required if you use this. - */ - classes?: Array; - /** - * Max sockets for downloadAsync. - */ - maxSockets?: number; - /** - * Urls to the Minecraft and Forge resource servers - * - * This is for launcher developers located in countries that have the Minecraft and Forge resource servers - * blocked for what ever reason. They obviously need to mirror the formatting of the original JSONs / file structures. - */ - url?: { - /** - * List of versions. - */ - meta?: string; - /** - * Minecraft resources. - */ - resource?: string; - /** - * Forge resources. - */ - mavenForge?: string; - /** - * for Forge only, you need to redefine the library url in the version json. - */ - defaultRepoForge?: string; - /** - * - */ - fallbackMaven?: string; - }; - /** - * Version of the ForgeWrapper which MCLC uses. This allows us to launch modern Forge. - */ - fw?: { - baseUrl?: string; - version?: string; - sh1?: string; - size?: number; - }; - logj4ConfigurationFile?: string; - } + interface ILauncherOptions { + /** + * Path or URL to the client package zip file. + */ + clientPackage?: string; + /** + * if true MCLC will remove the client package zip file after its finished extracting. + */ + removePackage?: boolean; + /** + * Path where you want the launcher to work in. + * This will usually be your .minecraft folder + */ + root: string; + /** + * OS override for minecraft natives + * + * @default will autodetect + */ + os?: 'windows' | 'osx' | 'linux'; + /** + * Array of custom Minecraft arguments. + */ + customLaunchArgs?: Array; + /** + * Array of custom Java arguments + */ + customArgs?: Array; + /** + * Array of game argument feature flags + */ + features?: Array; + /** + * minecraft version info + */ + version: { + /** + * Actual version. + * + * @example '1.16.4' + */ + number: string; + /** + * type of release, usually `release` or `snapshot` + */ + type: 'release' | 'snapshot' | string; + /** + * The name of the folder, jar file, and version json in the version folder. + * + * ` MCLC will look in the `versions` folder for this name + * @example '1.16.4-fabric' + */ + custom?: string; + }; + memory: { + /** + * Min amount of memory being used by Minecraft. + */ + max: string | number; + /** + * Max amount of memory being used by Minecraft. + */ + min: string | number; + }; + /** + * Path to Forge Jar. + * + * Versions below 1.13 should be the "universal" jar while versions above 1.13+ should be the "installer" jar + */ + forge?: string; + /** + * Path to the JRE executable file, will default to java if not entered. + */ + javaPath?: string; + proxy?: { + /** + * Host url to the proxy, don't include the port. + */ + host: string; + /** + * Username for the proxy. + * + * @default 8080 + */ + port?: string; + /** + * Username for the proxy. + */ + username?: string; + /** + * Password for the proxy. + */ + password?: string; + }; + /** + * Timeout on download requests. + */ + timeout?: number; + window?: { + /** + * Width of the Minecraft Client + */ + width?: number; + /** + * Height of the Minecraft Client + */ + height?: number; + /** + * Fullscreen the Minecraft Client. + */ + fullscreen?: boolean; + }; - interface ILauncherOptions { - /** - * Path or URL to the client package zip file. - */ - clientPackage?: string; - /** - * if true MCLC will remove the client package zip file after its finished extracting. - */ - removePackage?: boolean; - /** - * Path where you want the launcher to work in. - * This will usually be your .minecraft folder - */ - root: string; - /** - * OS override for minecraft natives - * - * @default will autodetect - */ - os?: OS; - /** - * Array of custom Minecraft arguments. - */ - customLaunchArgs?: Array; - /** - * Array of custom Java arguments - */ - customArgs?: Array; - /** - * Array of game argument feature flags - */ - features?: Array; - /** - * minecraft version info - */ - version: { - /** - * Actual version. - * - * @example '1.16.4' - */ - number: string; - /** - * type of release, usually `release` or `snapshot` - */ - type: 'release' | 'snapshot' | string; - /** - * The name of the folder, jar file, and version json in the version folder. - * - * ` MCLC will look in the `versions` folder for this name - * @example '1.16.4-fabric' - */ - custom?: string; - }; - memory: { - /** - * Min amount of memory being used by Minecraft. - */ - max: string | number; - /** - * Max amount of memory being used by Minecraft. - */ - min: string | number; - }; - /** - * Path to Forge Jar. - * - * Versions below 1.13 should be the "universal" jar while versions above 1.13+ should be the "installer" jar - */ - forge?: string; - /** - * Path to the JRE executable file, will default to java if not entered. - */ - javaPath?: string; - proxy?: { - /** - * Host url to the proxy, don't include the port. - */ - host: string; - /** - * Username for the proxy. - * - * @default 8080 - */ - port?: string; - /** - * Username for the proxy. - */ - username?: string; - /** - * Password for the proxy. - */ - password?: string; - }; - /** - * Timeout on download requests. - */ - timeout?: number; - window?: { + /** + * Allows the game to be launched directly into a world + */ + quickPlay?: { + /** + * The type of world you want to join. + * Note, that versions prior to 1.20 only support "legacy" + */ + type: 'singleplayer' | 'multiplayer' | 'realms' | 'legacy'; + /** + * Represents the world you want to join + * + * For singleplayer this should be the folder name of the world + * For multiplayer this should be the IP address of the server + * For realms this should be the Realms ID + * legacy follows multiplayer format + */ + identifier: string; + /** + * The specified path for logging (relative to the run directory) + */ + path?: string; + }; + /** + * Json object redefining paths for better customization + */ + overrides?: IOverrides; - /** - * Width of the Minecraft Client - */ - width?: number; - /** - * Height of the Minecraft Client - */ - height?: number; - /** - * Fullscreen the Minecraft Client. - */ - fullscreen?: boolean; - }; + authorization: Promise | IUser; + /** + * Path of json cache. + */ + cache?: string; + } + interface IUser { + access_token: string; + client_token: string; + uuid: string; + name: string; + user_properties: Partial; + meta?: { + type: 'mojang' | 'msa'; + demo?: boolean; + }; + } - /** - * Allows the game to be launched directly into a world - */ - quickPlay?: { - /** - * The type of world you want to join. - * Note, that versions prior to 1.20 only support "legacy" - */ - type: 'singleplayer' | 'multiplayer' | 'realms' | 'legacy'; - /** - * Represents the world you want to join - * - * For singleplayer this should be the folder name of the world - * For multiplayer this should be the IP address of the server - * For realms this should be the Realms ID - * legacy follows multiplayer format - */ - identifier: string; - /** - * The specified path for logging (relative to the run directory) - */ - path?: string; - }; - /** - * Json object redefining paths for better customization - */ - overrides?: IOverrides; + interface IProfile { + id: number; + name: string; + } - authorization: Promise | IUser; - /** - * Path of json cache. - */ - cache?: string; - } + interface IAuthenticator { + /** + * @param username email if using a password, else the username + * @param password password for mojang account + */ + getAuth(username: string, password?: string): Promise; + /** + * + * @param access_token Token being checked if it can be used to login with (online mode) + * @param client_token Client token being checked to see if there was a change of client (online mode) + */ + validate(access_token: string, client_token: string): Promise>; + /** + * + * @param access_token Token being checked if it can be used to login with (online mode) + * @param client_token Client token being checked to see if there was a change of client (online mode) + */ + refreshAuth(access_token: string, client_token: string): Promise; + /** + * + * @param access_token Token being checked if it can be used to login with (online mode) + * @param client_token Client token being checked to see if there was a change of client (online mode) + */ + invalidate(access_token: string, client_token: string): Promise>; + /** + * @param username email if using a password, else the username + * @param password password for mojang account + */ + signOut(username: string, password: string): Promise>; + changeApiUrl(url: string): void; + } - interface IUser { - access_token: string; - client_token: string; - uuid: string; - name: string; - user_properties: Partial; - meta?: { - type: "mojang" | "msa", - demo?: boolean - }; - } + import { EventEmitter } from 'events'; + import { ChildProcessWithoutNullStreams } from 'child_process'; - interface IProfile { - id: number; - name: string; - } + export class Client extends EventEmitter { + launch(options: ILauncherOptions): Promise; + protected printVersion(): void; + protected createRootDirectory(): void; + protected createGameDirectory(): void; + protected extractPackage(): Promise; + protected getModifyJson(): Promise; + protected startMinecraft(launchArguments: string[]): ChildProcessWithoutNullStreams; + } - interface IAuthenticator { - /** - * @param username email if using a password, else the username - * @param password password for mojang account - */ - getAuth(username: string, password?: string): Promise; - /** - * - * @param access_token Token being checked if it can be used to login with (online mode) - * @param client_token Client token being checked to see if there was a change of client (online mode) - */ - validate( - access_token: string, - client_token: string - ): Promise>; - /** - * - * @param access_token Token being checked if it can be used to login with (online mode) - * @param client_token Client token being checked to see if there was a change of client (online mode) - */ - refreshAuth( - access_token: string, - client_token: string, - ): Promise; - /** - * - * @param access_token Token being checked if it can be used to login with (online mode) - * @param client_token Client token being checked to see if there was a change of client (online mode) - */ - invalidate( - access_token: string, - client_token: string - ): Promise>; - /** - * @param username email if using a password, else the username - * @param password password for mojang account - */ - signOut( - username: string, - password: string - ): Promise>; - changeApiUrl(url: string): void; - } - - import { EventEmitter } from 'events' - import { ChildProcessWithoutNullStreams } from 'child_process' - - export class Client extends EventEmitter { - launch(options: ILauncherOptions): Promise; - protected printVersion(): void; - protected createRootDirectory(): void; - protected createGameDirectory(): void; - protected extractPackage(): Promise; - protected getModifyJson(): Promise; - protected startMinecraft(launchArguments: string[]): ChildProcessWithoutNullStreams; - } - - export const Authenticator: IAuthenticator; + export const Authenticator: IAuthenticator; } diff --git a/index.js b/index.js index 042698f..5cc4c4f 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ module.exports = { - Client: require('./components/launcher'), - Authenticator: require('./components/authenticator') -} + Client: require('./components/launcher'), + Authenticator: require('./components/authenticator'), +}; diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index f1ef4e6..0000000 --- a/package-lock.json +++ /dev/null @@ -1,2464 +0,0 @@ -{ - "name": "minecraft-launcher-core", - "version": "3.18.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "minecraft-launcher-core", - "version": "3.18.0", - "license": "MIT", - "dependencies": { - "adm-zip": "^0.4.13", - "checksum": "^0.1.1", - "request": "^2.88.2", - "uuid": "^8.3.2" - }, - "devDependencies": { - "@types/checksum": "^0.1.35", - "@types/node": "^14.0.27", - "eslint": "^6.8.0", - "eslint-config-standard": "^14.1.1", - "eslint-plugin-import": "^2.20.2", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.1" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.8.3" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.9.5", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/highlight": { - "version": "7.9.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.9.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@types/checksum": { - "version": "0.1.35", - "resolved": "https://registry.npmjs.org/@types/checksum/-/checksum-0.1.35.tgz", - "integrity": "sha512-Tm3eaZOW4viqdSPa1Y3HFJBqzmTqgChTfeFqBV8Xyevvf3IIG5Uo8WOHFRLhdUTADnz5waK7KC11V+tBfXnqkw==", - "dev": true - }, - "node_modules/@types/color-name": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "14.0.27", - "dev": true, - "license": "MIT" - }, - "node_modules/acorn": { - "version": "7.1.1", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0" - } - }, - "node_modules/adm-zip": { - "version": "0.4.13", - "license": "MIT", - "engines": { - "node": ">=0.3.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.11.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.11.0", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-includes": { - "version": "3.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0", - "is-string": "^1.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "node_modules/chalk": { - "version": "2.4.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "dev": true, - "license": "MIT" - }, - "node_modules/checksum": { - "version": "0.1.1", - "license": "MIT", - "dependencies": { - "optimist": "~0.3.5" - }, - "bin": { - "checksum": "bin/checksum-cli.js" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-width": { - "version": "2.2.1", - "dev": true, - "license": "ISC" - }, - "node_modules/color-convert": { - "version": "1.9.3", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/contains-path": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" - }, - "node_modules/cross-spawn": { - "version": "6.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/cross-spawn/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/define-properties": { - "version": "1.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.17.5", - "dev": true, - "license": "MIT", - "dependencies": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "6.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.3", - "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-standard": { - "version": "14.1.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=6.2.2", - "eslint-plugin-import": ">=2.18.0", - "eslint-plugin-node": ">=9.1.0", - "eslint-plugin-promise": ">=4.2.1", - "eslint-plugin-standard": ">=4.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^2.6.9", - "resolve": "^1.13.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-import-resolver-node/node_modules/resolve": { - "version": "1.17.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.6.0", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^2.6.9", - "pkg-dir": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-es": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-es/node_modules/eslint-utils": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-plugin-es/node_modules/regexpp": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.20.2", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.0.3", - "array.prototype.flat": "^1.2.1", - "contains-path": "^0.1.0", - "debug": "^2.6.9", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.1", - "has": "^1.0.3", - "minimatch": "^3.0.4", - "object.values": "^1.1.0", - "read-pkg-up": "^2.0.0", - "resolve": "^1.12.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "2.x - 6.x" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "1.5.0", - "dev": true, - "dependencies": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint-plugin-import/node_modules/resolve": { - "version": "1.17.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/eslint-utils": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-plugin-node/node_modules/ignore": { - "version": "5.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint-plugin-node/node_modules/resolve": { - "version": "1.17.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-promise": { - "version": "4.2.1", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-plugin-standard": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=5.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.0.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "1.4.3", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "1.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/espree": { - "version": "6.2.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^7.1.1", - "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.3.1", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.1.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.2.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^4.1.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/figures": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-entry-cache": { - "version": "5.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/find-up": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flat-cache": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flatted": { - "version": "2.0.2", - "dev": true, - "license": "ISC" - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "7.1.3", - "dev": true, - "license": "ISC", - "dependencies": { - "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" - }, - "engines": { - "node": "*" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "12.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.4", - "dev": true, - "license": "ISC" - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-symbols": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "dev": true, - "license": "ISC" - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "4.0.6", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/inquirer": { - "version": "7.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", - "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^3.0.0", - "lodash": "^4.17.15", - "mute-stream": "0.0.8", - "run-async": "^2.4.0", - "rxjs": "^6.5.3", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0", - "through": "^2.3.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/inquirer/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/inquirer/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/strip-ansi": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/supports-color": { - "version": "7.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/is-callable": { - "version": "1.1.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-string": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/isarray": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/levn": { - "version": "0.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/load-json-file": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/locate-path": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "dev": true, - "license": "MIT" - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/mute-stream": { - "version": "0.0.8", - "dev": true, - "license": "ISC" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "node_modules/nice-try": { - "version": "1.0.5", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/resolve": { - "version": "1.17.0", - "dev": true, - "license": "MIT", - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/object-inspect": { - "version": "1.7.0", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/optimist": { - "version": "0.3.7", - "license": "MIT/X11", - "dependencies": { - "wordwrap": "~0.0.2" - } - }, - "node_modules/optionator": { - "version": "0.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-locate": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-exists": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "node_modules/pify": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pkg-dir": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/read-pkg": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regexpp": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.5.0" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/rimraf": { - "version": "2.6.3", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/run-async": { - "version": "2.4.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/rxjs": { - "version": "6.5.5", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/shebang-command": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/shebang-regex": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/slice-ansi": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/spdx-correct": { - "version": "3.1.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.5", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimleft": { - "version": "2.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimstart": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimright": { - "version": "2.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5", - "string.prototype.trimend": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/table": { - "version": "5.4.6", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/table/node_modules/emoji-regex": { - "version": "7.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/string-width": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "license": "MIT" - }, - "node_modules/through": { - "version": "2.3.8", - "dev": true, - "license": "MIT" - }, - "node_modules/tmp": { - "version": "0.0.33", - "dev": true, - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tslib": { - "version": "1.11.2", - "dev": true, - "license": "0BSD" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/type-check": { - "version": "0.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.8.1", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/uri-js": { - "version": "4.2.2", - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/which": { - "version": "1.3.1", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "0.0.3", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "dev": true, - "license": "ISC" - }, - "node_modules/write": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=4" - } - } - } -} diff --git a/package.json b/package.json index 3a8d43b..82d6303 100644 --- a/package.json +++ b/package.json @@ -1,42 +1,44 @@ { - "name": "minecraft-launcher-core", - "version": "3.18.0", - "description": "Lightweight module that downloads and runs Minecraft using javascript / NodeJS", - "main": "index.js", - "dependencies": { - "adm-zip": "^0.4.13", - "checksum": "^0.1.1", - "request": "^2.88.2", - "uuid": "^8.3.2" - }, - "devDependencies": { - "@types/checksum": "^0.1.35", - "@types/node": "^14.0.27", - "eslint": "^6.8.0", - "eslint-config-standard": "^14.1.1", - "eslint-plugin-import": "^2.20.2", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.1" - }, - "scripts": { - "test": "eslint ." - }, - "repository": { - "type": "git", - "url": "git+https://github.com/Pierce01/MinecraftLauncher-core.git" - }, - "keywords": [ - "minecraft", - "minecraft-launcher-node", - "minecraft-launcher", - "launcher", - "minecraft-forge" - ], - "author": "Pierce Harriz", - "license": "MIT", - "bugs": { - "url": "https://github.com/Pierce01/MinecraftLauncher-core/issues" - }, - "homepage": "https://github.com/Pierce01/MinecraftLauncher-core#readme" + "name": "minecraft-launcher-core", + "version": "3.18.0", + "description": "Lightweight module that downloads and runs Minecraft using javascript / NodeJS", + "main": "index.js", + "dependencies": { + "adm-zip": "^0.4.13", + "checksum": "^0.1.1", + "request": "^2.88.2", + "uuid": "^8.3.2" + }, + "devDependencies": { + "@ianvs/prettier-plugin-sort-imports": "^4.1.1", + "@types/checksum": "^0.1.35", + "@types/node": "^14.0.27", + "@types/request": "^2.48.12", + "@typescript-eslint/eslint-plugin": "^7.1.0", + "@typescript-eslint/parser": "^7.1.0", + "eslint": "^8.57.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "prettier": "^3.2.5" + }, + "scripts": { + "test": "eslint ." + }, + "repository": { + "type": "git", + "url": "git+https://github.com/Pierce01/MinecraftLauncher-core.git" + }, + "keywords": [ + "minecraft", + "minecraft-launcher-node", + "minecraft-launcher", + "launcher", + "minecraft-forge" + ], + "author": "Pierce Harriz", + "license": "MIT", + "bugs": { + "url": "https://github.com/Pierce01/MinecraftLauncher-core/issues" + }, + "homepage": "https://github.com/Pierce01/MinecraftLauncher-core#readme" } diff --git a/test.js b/test.js index d4777e0..1a72e05 100644 --- a/test.js +++ b/test.js @@ -1,18 +1,18 @@ -const { Client, Authenticator } = require("."); +const { Client, Authenticator } = require('.'); const launcher = new Client(); launcher.launch({ - authorization: Authenticator.getAuth("username"), - root: "./minecraft", - version: { - number: "1.7.10", - type: "release", - }, - memory: { - max: "4G", - min: "2G", - }, + authorization: Authenticator.getAuth('username'), + root: './minecraft', + version: { + number: '1.7.10', + type: 'release', + }, + memory: { + max: '4G', + min: '2G', + }, }); -launcher.on("debug", (e) => console.log(e)); -launcher.on("data", (e) => console.log(e)); +launcher.on('debug', (e) => console.log(e)); +launcher.on('data', (e) => console.log(e)); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..73bd5f8 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1675 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@ampproject/remapping@^2.2.0": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + +"@babel/compat-data@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" + integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== + +"@babel/core@^7.21.8": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" + integrity sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.23.9" + "@babel/parser" "^7.23.9" + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.21.5", "@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + +"@babel/helper-compilation-targets@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz#4d79069b16cbcf1461289eccfbbd81501ae39991" + integrity sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ== + dependencies: + "@babel/compat-data" "^7.23.5" + "@babel/helper-validator-option" "^7.23.5" + browserslist "^4.22.2" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-module-imports@^7.22.15": + version "7.22.15" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" + integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== + dependencies: + "@babel/types" "^7.22.15" + +"@babel/helper-module-transforms@^7.23.3": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" + integrity sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ== + dependencies: + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-module-imports" "^7.22.15" + "@babel/helper-simple-access" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/helper-validator-identifier" "^7.22.20" + +"@babel/helper-simple-access@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" + integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz#322c61b7310c0997fe4c323955667f18fcefb91c" + integrity sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g== + dependencies: + "@babel/types" "^7.22.5" + +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/helper-validator-option@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" + integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== + +"@babel/helpers@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d" + integrity sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ== + dependencies: + "@babel/template" "^7.23.9" + "@babel/traverse" "^7.23.9" + "@babel/types" "^7.23.9" + +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.21.8", "@babel/parser@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== + +"@babel/template@^7.22.15", "@babel/template@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" + integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + +"@babel/traverse@^7.21.5", "@babel/traverse@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" + integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.21.5", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== + +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== + dependencies: + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" + integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== + +"@ianvs/prettier-plugin-sort-imports@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.1.1.tgz#364fb49c4104d577c80750dcc27a7bae4338095d" + integrity sha512-kJhXq63ngpTQ2dxgf5GasbPJWsJA3LgoOdd7WGhpUSzLgLgI4IsIzYkbJf9kmpOHe7Vdm/o3PcRA3jmizXUuAQ== + dependencies: + "@babel/core" "^7.21.8" + "@babel/generator" "^7.21.5" + "@babel/parser" "^7.21.8" + "@babel/traverse" "^7.21.5" + "@babel/types" "^7.21.5" + semver "^7.5.2" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz#9b18145d26cf33d08576cf4c7665b28554480ed7" + integrity sha512-Oud2QPM5dHviZNn4y/WhhYKSXksv+1xLEIsNrAbGcFzUN3ubqWRFT5gwPchNc5NuzILOU4tPBDTZ4VwhL8Y7cw== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.23" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz#afc96847f3f07841477f303eed687707a5aacd80" + integrity sha512-9/4foRoUKp8s96tSkh8DlAAc5A0Ty8vLXld+l9gjKKY6ckwI8G15f0hskGmuLZu78ZlGa1vtsfOa+lnB4vG6Jg== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@pkgr/core@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" + integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== + +"@types/caseless@*": + version "0.12.5" + resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.5.tgz#db9468cb1b1b5a925b8f34822f1669df0c5472f5" + integrity sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg== + +"@types/checksum@^0.1.35": + version "0.1.35" + resolved "https://registry.yarnpkg.com/@types/checksum/-/checksum-0.1.35.tgz#f1f9a4afd536101981a767f7a2b06618935dad67" + integrity sha512-Tm3eaZOW4viqdSPa1Y3HFJBqzmTqgChTfeFqBV8Xyevvf3IIG5Uo8WOHFRLhdUTADnz5waK7KC11V+tBfXnqkw== + +"@types/json-schema@^7.0.12": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/node@*": + version "20.11.20" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.20.tgz#f0a2aee575215149a62784210ad88b3a34843659" + integrity sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg== + dependencies: + undici-types "~5.26.4" + +"@types/node@^14.0.27": + version "14.18.63" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b" + integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ== + +"@types/request@^2.48.12": + version "2.48.12" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.12.tgz#0f590f615a10f87da18e9790ac94c29ec4c5ef30" + integrity sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.0" + +"@types/semver@^7.5.0": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + +"@typescript-eslint/eslint-plugin@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz#22bb999a8d59893c0ea07923e8a21f9d985ad740" + integrity sha512-j6vT/kCulhG5wBmGtstKeiVr1rdXE4nk+DT1k6trYkwlrvW9eOF5ZbgKnd/YR6PcM4uTEXa0h6Fcvf6X7Dxl0w== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "7.1.0" + "@typescript-eslint/type-utils" "7.1.0" + "@typescript-eslint/utils" "7.1.0" + "@typescript-eslint/visitor-keys" "7.1.0" + debug "^4.3.4" + graphemer "^1.4.0" + ignore "^5.2.4" + natural-compare "^1.4.0" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/parser@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.1.0.tgz#b89dab90840f7d2a926bf4c23b519576e8c31970" + integrity sha512-V1EknKUubZ1gWFjiOZhDSNToOjs63/9O0puCgGS8aDOgpZY326fzFu15QAUjwaXzRZjf/qdsdBrckYdv9YxB8w== + dependencies: + "@typescript-eslint/scope-manager" "7.1.0" + "@typescript-eslint/types" "7.1.0" + "@typescript-eslint/typescript-estree" "7.1.0" + "@typescript-eslint/visitor-keys" "7.1.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.1.0.tgz#e4babaa39a3d612eff0e3559f3e99c720a2b4a54" + integrity sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A== + dependencies: + "@typescript-eslint/types" "7.1.0" + "@typescript-eslint/visitor-keys" "7.1.0" + +"@typescript-eslint/type-utils@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.1.0.tgz#372dfa470df181bcee0072db464dc778b75ed722" + integrity sha512-UZIhv8G+5b5skkcuhgvxYWHjk7FW7/JP5lPASMEUoliAPwIH/rxoUSQPia2cuOj9AmDZmwUl1usKm85t5VUMew== + dependencies: + "@typescript-eslint/typescript-estree" "7.1.0" + "@typescript-eslint/utils" "7.1.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/types@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.1.0.tgz#52a86d6236fda646e7e5fe61154991dc0dc433ef" + integrity sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA== + +"@typescript-eslint/typescript-estree@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.0.tgz#419b1310f061feee6df676c5bed460537310c593" + integrity sha512-k7MyrbD6E463CBbSpcOnwa8oXRdHzH1WiVzOipK3L5KSML92ZKgUBrTlehdi7PEIMT8k0bQixHUGXggPAlKnOQ== + dependencies: + "@typescript-eslint/types" "7.1.0" + "@typescript-eslint/visitor-keys" "7.1.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/utils@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.1.0.tgz#710ecda62aff4a3c8140edabf3c5292d31111ddd" + integrity sha512-WUFba6PZC5OCGEmbweGpnNJytJiLG7ZvDBJJoUcX4qZYf1mGZ97mO2Mps6O2efxJcJdRNpqweCistDbZMwIVHw== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "7.1.0" + "@typescript-eslint/types" "7.1.0" + "@typescript-eslint/typescript-estree" "7.1.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.0.tgz#576c4ad462ca1378135a55e2857d7aced96ce0a0" + integrity sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA== + dependencies: + "@typescript-eslint/types" "7.1.0" + eslint-visitor-keys "^3.4.1" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.9.0: + version "8.11.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" + integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== + +adm-zip@^0.4.13: + version "0.4.16" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" + integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== + +ajv@^6.12.3, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +asn1@~0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== + dependencies: + tweetnacl "^0.14.3" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browserslist@^4.22.2: + version "4.23.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== + dependencies: + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" + node-releases "^2.0.14" + update-browserslist-db "^1.0.13" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +caniuse-lite@^1.0.30001587: + version "1.0.30001591" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz#16745e50263edc9f395895a7cd468b9f3767cf33" + integrity sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + +chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +checksum@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/checksum/-/checksum-0.1.1.tgz#dc6527d4c90be8560dbd1ed4cecf3297d528e9e9" + integrity sha512-xWkkJpoWQ6CptWw2GvtoQbScL3xtvGjoqvHpALE7B0tSHxSw0ex0tlsKOKkbETaOYGBhMliAyscestDyAZIN9g== + dependencies: + optimist "~0.3.5" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + +debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +electron-to-chromium@^1.4.668: + version "1.4.683" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.683.tgz#b68167ed66dbea01feb86915aca92c09bc1b651a" + integrity sha512-FmopjiJjkUzqa5F5Sv+wxd8KimtCxyLFOFgRPwEeMLVmP+vHH/GjNGCuIYrCIchbMSiOe+nG/OPBbR/XoExBNA== + +escalade@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-prettier@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f" + integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw== + +eslint-plugin-prettier@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1" + integrity sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.8.6" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.57.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-glob@^3.2.9: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.17.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" + integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" + integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.3" + rimraf "^3.0.2" + +flatted@^3.2.9: + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + +form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^13.19.0: + version "13.24.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" + integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +ignore@^5.2.0, ignore@^5.2.4: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + +keyv@^4.5.3: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +node-releases@^2.0.14: + version "2.0.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" + integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optimist@~0.3.5: + version "0.3.7" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" + integrity sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ== + dependencies: + wordwrap "~0.0.2" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== + +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.0.1, safe-buffer@^5.1.2: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.2, semver@^7.5.4: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +sshpk@^1.7.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +synckit@^0.8.6: + version "0.8.8" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" + integrity sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ== + dependencies: + "@pkgr/core" "^0.1.0" + tslib "^2.6.2" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +ts-api-utils@^1.0.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" + integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA== + +tslib@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +update-browserslist-db@^1.0.13: + version "1.0.13" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" + integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 998eab95e69aaaef4104e9c84883e28f76d8a0c2 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 27 Feb 2024 22:31:20 +0300 Subject: [PATCH 03/97] Add progress to testing --- test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test.js b/test.js index 1a72e05..159e5b3 100644 --- a/test.js +++ b/test.js @@ -16,3 +16,4 @@ launcher.launch({ launcher.on('debug', (e) => console.log(e)); launcher.on('data', (e) => console.log(e)); +launcher.on('progress', (e) => console.log(e)); From db98c9046dc86370d6d5414f9992d265e9602f30 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 27 Feb 2024 22:33:54 +0300 Subject: [PATCH 04/97] components -> src --- index.js | 4 ++-- {components => src}/authenticator.js | 0 {components => src}/handler.js | 0 {components => src}/launcher.js | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename {components => src}/authenticator.js (100%) rename {components => src}/handler.js (100%) rename {components => src}/launcher.js (100%) diff --git a/index.js b/index.js index 5cc4c4f..f8916e9 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,4 @@ module.exports = { - Client: require('./components/launcher'), - Authenticator: require('./components/authenticator'), + Client: require('./src/launcher'), + Authenticator: require('./src/authenticator'), }; diff --git a/components/authenticator.js b/src/authenticator.js similarity index 100% rename from components/authenticator.js rename to src/authenticator.js diff --git a/components/handler.js b/src/handler.js similarity index 100% rename from components/handler.js rename to src/handler.js diff --git a/components/launcher.js b/src/launcher.js similarity index 100% rename from components/launcher.js rename to src/launcher.js From 16aa00baa9b49b95a9d4abc41de5b19a04f67233 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 27 Feb 2024 23:07:34 +0300 Subject: [PATCH 05/97] [AUTH] Rewrite request into axios --- package.json | 1 + src/authenticator.js | 193 +++++++++++++++---------------------------- yarn.lock | 30 ++++++- 3 files changed, 96 insertions(+), 128 deletions(-) diff --git a/package.json b/package.json index 82d6303..0cfb25b 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "index.js", "dependencies": { "adm-zip": "^0.4.13", + "axios": "^1.6.7", "checksum": "^0.1.1", "request": "^2.88.2", "uuid": "^8.3.2" diff --git a/src/authenticator.js b/src/authenticator.js index 8654740..e478b75 100644 --- a/src/authenticator.js +++ b/src/authenticator.js @@ -1,4 +1,4 @@ -const request = require('request'); +const axios = require('axios'); const { v3 } = require('uuid'); let uuid; @@ -6,22 +6,18 @@ let api_url = 'https://authserver.mojang.com'; module.exports.getAuth = function (username, password, client_token = null) { return new Promise((resolve, reject) => { - getUUID(username); - if (!password) { - const user = { + if (!uuid) uuid = v3(username, v3.DNS); + if (!password) + return resolve({ access_token: uuid, client_token: client_token || uuid, uuid, name: username, user_properties: '{}', - }; + }); - return resolve(user); - } - - const requestObject = { - url: api_url + '/authenticate', - json: { + axios + .post(api_url + '/authenticate', { agent: { name: 'Minecraft', version: 1, @@ -30,139 +26,82 @@ module.exports.getAuth = function (username, password, client_token = null) { password, clientToken: uuid, requestUser: true, - }, - }; - - request.post(requestObject, function (error, response, body) { - if (error) return reject(error); - if (!body || !body.selectedProfile) { - return reject(new Error('Validation error: ' + response.statusMessage)); - } - - const userProfile = { - access_token: body.accessToken, - client_token: body.clientToken, - uuid: body.selectedProfile.id, - name: body.selectedProfile.name, - selected_profile: body.selectedProfile, - user_properties: parsePropts(body.user.properties), - }; - - resolve(userProfile); - }); + }) + .then(({ body }) => { + if (!body || !body.selectedProfile) + return reject(new Error('Validation error: ' + response.statusMessage)); + + return resolve({ + access_token: body.accessToken, + client_token: body.clientToken, + uuid: body.selectedProfile.id, + name: body.selectedProfile.name, + selected_profile: body.selectedProfile, + user_properties: parsePropts(body.user.properties), + }); + }) + .catch((error) => reject(error)); }); }; module.exports.validate = function (accessToken, clientToken) { - return new Promise((resolve, reject) => { - const requestObject = { - url: api_url + '/validate', - json: { - accessToken, - clientToken, - }, - }; - - request.post(requestObject, async function (error, response, body) { - if (error) return reject(error); - - if (!body) resolve(true); - else reject(body); - }); - }); + return new Promise((resolve, reject) => + axios + .post(api_url + '/validate', { accessToken, clientToken }) + .then(({ data }) => (!data ? resolve(true) : reject(data))) + .catch((error) => reject(error)), + ); }; module.exports.refreshAuth = function (accessToken, clientToken) { - return new Promise((resolve, reject) => { - const requestObject = { - url: api_url + '/refresh', - json: { - accessToken, - clientToken, - requestUser: true, - }, - }; - - request.post(requestObject, function (error, response, body) { - if (error) return reject(error); - if (!body || !body.selectedProfile) { - return reject(new Error('Validation error: ' + response.statusMessage)); - } - - const userProfile = { - access_token: body.accessToken, - client_token: getUUID(body.selectedProfile.name), - uuid: body.selectedProfile.id, - name: body.selectedProfile.name, - user_properties: parsePropts(body.user.properties), - }; - - return resolve(userProfile); - }); - }); + return new Promise((resolve, reject) => + axios + .post(api_url + '/refresh', { accessToken, clientToken, requestUser: true }) + .then(({ body }) => { + if (!body || !body.selectedProfile) + return reject(new Error('Validation error: ' + response.statusMessage)); + + return resolve({ + access_token: body.accessToken, + client_token: getUUID(body.selectedProfile.name), + uuid: body.selectedProfile.id, + name: body.selectedProfile.name, + user_properties: parsePropts(body.user.properties), + }); + }) + .catch((error) => reject(error)), + ); }; module.exports.invalidate = function (accessToken, clientToken) { - return new Promise((resolve, reject) => { - const requestObject = { - url: api_url + '/invalidate', - json: { - accessToken, - clientToken, - }, - }; - - request.post(requestObject, function (error, response, body) { - if (error) return reject(error); - - if (!body) return resolve(true); - else return reject(body); - }); - }); + return new Promise((resolve, reject) => + axios + .post(api_url + '/invalidate', { accessToken, clientToken }) + .then(({ data }) => (!data ? resolve(true) : reject(data))) + .catch((error) => reject(error)), + ); }; module.exports.signOut = function (username, password) { - return new Promise((resolve, reject) => { - const requestObject = { - url: api_url + '/signout', - json: { - username, - password, - }, - }; - - request.post(requestObject, function (error, response, body) { - if (error) return reject(error); - - if (!body) return resolve(true); - else return reject(body); - }); - }); + return new Promise((resolve, reject) => + axios + .post(api_url + '/signout', { username, password }) + .then(({ data }) => (!data ? resolve(true) : reject(data))) + .catch((error) => reject(error)), + ); }; module.exports.changeApiUrl = function (url) { api_url = url; + return; }; -function parsePropts(array) { - if (array) { - const newObj = {}; - for (const entry of array) { - if (newObj[entry.name]) { - newObj[entry.name].push(entry.value); - } else { - newObj[entry.name] = [entry.value]; - } - } - return JSON.stringify(newObj); - } else { - return '{}'; - } -} +const parsePropts = (array) => { + if (!array) return '{}'; + + const newObj = {}; + for (const entry of array) + newObj[entry.name] ? newObj[entry.name].push(entry.value) : (newObj[entry.name] = [entry.value]); -function getUUID(value) { - if (!uuid) { - uuid = v3(value, v3.DNS); - } - return uuid; -} + return JSON.stringify(newObj); +}; diff --git a/yarn.lock b/yarn.lock index 73bd5f8..9558d48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -534,6 +534,15 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== +axios@^1.6.7: + version "1.6.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" + integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== + dependencies: + follow-redirects "^1.15.4" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -641,7 +650,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -930,6 +939,11 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== +follow-redirects@^1.15.4: + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== + forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -944,6 +958,15 @@ form-data@^2.5.0: combined-stream "^1.0.6" mime-types "^2.1.12" +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -1386,6 +1409,11 @@ prettier@^3.2.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" From 1a66368a97cf8df1e0c20eacd1fd324f3612cde5 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 27 Feb 2024 23:34:59 +0300 Subject: [PATCH 06/97] Finish rewriting request into axios --- package.json | 2 - src/handler.js | 162 +++++++++++--------------- src/launcher.js | 277 ++++++++++++++++++++++---------------------- test.js | 3 + yarn.lock | 301 +----------------------------------------------- 5 files changed, 209 insertions(+), 536 deletions(-) diff --git a/package.json b/package.json index 0cfb25b..4b1bf45 100644 --- a/package.json +++ b/package.json @@ -7,14 +7,12 @@ "adm-zip": "^0.4.13", "axios": "^1.6.7", "checksum": "^0.1.1", - "request": "^2.88.2", "uuid": "^8.3.2" }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.1.1", "@types/checksum": "^0.1.35", "@types/node": "^14.0.27", - "@types/request": "^2.48.12", "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", "eslint": "^8.57.0", diff --git a/src/handler.js b/src/handler.js index 92270f3..097df5b 100644 --- a/src/handler.js +++ b/src/handler.js @@ -1,18 +1,21 @@ const fs = require('fs'); const path = require('path'); -const request = require('request'); +const axios = require('axios'); const checksum = require('checksum'); const Zip = require('adm-zip'); const child = require('child_process'); +const http = require('http'); +const https = require('https'); let counter = 0; class Handler { constructor(client) { this.client = client; this.options = client.options; - this.baseRequest = request.defaults({ - pool: { maxSockets: this.options.overrides.maxSockets || 2 }, + this.baseRequest = axios.create({ timeout: this.options.timeout || 50000, + httpAgent: new http.Agent({ keepAlive: true, maxSockets: this.options.overrides.maxSockets || 2 }), + httpsAgent: new https.Agent({ keepAlive: true, maxSockets: this.options.overrides.maxSockets || 2 }), }); } @@ -37,35 +40,20 @@ class Handler { }); } - downloadAsync(url, directory, name, retry, type) { - return new Promise((resolve) => { + async downloadAsync(url, directory, name, retry, type) { + try { fs.mkdirSync(directory, { recursive: true }); - const _request = this.baseRequest(url); - - let receivedBytes = 0; - let totalBytes = 0; - - _request.on('response', (data) => { - if (data.statusCode === 404) { - this.client.emit('debug', `[MCLC]: Failed to download ${url} due to: File not found...`); - return resolve(false); - } - - totalBytes = parseInt(data.headers['content-length']); + const response = await this.baseRequest({ + url: url, + method: 'GET', + responseType: 'stream', }); - _request.on('error', async (error) => { - this.client.emit( - 'debug', - `[MCLC]: Failed to download asset to ${path.join(directory, name)} due to\n${error}.` + - ` Retrying... ${retry}`, - ); - if (retry) await this.downloadAsync(url, directory, name, false, type); - resolve(); - }); + const totalBytes = parseInt(response.headers['content-length']); + let receivedBytes = 0; - _request.on('data', (data) => { + response.data.on('data', (data) => { receivedBytes += data.length; this.client.emit('download-status', { name: name, @@ -76,27 +64,26 @@ class Handler { }); const file = fs.createWriteStream(path.join(directory, name)); - _request.pipe(file); + response.data.pipe(file); - file.once('finish', () => { - this.client.emit('download', name); - resolve({ - failed: false, - asset: null, - }); + await new Promise((resolve, reject) => { + file.on('finish', resolve); + file.on('error', reject); }); - file.on('error', async (e) => { - this.client.emit( - 'debug', - `[MCLC]: Failed to download asset to ${path.join(directory, name)} due to\n${e}.` + - ` Retrying... ${retry}`, - ); - if (fs.existsSync(path.join(directory, name))) fs.unlinkSync(path.join(directory, name)); - if (retry) await this.downloadAsync(url, directory, name, false, type); - resolve(); - }); - }); + this.client.emit('download', name); + return { + failed: false, + asset: null, + }; + } catch (error) { + this.client.emit( + 'debug', + `[MCLC]: Failed to download asset to ${path.join(directory, name)} due\n${error}. Retrying... ${retry}`, + ); + if (retry) await this.downloadAsync(url, directory, name, false, type); + return; + } } checkSum(hash, file) { @@ -111,59 +98,45 @@ class Handler { }); } - getVersion() { - return new Promise((resolve) => { + async getVersion() { + try { const versionJsonPath = this.options.overrides.versionJson || path.join(this.options.directory, `${this.options.version.number}.json`); if (fs.existsSync(versionJsonPath)) { this.version = JSON.parse(fs.readFileSync(versionJsonPath)); - return resolve(this.version); + return this.version; } const manifest = `${this.options.overrides.url.meta}/mc/game/version_manifest.json`; const cache = this.options.cache ? `${this.options.cache}/json` : `${this.options.root}/cache/json`; - request.get(manifest, (error, response, body) => { - if (error && error.code !== 'ENOTFOUND') return resolve(error); - if (!error) { - if (!fs.existsSync(cache)) { - fs.mkdirSync(cache, { recursive: true }); - this.client.emit('debug', '[MCLC]: Cache directory created.'); - } - fs.writeFile(path.join(`${cache}/version_manifest.json`), body, (err) => { - if (err) return resolve(err); - this.client.emit('debug', '[MCLC]: Cached version_manifest.json'); - }); - } - const parsed = - error && error.code === 'ENOTFOUND' - ? JSON.parse(fs.readFileSync(`${cache}/version_manifest.json`)) - : JSON.parse(body); - const desiredVersion = Object.values(parsed.versions).find( - (version) => version.id === this.options.version.number, - ); - if (desiredVersion) { - request.get(desiredVersion.url, (error, response, body) => { - if (error && error.code !== 'ENOTFOUND') throw Error(error); - if (!error) { - fs.writeFile(path.join(`${cache}/${this.options.version.number}.json`), body, (err) => { - if (err) throw Error(err); - this.client.emit('debug', `[MCLC]: Cached ${this.options.version.number}.json`); - }); - } + const { data } = await axios.get(manifest); - this.client.emit('debug', '[MCLC]: Parsed version from version manifest'); - this.version = - error && error.code === 'ENOTFOUND' - ? JSON.parse(fs.readFileSync(`${cache}/${this.options.version.number}.json`)) - : JSON.parse(body); - return resolve(this.version); - }); - } else { - throw Error(`Failed to find version ${this.options.version.number} in version_manifest.json`); - } - }); - }); + if (!fs.existsSync(cache)) { + fs.mkdirSync(cache, { recursive: true }); + this.client.emit('debug', '[MCLC]: Cache directory created.'); + } + + fs.writeFileSync(path.join(cache, 'version_manifest.json'), JSON.stringify(data)); + this.client.emit('debug', '[MCLC]: Cached version_manifest.json'); + + const desiredVersion = Object.values(data.versions).find( + (version) => version.id === this.options.version.number, + ); + if (desiredVersion) { + const { data } = await axios.get(desiredVersion.url); + fs.writeFileSync(path.join(`${cache}/${this.options.version.number}.json`), JSON.stringify(data)); + this.client.emit('debug', `[MCLC]: Cached ${this.options.version.number}.json`); + + this.client.emit('debug', '[MCLC]: Parsed version from version manifest'); + this.version = data; + return this.version; + } else { + throw Error(`Failed to find version ${this.options.version.number} in version_manifest.json`); + } + } catch (error) { + return error; + } } async getJar() { @@ -499,13 +472,12 @@ class Handler { const downloadLink = `${url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; // Checking if the file still exists on Forge's server, if not, replace it with the fallback. // Not checking for sucess, only if it 404s. - this.baseRequest(downloadLink, (error, response, body) => { - if (error) { - this.client.emit('debug', `[MCLC]: Failed checking request for ${downloadLink}`); - } else { - if (response.statusCode === 404) library.url = this.options.overrides.url.fallbackMaven; - } - }); + try { + const response = await axios.head(downloadLink); + if (response.status === 404) library.url = this.options.overrides.url.fallbackMaven; + } catch (error) { + this.client.emit('debug', `[MCLC]: Failed checking request for ${downloadLink}`); + } }), ); } diff --git a/src/launcher.js b/src/launcher.js index a0008c5..0b6fb12 100644 --- a/src/launcher.js +++ b/src/launcher.js @@ -6,155 +6,148 @@ const EventEmitter = require('events').EventEmitter; class MCLCore extends EventEmitter { async launch(options) { - try { - this.options = { ...options }; - this.options.root = path.resolve(this.options.root); - this.options.overrides = { - detached: true, - ...this.options.overrides, - url: { - meta: 'https://launchermeta.mojang.com', - resource: 'https://resources.download.minecraft.net', - mavenForge: 'https://files.minecraftforge.net/maven/', - defaultRepoForge: 'https://libraries.minecraft.net/', - fallbackMaven: 'https://search.maven.org/remotecontent?filepath=', - ...(this.options.overrides ? this.options.overrides.url : undefined), - }, - fw: { - baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', - version: '1.5.7', - sh1: '155ac9f4e5f65288eaacae19025ac4d9da1f0ef2', - size: 34910, - ...(this.options.overrides ? this.options.overrides.fw : undefined), - }, - }; - - this.handler = new Handler(this); - - this.printVersion(); - - const java = await this.handler.checkJava(this.options.javaPath || 'java'); - if (!java.run) { - this.emit('debug', `[MCLC]: Couldn't start Minecraft due to: ${java.message}`); - this.emit('close', 1); - return null; - } + this.options = { ...options }; + this.options.root = path.resolve(this.options.root); + this.options.overrides = { + detached: true, + ...this.options.overrides, + url: { + meta: 'https://launchermeta.mojang.com', + resource: 'https://resources.download.minecraft.net', + mavenForge: 'https://files.minecraftforge.net/maven/', + defaultRepoForge: 'https://libraries.minecraft.net/', + fallbackMaven: 'https://search.maven.org/remotecontent?filepath=', + ...(this.options.overrides ? this.options.overrides.url : undefined), + }, + fw: { + baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', + version: '1.5.7', + sh1: '155ac9f4e5f65288eaacae19025ac4d9da1f0ef2', + size: 34910, + ...(this.options.overrides ? this.options.overrides.fw : undefined), + }, + }; + + this.handler = new Handler(this); + + this.printVersion(); + + const java = await this.handler.checkJava(this.options.javaPath || 'java'); + if (!java.run) { + this.emit('debug', `[MCLC]: Couldn't start Minecraft due to: ${java.message}`); + this.emit('close', 1); + return null; + } - this.createRootDirectory(); - this.createGameDirectory(); + this.createRootDirectory(); + this.createGameDirectory(); - await this.extractPackage(); + await this.extractPackage(); - const directory = - this.options.overrides.directory || - path.join( - this.options.root, - 'versions', - this.options.version.custom ? this.options.version.custom : this.options.version.number, - ); - this.options.directory = directory; - - const versionFile = await this.handler.getVersion(); - const mcPath = - this.options.overrides.minecraftJar || - (this.options.version.custom - ? path.join( - this.options.root, - 'versions', - this.options.version.custom, - `${this.options.version.custom}.jar`, - ) - : path.join(directory, `${this.options.version.number}.jar`)); - this.options.mcPath = mcPath; - const nativePath = await this.handler.getNatives(); - - if (!fs.existsSync(mcPath)) { - this.emit('debug', '[MCLC]: Attempting to download Minecraft version jar'); - await this.handler.getJar(); - } + const directory = + this.options.overrides.directory || + path.join( + this.options.root, + 'versions', + this.options.version.custom ? this.options.version.custom : this.options.version.number, + ); + this.options.directory = directory; + + const versionFile = await this.handler.getVersion(); + const mcPath = + this.options.overrides.minecraftJar || + (this.options.version.custom + ? path.join( + this.options.root, + 'versions', + this.options.version.custom, + `${this.options.version.custom}.jar`, + ) + : path.join(directory, `${this.options.version.number}.jar`)); + this.options.mcPath = mcPath; + const nativePath = await this.handler.getNatives(); + + if (!fs.existsSync(mcPath)) { + this.emit('debug', '[MCLC]: Attempting to download Minecraft version jar'); + await this.handler.getJar(); + } - const modifyJson = await this.getModifyJson(); - - const args = []; - - let jvm = [ - '-XX:-UseAdaptiveSizePolicy', - '-XX:-OmitStackTraceInFastThrow', - '-Dfml.ignorePatchDiscrepancies=true', - '-Dfml.ignoreInvalidMinecraftCertificates=true', - `-Djava.library.path=${nativePath}`, - `-Xmx${this.handler.getMemory()[0]}`, - `-Xms${this.handler.getMemory()[1]}`, - ]; - if (this.handler.getOS() === 'osx') { - if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()); - } else jvm.push(await this.handler.getJVM()); - - if (this.options.customArgs) jvm = jvm.concat(this.options.customArgs); - if (this.options.overrides.logj4ConfigurationFile) { - jvm.push(`-Dlog4j.configurationFile=${path.resolve(this.options.overrides.logj4ConfigurationFile)}`); - } - // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition - if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) - jvm.push('-Dlog4j2.formatMsgNoLookups=true'); - if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); - if (parseInt(versionFile.id.split('.')[1]) < 17) { - if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { - const configPath = path.resolve(this.options.overrides.cwd || this.options.root); - const intVersion = parseInt(versionFile.id.split('.')[1]); - if (intVersion >= 12) { - await this.handler.downloadAsync( - 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', - configPath, - 'log4j2_112-116.xml', - true, - 'log4j', - ); - jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml'); - } else if (intVersion >= 7) { - await this.handler.downloadAsync( - 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', - configPath, - 'log4j2_17-111.xml', - true, - 'log4j', - ); - jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml'); - } + const modifyJson = await this.getModifyJson(); + + const args = []; + + let jvm = [ + '-XX:-UseAdaptiveSizePolicy', + '-XX:-OmitStackTraceInFastThrow', + '-Dfml.ignorePatchDiscrepancies=true', + '-Dfml.ignoreInvalidMinecraftCertificates=true', + `-Djava.library.path=${nativePath}`, + `-Xmx${this.handler.getMemory()[0]}`, + `-Xms${this.handler.getMemory()[1]}`, + ]; + if (this.handler.getOS() === 'osx') { + if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()); + } else jvm.push(await this.handler.getJVM()); + + if (this.options.customArgs) jvm = jvm.concat(this.options.customArgs); + if (this.options.overrides.logj4ConfigurationFile) { + jvm.push(`-Dlog4j.configurationFile=${path.resolve(this.options.overrides.logj4ConfigurationFile)}`); + } + // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition + if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) + jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) < 17) { + if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { + const configPath = path.resolve(this.options.overrides.cwd || this.options.root); + const intVersion = parseInt(versionFile.id.split('.')[1]); + if (intVersion >= 12) { + await this.handler.downloadAsync( + 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', + configPath, + 'log4j2_112-116.xml', + true, + 'log4j', + ); + jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml'); + } else if (intVersion >= 7) { + await this.handler.downloadAsync( + 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', + configPath, + 'log4j2_17-111.xml', + true, + 'log4j', + ); + jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml'); } } - - const classes = - this.options.overrides.classes || this.handler.cleanUp(await this.handler.getClasses(modifyJson)); - const classPaths = ['-cp']; - const separator = this.handler.getOS() === 'windows' ? ';' : ':'; - this.emit('debug', `[MCLC]: Using ${separator} to separate class paths`); - // Handling launch arguments. - const file = modifyJson || versionFile; - // So mods like fabric work. - const jar = fs.existsSync(mcPath) - ? `${separator}${mcPath}` - : `${separator}${path.join(directory, `${this.options.version.number}.jar`)}`; - classPaths.push( - `${this.options.forge ? this.options.forge + separator : ''}${classes.join(separator)}${jar}`, - ); - classPaths.push(file.mainClass); - - this.emit('debug', '[MCLC]: Attempting to download assets'); - await this.handler.getAssets(); - - // Forge -> Custom -> Vanilla - const launchOptions = await this.handler.getLaunchOptions(modifyJson); - - const launchArguments = args.concat(jvm, classPaths, launchOptions); - this.emit('arguments', launchArguments); - this.emit('debug', `[MCLC]: Launching with arguments ${launchArguments.join(' ')}`); - - return this.startMinecraft(launchArguments); - } catch (e) { - this.emit('debug', `[MCLC]: Failed to start due to ${e}, closing...`); - return null; } + + const classes = + this.options.overrides.classes || this.handler.cleanUp(await this.handler.getClasses(modifyJson)); + const classPaths = ['-cp']; + const separator = this.handler.getOS() === 'windows' ? ';' : ':'; + this.emit('debug', `[MCLC]: Using ${separator} to separate class paths`); + // Handling launch arguments. + const file = modifyJson || versionFile; + // So mods like fabric work. + const jar = fs.existsSync(mcPath) + ? `${separator}${mcPath}` + : `${separator}${path.join(directory, `${this.options.version.number}.jar`)}`; + classPaths.push(`${this.options.forge ? this.options.forge + separator : ''}${classes.join(separator)}${jar}`); + classPaths.push(file.mainClass); + + this.emit('debug', '[MCLC]: Attempting to download assets'); + await this.handler.getAssets(); + + // Forge -> Custom -> Vanilla + const launchOptions = await this.handler.getLaunchOptions(modifyJson); + + const launchArguments = args.concat(jvm, classPaths, launchOptions); + this.emit('arguments', launchArguments); + this.emit('debug', `[MCLC]: Launching with arguments ${launchArguments.join(' ')}`); + + return this.startMinecraft(launchArguments); } printVersion() { diff --git a/test.js b/test.js index 159e5b3..e2a93ad 100644 --- a/test.js +++ b/test.js @@ -12,6 +12,9 @@ launcher.launch({ max: '4G', min: '2G', }, + overrides: { + maxSockets: 32, + }, }); launcher.on('debug', (e) => console.log(e)); diff --git a/yarn.lock b/yarn.lock index 9558d48..7edec57 100644 --- a/yarn.lock +++ b/yarn.lock @@ -315,11 +315,6 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@types/caseless@*": - version "0.12.5" - resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.5.tgz#db9468cb1b1b5a925b8f34822f1669df0c5472f5" - integrity sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg== - "@types/checksum@^0.1.35": version "0.1.35" resolved "https://registry.yarnpkg.com/@types/checksum/-/checksum-0.1.35.tgz#f1f9a4afd536101981a767f7a2b06618935dad67" @@ -330,38 +325,16 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== -"@types/node@*": - version "20.11.20" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.20.tgz#f0a2aee575215149a62784210ad88b3a34843659" - integrity sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg== - dependencies: - undici-types "~5.26.4" - "@types/node@^14.0.27": version "14.18.63" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b" integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ== -"@types/request@^2.48.12": - version "2.48.12" - resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.12.tgz#0f590f615a10f87da18e9790ac94c29ec4c5ef30" - integrity sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw== - dependencies: - "@types/caseless" "*" - "@types/node" "*" - "@types/tough-cookie" "*" - form-data "^2.5.0" - "@types/semver@^7.5.0": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== -"@types/tough-cookie@*": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" - integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== - "@typescript-eslint/eslint-plugin@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz#22bb999a8d59893c0ea07923e8a21f9d985ad740" @@ -468,7 +441,7 @@ adm-zip@^0.4.13: resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== -ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -507,33 +480,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== - -aws4@^1.8.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" - integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== - axios@^1.6.7: version "1.6.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" @@ -548,13 +499,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== - dependencies: - tweetnacl "^0.14.3" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -597,11 +541,6 @@ caniuse-lite@^1.0.30001587: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz#16745e50263edc9f395895a7cd468b9f3767cf33" integrity sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ== -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== - chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -650,7 +589,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: +combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -667,11 +606,6 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== - cross-spawn@^7.0.2: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -681,13 +615,6 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== - dependencies: - assert-plus "^1.0.0" - debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -719,14 +646,6 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - electron-to-chromium@^1.4.668: version "1.4.683" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.683.tgz#b68167ed66dbea01feb86915aca92c09bc1b651a" @@ -850,21 +769,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -944,20 +848,6 @@ follow-redirects@^1.15.4: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== - -form-data@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" - integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -967,15 +857,6 @@ form-data@^4.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -986,13 +867,6 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== - dependencies: - assert-plus "^1.0.0" - glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -1048,19 +922,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1071,15 +932,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -1133,21 +985,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -1160,11 +1002,6 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -1180,36 +1017,16 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== - json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -1269,7 +1086,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@~2.1.19: +mime-types@^2.1.12: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -1305,11 +1122,6 @@ node-releases@^2.0.14: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1377,11 +1189,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -1414,52 +1221,16 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -psl@^1.1.28: - version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== - -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -request@^2.88.2: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -1484,16 +1255,6 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1, safe-buffer@^5.1.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -1523,21 +1284,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -sshpk@^1.7.0: - version "1.18.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" - integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -1589,14 +1335,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - ts-api-utils@^1.0.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" @@ -1607,18 +1345,6 @@ tslib@^2.6.2: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -1631,11 +1357,6 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== - update-browserslist-db@^1.0.13: version "1.0.13" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" @@ -1651,25 +1372,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -uuid@^3.3.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" From f30266a5666fb88af41e83aedf11cacc012c92f6 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 28 Feb 2024 16:09:42 +0300 Subject: [PATCH 07/97] Remove the need for checksum package --- src/handler.js | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/handler.js b/src/handler.js index 097df5b..1b8c5bd 100644 --- a/src/handler.js +++ b/src/handler.js @@ -1,11 +1,11 @@ const fs = require('fs'); const path = require('path'); const axios = require('axios'); -const checksum = require('checksum'); const Zip = require('adm-zip'); const child = require('child_process'); const http = require('http'); const https = require('https'); +const crypto = require('crypto'); let counter = 0; class Handler { @@ -88,11 +88,12 @@ class Handler { checkSum(hash, file) { return new Promise((resolve, reject) => { - checksum.file(file, (err, sum) => { + this.checksumFile(file, (err, sum) => { if (err) { this.client.emit('debug', `[MCLC]: Failed to check file hash due to ${err}`); - return resolve(false); + return reject(); } + return resolve(hash === sum); }); }); @@ -797,6 +798,38 @@ class Handler { return this.client.emit('package-extract', true); } + + checksumFile(filename, callback) { + let options = {}; + if (!options.algorithm) options.algorithm = 'sha1'; + if (!options.encoding) options.encoding = 'hex'; + + fs.stat(filename, function (err, stat) { + if (!err && !stat.isFile()) err = new Error('Not a file'); + if (err) return callback(err); + + const hash = crypto.createHash(options.algorithm); + const fileStream = fs.createReadStream(filename); + + if (!hash.write) { + fileStream.on('data', function (data) { + hash.update(data); + }); + + fileStream.on('end', function () { + callback(null, hash.digest(options.encoding)); + }); + } else { + hash.setEncoding(options.encoding); + fileStream.pipe(hash, { end: false }); + + fileStream.on('end', function () { + hash.end(); + callback(null, hash.read()); + }); + } + }); + } } module.exports = Handler; From 1fa2d38ef14dd941edbc3d94e158b23c61375a68 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 28 Feb 2024 16:12:29 +0300 Subject: [PATCH 08/97] Fully remove checksum --- package.json | 2 -- src/handler.js | 10 +++------- yarn.lock | 24 ------------------------ 3 files changed, 3 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index 4b1bf45..0e4cc66 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,10 @@ "dependencies": { "adm-zip": "^0.4.13", "axios": "^1.6.7", - "checksum": "^0.1.1", "uuid": "^8.3.2" }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.1.1", - "@types/checksum": "^0.1.35", "@types/node": "^14.0.27", "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", diff --git a/src/handler.js b/src/handler.js index 1b8c5bd..2cc3709 100644 --- a/src/handler.js +++ b/src/handler.js @@ -800,15 +800,11 @@ class Handler { } checksumFile(filename, callback) { - let options = {}; - if (!options.algorithm) options.algorithm = 'sha1'; - if (!options.encoding) options.encoding = 'hex'; - fs.stat(filename, function (err, stat) { if (!err && !stat.isFile()) err = new Error('Not a file'); if (err) return callback(err); - const hash = crypto.createHash(options.algorithm); + const hash = crypto.createHash('sha1'); const fileStream = fs.createReadStream(filename); if (!hash.write) { @@ -817,10 +813,10 @@ class Handler { }); fileStream.on('end', function () { - callback(null, hash.digest(options.encoding)); + callback(null, hash.digest('hex')); }); } else { - hash.setEncoding(options.encoding); + hash.setEncoding('hex'); fileStream.pipe(hash, { end: false }); fileStream.on('end', function () { diff --git a/yarn.lock b/yarn.lock index 7edec57..b710218 100644 --- a/yarn.lock +++ b/yarn.lock @@ -315,11 +315,6 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== -"@types/checksum@^0.1.35": - version "0.1.35" - resolved "https://registry.yarnpkg.com/@types/checksum/-/checksum-0.1.35.tgz#f1f9a4afd536101981a767f7a2b06618935dad67" - integrity sha512-Tm3eaZOW4viqdSPa1Y3HFJBqzmTqgChTfeFqBV8Xyevvf3IIG5Uo8WOHFRLhdUTADnz5waK7KC11V+tBfXnqkw== - "@types/json-schema@^7.0.12": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" @@ -558,13 +553,6 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -checksum@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/checksum/-/checksum-0.1.1.tgz#dc6527d4c90be8560dbd1ed4cecf3297d528e9e9" - integrity sha512-xWkkJpoWQ6CptWw2GvtoQbScL3xtvGjoqvHpALE7B0tSHxSw0ex0tlsKOKkbETaOYGBhMliAyscestDyAZIN9g== - dependencies: - optimist "~0.3.5" - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -1129,13 +1117,6 @@ once@^1.3.0: dependencies: wrappy "1" -optimist@~0.3.5: - version "0.3.7" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.3.7.tgz#c90941ad59e4273328923074d2cf2e7cbc6ec0d9" - integrity sha512-TCx0dXQzVtSCg2OgY/bO9hjM9cV4XYx09TVK+s3+FhkjT6LovsLe+pPMzpWf+6yXK/hUizs2gUoTw3jHM0VaTQ== - dependencies: - wordwrap "~0.0.2" - optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -1384,11 +1365,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw== - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From d6652d33b5244a91e655bd4361d48ba79663fc85 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 28 Feb 2024 16:59:24 +0300 Subject: [PATCH 09/97] Support ESM (WIP, need to convert into TS to support both) --- index.d.ts | 1 - index.js | 4 - package.json | 5 +- .../authenticator.cjs} | 0 src/{handler.js => cjs/handler.cjs} | 13 +- src/{launcher.js => cjs/launcher.cjs} | 24 +- src/esm/authenticator.mjs | 107 +++ src/esm/handler.mjs | 838 ++++++++++++++++++ src/esm/launcher.mjs | 215 +++++ src/index.cjs | 4 + src/index.mjs | 2 + test.cjs | 22 + test.js => test.mjs | 3 +- 13 files changed, 1210 insertions(+), 28 deletions(-) delete mode 100644 index.js rename src/{authenticator.js => cjs/authenticator.cjs} (100%) rename src/{handler.js => cjs/handler.cjs} (99%) rename src/{launcher.js => cjs/launcher.cjs} (94%) create mode 100644 src/esm/authenticator.mjs create mode 100644 src/esm/handler.mjs create mode 100644 src/esm/launcher.mjs create mode 100644 src/index.cjs create mode 100644 src/index.mjs create mode 100644 test.cjs rename test.js => test.mjs (88%) diff --git a/index.d.ts b/index.d.ts index a5080e3..3f7e665 100644 --- a/index.d.ts +++ b/index.d.ts @@ -280,7 +280,6 @@ declare module 'minecraft-launcher-core' { export class Client extends EventEmitter { launch(options: ILauncherOptions): Promise; - protected printVersion(): void; protected createRootDirectory(): void; protected createGameDirectory(): void; protected extractPackage(): Promise; diff --git a/index.js b/index.js deleted file mode 100644 index f8916e9..0000000 --- a/index.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - Client: require('./src/launcher'), - Authenticator: require('./src/authenticator'), -}; diff --git a/package.json b/package.json index 0e4cc66..ec6b8fb 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "minecraft-launcher-core", "version": "3.18.0", "description": "Lightweight module that downloads and runs Minecraft using javascript / NodeJS", - "main": "index.js", + "main": "src/esm.js", + "type": "module", "dependencies": { "adm-zip": "^0.4.13", "axios": "^1.6.7", @@ -38,4 +39,4 @@ "url": "https://github.com/Pierce01/MinecraftLauncher-core/issues" }, "homepage": "https://github.com/Pierce01/MinecraftLauncher-core#readme" -} +} \ No newline at end of file diff --git a/src/authenticator.js b/src/cjs/authenticator.cjs similarity index 100% rename from src/authenticator.js rename to src/cjs/authenticator.cjs diff --git a/src/handler.js b/src/cjs/handler.cjs similarity index 99% rename from src/handler.js rename to src/cjs/handler.cjs index 2cc3709..36f5639 100644 --- a/src/handler.js +++ b/src/cjs/handler.cjs @@ -1,11 +1,12 @@ -const fs = require('fs'); -const path = require('path'); +const fs = require('node:fs'); +const path = require('node:path'); +const child = require('node:child_process'); +const http = require('node:http'); +const https = require('node:https'); +const crypto = require('node:crypto'); const axios = require('axios'); const Zip = require('adm-zip'); -const child = require('child_process'); -const http = require('http'); -const https = require('https'); -const crypto = require('crypto'); + let counter = 0; class Handler { diff --git a/src/launcher.js b/src/cjs/launcher.cjs similarity index 94% rename from src/launcher.js rename to src/cjs/launcher.cjs index 0b6fb12..c4c3338 100644 --- a/src/launcher.js +++ b/src/cjs/launcher.cjs @@ -1,8 +1,8 @@ -const child = require('child_process'); -const path = require('path'); +const child = require('node:child_process'); +const path = require('node:path'); +const fs = require('node:fs'); +const EventEmitter = require('node:events').EventEmitter; const Handler = require('./handler'); -const fs = require('fs'); -const EventEmitter = require('events').EventEmitter; class MCLCore extends EventEmitter { async launch(options) { @@ -30,7 +30,7 @@ class MCLCore extends EventEmitter { this.handler = new Handler(this); - this.printVersion(); + this.emit('debug', `[MCLC]: MCLC version ${this.version()}`); const java = await this.handler.checkJava(this.options.javaPath || 'java'); if (!java.run) { @@ -150,15 +150,6 @@ class MCLCore extends EventEmitter { return this.startMinecraft(launchArguments); } - printVersion() { - if (fs.existsSync(path.join(__dirname, '..', 'package.json'))) { - const { version } = require('../package.json'); - this.emit('debug', `[MCLC]: MCLC version ${version}`); - } else { - this.emit('debug', '[MCLC]: Package JSON not found, skipping MCLC version check.'); - } - } - createRootDirectory() { if (!fs.existsSync(this.options.root)) { this.emit('debug', '[MCLC]: Attempting to create root folder'); @@ -219,6 +210,11 @@ class MCLCore extends EventEmitter { minecraft.on('close', (code) => this.emit('close', code)); return minecraft; } + + version() { + // Should be changed each update + return '3.18.0'; + } } module.exports = MCLCore; diff --git a/src/esm/authenticator.mjs b/src/esm/authenticator.mjs new file mode 100644 index 0000000..6e70ab2 --- /dev/null +++ b/src/esm/authenticator.mjs @@ -0,0 +1,107 @@ +import axios from 'axios'; +import { v3 } from 'uuid'; + +let uuid; +let api_url = 'https://authserver.mojang.com'; + +export function getAuth(username, password, client_token = null) { + return new Promise((resolve, reject) => { + if (!uuid) uuid = v3(username, v3.DNS); + if (!password) + return resolve({ + access_token: uuid, + client_token: client_token || uuid, + uuid, + name: username, + user_properties: '{}', + }); + + axios + .post(api_url + '/authenticate', { + agent: { + name: 'Minecraft', + version: 1, + }, + username, + password, + clientToken: uuid, + requestUser: true, + }) + .then(({ body }) => { + if (!body || !body.selectedProfile) + return reject(new Error('Validation error: ' + response.statusMessage)); + + return resolve({ + access_token: body.accessToken, + client_token: body.clientToken, + uuid: body.selectedProfile.id, + name: body.selectedProfile.name, + selected_profile: body.selectedProfile, + user_properties: parsePropts(body.user.properties), + }); + }) + .catch((error) => reject(error)); + }); +} + +export function validate(accessToken, clientToken) { + return new Promise((resolve, reject) => + axios + .post(api_url + '/validate', { accessToken, clientToken }) + .then(({ data }) => (!data ? resolve(true) : reject(data))) + .catch((error) => reject(error)), + ); +} + +export function refreshAuth(accessToken, clientToken) { + return new Promise((resolve, reject) => + axios + .post(api_url + '/refresh', { accessToken, clientToken, requestUser: true }) + .then(({ body }) => { + if (!body || !body.selectedProfile) + return reject(new Error('Validation error: ' + response.statusMessage)); + + return resolve({ + access_token: body.accessToken, + client_token: getUUID(body.selectedProfile.name), + uuid: body.selectedProfile.id, + name: body.selectedProfile.name, + user_properties: parsePropts(body.user.properties), + }); + }) + .catch((error) => reject(error)), + ); +} + +export function invalidate(accessToken, clientToken) { + return new Promise((resolve, reject) => + axios + .post(api_url + '/invalidate', { accessToken, clientToken }) + .then(({ data }) => (!data ? resolve(true) : reject(data))) + .catch((error) => reject(error)), + ); +} + +export function signOut(username, password) { + return new Promise((resolve, reject) => + axios + .post(api_url + '/signout', { username, password }) + .then(({ data }) => (!data ? resolve(true) : reject(data))) + .catch((error) => reject(error)), + ); +} + +export function changeApiUrl(url) { + api_url = url; + return; +} + +const parsePropts = (array) => { + if (!array) return '{}'; + + const newObj = {}; + for (const entry of array) + newObj[entry.name] ? newObj[entry.name].push(entry.value) : (newObj[entry.name] = [entry.value]); + + return JSON.stringify(newObj); +}; diff --git a/src/esm/handler.mjs b/src/esm/handler.mjs new file mode 100644 index 0000000..c78fa3b --- /dev/null +++ b/src/esm/handler.mjs @@ -0,0 +1,838 @@ +import { + stat as _stat, + copyFileSync, + createReadStream, + createWriteStream, + existsSync, + mkdirSync, + readdirSync, + readFileSync, + unlinkSync, + writeFileSync, +} from 'fs'; +import { exec } from 'node:child_process'; +import { createHash } from 'node:crypto'; +import { Agent } from 'node:http'; +import { Agent as _Agent } from 'node:https'; +import { resolve as _resolve, join, sep } from 'node:path'; +import Zip from 'adm-zip'; +import axios from 'axios'; + +let counter = 0; + +class Handler { + constructor(client) { + this.client = client; + this.options = client.options; + this.baseRequest = axios.create({ + timeout: this.options.timeout || 50000, + httpAgent: new Agent({ keepAlive: true, maxSockets: this.options.overrides.maxSockets || 2 }), + httpsAgent: new _Agent({ keepAlive: true, maxSockets: this.options.overrides.maxSockets || 2 }), + }); + } + + checkJava(java) { + return new Promise((resolve) => { + exec(`"${java}" -version`, (error, stdout, stderr) => { + if (error) { + resolve({ + run: false, + message: error, + }); + } else { + this.client.emit( + 'debug', + `[MCLC]: Using Java version ${stderr.match(/"(.*?)"/).pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`, + ); + resolve({ + run: true, + }); + } + }); + }); + } + + async downloadAsync(url, directory, name, retry, type) { + try { + mkdirSync(directory, { recursive: true }); + + const response = await this.baseRequest({ + url: url, + method: 'GET', + responseType: 'stream', + }); + + const totalBytes = parseInt(response.headers['content-length']); + let receivedBytes = 0; + + response.data.on('data', (data) => { + receivedBytes += data.length; + this.client.emit('download-status', { + name: name, + type: type, + current: receivedBytes, + total: totalBytes, + }); + }); + + const file = createWriteStream(join(directory, name)); + response.data.pipe(file); + + await new Promise((resolve, reject) => { + file.on('finish', resolve); + file.on('error', reject); + }); + + this.client.emit('download', name); + return { + failed: false, + asset: null, + }; + } catch (error) { + this.client.emit( + 'debug', + `[MCLC]: Failed to download asset to ${join(directory, name)} due\n${error}. Retrying... ${retry}`, + ); + if (retry) await this.downloadAsync(url, directory, name, false, type); + return; + } + } + + checkSum(hash, file) { + return new Promise((resolve, reject) => { + this.checksumFile(file, (err, sum) => { + if (err) { + this.client.emit('debug', `[MCLC]: Failed to check file hash due to ${err}`); + return reject(); + } + + return resolve(hash === sum); + }); + }); + } + + async getVersion() { + try { + const versionJsonPath = + this.options.overrides.versionJson || + join(this.options.directory, `${this.options.version.number}.json`); + if (existsSync(versionJsonPath)) { + this.version = JSON.parse(readFileSync(versionJsonPath)); + return this.version; + } + + const manifest = `${this.options.overrides.url.meta}/mc/game/version_manifest.json`; + const cache = this.options.cache ? `${this.options.cache}/json` : `${this.options.root}/cache/json`; + const { data } = await axios.get(manifest); + + if (!existsSync(cache)) { + mkdirSync(cache, { recursive: true }); + this.client.emit('debug', '[MCLC]: Cache directory created.'); + } + + writeFileSync(join(cache, 'version_manifest.json'), JSON.stringify(data)); + this.client.emit('debug', '[MCLC]: Cached version_manifest.json'); + + const desiredVersion = Object.values(data.versions).find( + (version) => version.id === this.options.version.number, + ); + if (desiredVersion) { + const { data } = await axios.get(desiredVersion.url); + writeFileSync(join(`${cache}/${this.options.version.number}.json`), JSON.stringify(data)); + this.client.emit('debug', `[MCLC]: Cached ${this.options.version.number}.json`); + + this.client.emit('debug', '[MCLC]: Parsed version from version manifest'); + this.version = data; + return this.version; + } else { + throw Error(`Failed to find version ${this.options.version.number} in version_manifest.json`); + } + } catch (error) { + return error; + } + } + + async getJar() { + await this.downloadAsync( + this.version.downloads.client.url, + this.options.directory, + `${this.options.version.custom ? this.options.version.custom : this.options.version.number}.jar`, + true, + 'version-jar', + ); + writeFileSync( + join(this.options.directory, `${this.options.version.number}.json`), + JSON.stringify(this.version, null, 4), + ); + return this.client.emit('debug', '[MCLC]: Downloaded version jar and wrote version json'); + } + + async getAssets() { + const assetDirectory = _resolve(this.options.overrides.assetRoot || join(this.options.root, 'assets')); + const assetId = this.options.version.custom || this.options.version.number; + if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) { + await this.downloadAsync( + this.version.assetIndex.url, + join(assetDirectory, 'indexes'), + `${assetId}.json`, + true, + 'asset-json', + ); + } + + const index = JSON.parse( + readFileSync(join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' }), + ); + + this.client.emit('progress', { + type: 'assets', + task: 0, + total: Object.keys(index.objects).length, + }); + + await Promise.all( + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = join(assetDirectory, 'objects', subhash); + + if (!existsSync(join(subAsset, hash)) || !(await this.checkSum(hash, join(subAsset, hash)))) { + await this.downloadAsync( + `${this.options.overrides.url.resource}/${subhash}/${hash}`, + subAsset, + hash, + true, + 'assets', + ); + } + counter++; + this.client.emit('progress', { + type: 'assets', + task: counter, + total: Object.keys(index.objects).length, + }); + }), + ); + counter = 0; + + // Copy assets to legacy if it's an older Minecraft version. + if (this.isLegacy()) { + if (existsSync(join(assetDirectory, 'legacy'))) { + this.client.emit( + 'debug', + "[MCLC]: The 'legacy' directory is no longer used as Minecraft looks " + + "for the resouces folder regardless of what is passed in the assetDirecotry launch option. I'd " + + `recommend removing the directory (${join(assetDirectory, 'legacy')})`, + ); + } + + const legacyDirectory = join(this.options.root, 'resources'); + this.client.emit('debug', `[MCLC]: Copying assets over to ${legacyDirectory}`); + + this.client.emit('progress', { + type: 'assets-copy', + task: 0, + total: Object.keys(index.objects).length, + }); + + await Promise.all( + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = join(assetDirectory, 'objects', subhash); + + const legacyAsset = asset.split('/'); + legacyAsset.pop(); + + if (!existsSync(join(legacyDirectory, legacyAsset.join('/')))) { + mkdirSync(join(legacyDirectory, legacyAsset.join('/')), { recursive: true }); + } + + if (!existsSync(join(legacyDirectory, asset))) { + copyFileSync(join(subAsset, hash), join(legacyDirectory, asset)); + } + counter++; + this.client.emit('progress', { + type: 'assets-copy', + task: counter, + total: Object.keys(index.objects).length, + }); + }), + ); + } + counter = 0; + + this.client.emit('debug', '[MCLC]: Downloaded assets'); + } + + parseRule(lib) { + if (lib.rules) { + if (lib.rules.length > 1) { + if ( + lib.rules[0].action === 'allow' && + lib.rules[1].action === 'disallow' && + lib.rules[1].os.name === 'osx' + ) { + return this.getOS() === 'osx'; + } + return true; + } else { + if (lib.rules[0].action === 'allow' && lib.rules[0].os) return lib.rules[0].os.name !== this.getOS(); + } + } else { + return false; + } + } + + async getNatives() { + const nativeDirectory = _resolve( + this.options.overrides.natives || join(this.options.root, 'natives', this.version.id), + ); + + if (parseInt(this.version.id.split('.')[1]) >= 19) return this.options.overrides.cwd || this.options.root; + + if (!existsSync(nativeDirectory) || !readdirSync(nativeDirectory).length) { + mkdirSync(nativeDirectory, { recursive: true }); + + const natives = async () => { + const natives = []; + await Promise.all( + this.version.libraries.map(async (lib) => { + if (!lib.downloads || !lib.downloads.classifiers) return; + if (this.parseRule(lib)) return; + + const native = + this.getOS() === 'osx' + ? lib.downloads.classifiers['natives-osx'] || lib.downloads.classifiers['natives-macos'] + : lib.downloads.classifiers[`natives-${this.getOS()}`]; + + natives.push(native); + }), + ); + return natives; + }; + const stat = await natives(); + + this.client.emit('progress', { + type: 'natives', + task: 0, + total: stat.length, + }); + + await Promise.all( + stat.map(async (native) => { + if (!native) return; + const name = native.path.split('/').pop(); + await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); + if (!(await this.checkSum(native.sha1, join(nativeDirectory, name)))) { + await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); + } + try { + new Zip(join(nativeDirectory, name)).extractAllTo(nativeDirectory, true); + } catch (e) { + // Only doing a console.warn since a stupid error happens. You can basically ignore this. + // if it says Invalid file name, just means two files were downloaded and both were deleted. + // All is well. + console.warn(e); + } + unlinkSync(join(nativeDirectory, name)); + counter++; + this.client.emit('progress', { + type: 'natives', + task: counter, + total: stat.length, + }); + }), + ); + this.client.emit('debug', '[MCLC]: Downloaded and extracted natives'); + } + + counter = 0; + this.client.emit('debug', `[MCLC]: Set native path to ${nativeDirectory}`); + + return nativeDirectory; + } + + fwAddArgs() { + const forgeWrapperAgrs = [ + `-Dforgewrapper.librariesDir=${_resolve(this.options.overrides.libraryRoot || join(this.options.root, 'libraries'))}`, + `-Dforgewrapper.installer=${this.options.forge}`, + `-Dforgewrapper.minecraft=${this.options.mcPath}`, + ]; + this.options.customArgs + ? (this.options.customArgs = this.options.customArgs.concat(forgeWrapperAgrs)) + : (this.options.customArgs = forgeWrapperAgrs); + } + + isModernForge(json) { + return ( + json.inheritsFrom && + json.inheritsFrom.split('.')[1] >= 12 && + !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') + ); + } + + async getForgedWrapped() { + let json = null; + let installerJson = null; + const versionPath = join(this.options.root, 'forge', `${this.version.id}`, 'version.json'); + // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not + // be re-generated on the next run. + if (existsSync(versionPath)) { + try { + json = JSON.parse(readFileSync(versionPath)); + if (!json.forgeWrapperVersion || !(json.forgeWrapperVersion === this.options.overrides.fw.version)) { + this.client.emit( + 'debug', + '[MCLC]: Old ForgeWrapper has generated this version JSON, re-generating', + ); + } else { + // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. + if (this.isModernForge(json)) { + this.fwAddArgs(); + this.options.forge = null; + } + return json; + } + } catch (e) { + console.warn(e); + this.client.emit('debug', '[MCLC]: Failed to parse Forge version JSON, re-generating'); + } + } + + this.client.emit('debug', '[MCLC]: Generating Forge version json, this might take a bit'); + const zipFile = new Zip(this.options.forge); + json = zipFile.readAsText('version.json'); + if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); + + try { + json = JSON.parse(json); + if (installerJson) installerJson = JSON.parse(installerJson); + } catch (e) { + this.client.emit('debug', '[MCLC]: Failed to load json files for ForgeWrapper, using Vanilla instead'); + return null; + } + // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. + if (installerJson) { + json.mavenFiles + ? (json.mavenFiles = json.mavenFiles.concat(installerJson.libraries)) + : (json.mavenFiles = installerJson.libraries); + } + + // Holder for the specifc jar ending which depends on the specifc forge version. + let jarEnding = 'universal'; + // We need to handle modern forge differently than legacy. + if (this.isModernForge(json)) { + // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. + if (json.inheritsFrom !== '1.12.2') { + this.fwAddArgs(); + const fwName = `ForgeWrapper-${this.options.overrides.fw.version}.jar`; + const fwPathArr = ['io', 'github', 'zekerzhayard', 'ForgeWrapper', this.options.overrides.fw.version]; + json.libraries.push({ + name: fwPathArr.join(':'), + downloads: { + artifact: { + path: [...fwPathArr, fwName].join('/'), + url: `${this.options.overrides.fw.baseUrl}${this.options.overrides.fw.version}/${fwName}`, + sha1: this.options.overrides.fw.sh1, + size: this.options.overrides.fw.size, + }, + }, + }); + json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main'; + jarEnding = 'launcher'; + + // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. + for (const library of json.mavenFiles) { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { + library.downloads.artifact.url = + this.options.overrides.url.mavenForge + library.downloads.artifact.path; + break; + } + } + } else { + // Remove the forge dependent since we're going to overwrite the first entry anyways. + for (const library in json.mavenFiles) { + const lib = json.mavenFiles[library].name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { + delete json.mavenFiles[library]; + break; + } + } + } + } else { + // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. + await Promise.all( + json.libraries.map(async (library) => { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; + + let url = this.options.overrides.url.mavenForge; + const name = `${lib[1]}-${lib[2]}.jar`; + + if (!library.url) { + if (library.serverreq || library.clientreq) { + url = this.options.overrides.url.defaultRepoForge; + } else { + return; + } + } + library.url = url; + const downloadLink = `${url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; + // Checking if the file still exists on Forge's server, if not, replace it with the fallback. + // Not checking for sucess, only if it 404s. + try { + const response = await axios.head(downloadLink); + if (response.status === 404) library.url = this.options.overrides.url.fallbackMaven; + } catch (error) { + this.client.emit('debug', `[MCLC]: Failed checking request for ${downloadLink}`); + } + }), + ); + } + // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. + // If it doesn't, we simply remove it since we're already providing the universal jar. + if (json.libraries[0].downloads) { + const name = json.libraries[0].name; + if (name.includes('minecraftforge:forge') && !name.includes('universal')) { + json.libraries[0].name = name + `:${jarEnding}`; + json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.path.replace( + '.jar', + `-${jarEnding}.jar`, + ); + json.libraries[0].downloads.artifact.url = + this.options.overrides.url.mavenForge + json.libraries[0].downloads.artifact.path; + } + } else { + delete json.libraries[0]; + } + + // Removing duplicates and null types + json.libraries = this.cleanUp(json.libraries); + if (json.mavenFiles) json.mavenFiles = this.cleanUp(json.mavenFiles); + + json.forgeWrapperVersion = this.options.overrides.fw.version; + + // Saving file for next run! + if (!existsSync(join(this.options.root, 'forge', this.version.id))) { + mkdirSync(join(this.options.root, 'forge', this.version.id), { recursive: true }); + } + writeFileSync(versionPath, JSON.stringify(json, null, 4)); + + // Make MCLC treat modern forge as a custom version json rather then legacy forge. + if (this.isModernForge(json)) this.options.forge = null; + + return json; + } + + async downloadToDirectory(directory, libraries, eventName) { + const libs = []; + + await Promise.all( + libraries.map(async (library) => { + if (!library) return; + if (this.parseRule(library)) return; + const lib = library.name.split(':'); + + let jarPath; + let name; + if (library.downloads && library.downloads.artifact && library.downloads.artifact.path) { + name = + library.downloads.artifact.path.split('/')[ + library.downloads.artifact.path.split('/').length - 1 + ]; + jarPath = join(directory, this.popString(library.downloads.artifact.path)); + } else { + name = `${lib[1]}-${lib[2]}${lib[3] ? '-' + lib[3] : ''}.jar`; + jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); + } + + const downloadLibrary = async (library) => { + if (library.url) { + const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; + await this.downloadAsync(url, jarPath, name, true, eventName); + } else if (library.downloads && library.downloads.artifact && library.downloads.artifact.url) { + // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. + await this.downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); + } + }; + + if (!existsSync(join(jarPath, name))) await downloadLibrary(library); + if (library.downloads && library.downloads.artifact) { + if (!this.checkSum(library.downloads.artifact.sha1, join(jarPath, name))) + await downloadLibrary(library); + } + + counter++; + this.client.emit('progress', { + type: eventName, + task: counter, + total: libraries.length, + }); + libs.push(`${jarPath}${sep}${name}`); + }), + ); + counter = 0; + + return libs; + } + + async getClasses(classJson) { + let libs = []; + + const libraryDirectory = _resolve(this.options.overrides.libraryRoot || join(this.options.root, 'libraries')); + + if (classJson) { + if (classJson.mavenFiles) { + await this.downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom'); + } + libs = await this.downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom'); + } + + const parsed = this.version.libraries.map((lib) => { + if (lib.downloads && lib.downloads.artifact && !this.parseRule(lib)) return lib; + }); + + libs = libs.concat(await this.downloadToDirectory(libraryDirectory, parsed, 'classes')); + counter = 0; + + // Temp Quilt support + if (classJson) libs.sort(); + + this.client.emit('debug', '[MCLC]: Collected class paths'); + return libs; + } + + popString(path) { + return path.split('/').slice(0, -1).join('/'); + } + + cleanUp(array) { + return [...new Set(Object.values(array).filter((value) => value !== null))]; + } + + formatQuickPlay() { + const types = { + singleplayer: '--quickPlaySingleplayer', + multiplayer: '--quickPlayMultiplayer', + realms: '--quickPlayRealms', + legacy: null, + }; + const { type, identifier, path } = this.options.quickPlay; + const keys = Object.keys(types); + if (!keys.includes(type)) { + this.client.emit('debug', `[MCLC]: quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); + return null; + } + const returnArgs = + type === 'legacy' + ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] + : [types[type], identifier]; + if (path) returnArgs.push('--quickPlayPath', path); + return returnArgs; + } + + async getLaunchOptions(modification) { + const type = Object.assign({}, this.version, modification); + + let args = type.minecraftArguments ? type.minecraftArguments.split(' ') : type.arguments.game; + const assetRoot = _resolve(this.options.overrides.assetRoot || join(this.options.root, 'assets')); + const assetPath = this.isLegacy() ? join(this.options.root, 'resources') : join(assetRoot); + + const minArgs = this.options.overrides.minArgs || this.isLegacy() ? 5 : 11; + if (args.length < minArgs) + args = args.concat( + this.version.minecraftArguments + ? this.version.minecraftArguments.split(' ') + : this.version.arguments.game, + ); + if (this.options.customLaunchArgs) args = args.concat(this.options.customLaunchArgs); + + this.options.authorization = await Promise.resolve(this.options.authorization); + this.options.authorization.meta = this.options.authorization.meta + ? this.options.authorization.meta + : { type: 'mojang' }; + const fields = { + '${auth_access_token}': this.options.authorization.access_token, + '${auth_session}': this.options.authorization.access_token, + '${auth_player_name}': this.options.authorization.name, + '${auth_uuid}': this.options.authorization.uuid, + '${auth_xuid}': this.options.authorization.meta.xuid || this.options.authorization.access_token, + '${user_properties}': this.options.authorization.user_properties, + '${user_type}': this.options.authorization.meta.type, + '${version_name}': this.options.version.number || this.options.overrides.versionName, + '${assets_index_name}': + this.options.overrides.assetIndex || this.options.version.custom || this.options.version.number, + '${game_directory}': this.options.overrides.gameDirectory || this.options.root, + '${assets_root}': assetPath, + '${game_assets}': assetPath, + '${version_type}': this.options.version.type, + '${clientid}': + this.options.authorization.meta.clientId || + this.options.authorization.client_token || + this.options.authorization.access_token, + '${resolution_width}': this.options.window ? this.options.window.width : 856, + '${resolution_height}': this.options.window ? this.options.window.height : 482, + }; + + if ( + this.options.authorization.meta.demo && + (this.options.features ? !this.options.features.includes('is_demo_user') : true) + ) { + args.push('--demo'); + } + + const replaceArg = (obj, index) => { + if (Array.isArray(obj.value)) { + for (const arg of obj.value) { + args.push(arg); + } + } else { + args.push(obj.value); + } + delete args[index]; + }; + + for (let index = 0; index < args.length; index++) { + if (typeof args[index] === 'object') { + if (args[index].rules) { + if (!this.options.features) continue; + const featureFlags = []; + for (const rule of args[index].rules) { + featureFlags.push(...Object.keys(rule.features)); + } + let hasAllRules = true; + for (const feature of this.options.features) { + if (!featureFlags.includes(feature)) { + hasAllRules = false; + } + } + if (hasAllRules) replaceArg(args[index], index); + } else { + replaceArg(args[index], index); + } + } else { + if (Object.keys(fields).includes(args[index])) { + args[index] = fields[args[index]]; + } + } + } + if (this.options.window) { + if (this.options.window.fullscreen) { + args.push('--fullscreen'); + } else { + if (this.options.window.width) args.push('--width', this.options.window.width); + if (this.options.window.height) args.push('--height', this.options.window.height); + } + } + if (this.options.server) + this.client.emit('debug', '[MCLC]: server and port are deprecated launch flags. Use the quickPlay field.'); + if (this.options.quickPlay) args = args.concat(this.formatQuickPlay()); + if (this.options.proxy) { + args.push( + '--proxyHost', + this.options.proxy.host, + '--proxyPort', + this.options.proxy.port || '8080', + '--proxyUser', + this.options.proxy.username, + '--proxyPass', + this.options.proxy.password, + ); + } + args = args.filter((value) => typeof value === 'string' || typeof value === 'number'); + this.client.emit('debug', '[MCLC]: Set launch options'); + return args; + } + + async getJVM() { + const opts = { + windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', + osx: '-XstartOnFirstThread', + linux: '-Xss1M', + }; + return opts[this.getOS()]; + } + + isLegacy() { + return this.version.assets === 'legacy' || this.version.assets === 'pre-1.6'; + } + + getOS() { + if (this.options.os) { + return this.options.os; + } else { + switch (process.platform) { + case 'win32': + return 'windows'; + case 'darwin': + return 'osx'; + default: + return 'linux'; + } + } + } + + // To prevent launchers from breaking when they update. Will be reworked with rewrite. + getMemory() { + if (!this.options.memory) { + this.client.emit('debug', '[MCLC]: Memory not set! Setting 1GB as MAX!'); + this.options.memory = { + min: 512, + max: 1023, + }; + } + if (!isNaN(this.options.memory.max) && !isNaN(this.options.memory.min)) { + if (this.options.memory.max < this.options.memory.min) { + this.client.emit('debug', '[MCLC]: MIN memory is higher then MAX! Resetting!'); + this.options.memory.max = 1023; + this.options.memory.min = 512; + } + return [`${this.options.memory.max}M`, `${this.options.memory.min}M`]; + } else { + return [`${this.options.memory.max}`, `${this.options.memory.min}`]; + } + } + + async extractPackage(options = this.options) { + if (options.clientPackage.startsWith('http')) { + await this.downloadAsync(options.clientPackage, options.root, 'clientPackage.zip', true, 'client-package'); + options.clientPackage = join(options.root, 'clientPackage.zip'); + } + new Zip(options.clientPackage).extractAllTo(options.root, true); + if (options.removePackage) unlinkSync(options.clientPackage); + + return this.client.emit('package-extract', true); + } + + checksumFile(filename, callback) { + _stat(filename, function (err, stat) { + if (!err && !stat.isFile()) err = new Error('Not a file'); + if (err) return callback(err); + + const hash = createHash('sha1'); + const fileStream = createReadStream(filename); + + if (!hash.write) { + fileStream.on('data', function (data) { + hash.update(data); + }); + + fileStream.on('end', function () { + callback(null, hash.digest('hex')); + }); + } else { + hash.setEncoding('hex'); + fileStream.pipe(hash, { end: false }); + + fileStream.on('end', function () { + hash.end(); + callback(null, hash.read()); + }); + } + }); + } +} + +export default Handler; diff --git a/src/esm/launcher.mjs b/src/esm/launcher.mjs new file mode 100644 index 0000000..61a13d5 --- /dev/null +++ b/src/esm/launcher.mjs @@ -0,0 +1,215 @@ +import { spawn } from 'node:child_process'; +import { EventEmitter } from 'node:events'; +import { existsSync, mkdirSync, readFileSync } from 'node:fs'; +import { join, resolve } from 'node:path'; +import Handler from './handler.mjs'; + +class MCLCore extends EventEmitter { + async launch(options) { + this.options = { ...options }; + this.options.root = resolve(this.options.root); + this.options.overrides = { + detached: true, + ...this.options.overrides, + url: { + meta: 'https://launchermeta.mojang.com', + resource: 'https://resources.download.minecraft.net', + mavenForge: 'https://files.minecraftforge.net/maven/', + defaultRepoForge: 'https://libraries.minecraft.net/', + fallbackMaven: 'https://search.maven.org/remotecontent?filepath=', + ...(this.options.overrides ? this.options.overrides.url : undefined), + }, + fw: { + baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', + version: '1.5.7', + sh1: '155ac9f4e5f65288eaacae19025ac4d9da1f0ef2', + size: 34910, + ...(this.options.overrides ? this.options.overrides.fw : undefined), + }, + }; + + this.handler = new Handler(this); + + this.emit('debug', `[MCLC]: MCLC version ${this.version()}`); + + const java = await this.handler.checkJava(this.options.javaPath || 'java'); + if (!java.run) { + this.emit('debug', `[MCLC]: Couldn't start Minecraft due to: ${java.message}`); + this.emit('close', 1); + return null; + } + + this.createRootDirectory(); + this.createGameDirectory(); + + await this.extractPackage(); + + const directory = + this.options.overrides.directory || + join( + this.options.root, + 'versions', + this.options.version.custom ? this.options.version.custom : this.options.version.number, + ); + this.options.directory = directory; + + const versionFile = await this.handler.getVersion(); + const mcPath = + this.options.overrides.minecraftJar || + (this.options.version.custom + ? join(this.options.root, 'versions', this.options.version.custom, `${this.options.version.custom}.jar`) + : join(directory, `${this.options.version.number}.jar`)); + this.options.mcPath = mcPath; + const nativePath = await this.handler.getNatives(); + + if (!existsSync(mcPath)) { + this.emit('debug', '[MCLC]: Attempting to download Minecraft version jar'); + await this.handler.getJar(); + } + + const modifyJson = await this.getModifyJson(); + + const args = []; + + let jvm = [ + '-XX:-UseAdaptiveSizePolicy', + '-XX:-OmitStackTraceInFastThrow', + '-Dfml.ignorePatchDiscrepancies=true', + '-Dfml.ignoreInvalidMinecraftCertificates=true', + `-Djava.library.path=${nativePath}`, + `-Xmx${this.handler.getMemory()[0]}`, + `-Xms${this.handler.getMemory()[1]}`, + ]; + if (this.handler.getOS() === 'osx') { + if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()); + } else jvm.push(await this.handler.getJVM()); + + if (this.options.customArgs) jvm = jvm.concat(this.options.customArgs); + if (this.options.overrides.logj4ConfigurationFile) { + jvm.push(`-Dlog4j.configurationFile=${resolve(this.options.overrides.logj4ConfigurationFile)}`); + } + // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition + if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) + jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) < 17) { + if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { + const configPath = resolve(this.options.overrides.cwd || this.options.root); + const intVersion = parseInt(versionFile.id.split('.')[1]); + if (intVersion >= 12) { + await this.handler.downloadAsync( + 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', + configPath, + 'log4j2_112-116.xml', + true, + 'log4j', + ); + jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml'); + } else if (intVersion >= 7) { + await this.handler.downloadAsync( + 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', + configPath, + 'log4j2_17-111.xml', + true, + 'log4j', + ); + jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml'); + } + } + } + + const classes = + this.options.overrides.classes || this.handler.cleanUp(await this.handler.getClasses(modifyJson)); + const classPaths = ['-cp']; + const separator = this.handler.getOS() === 'windows' ? ';' : ':'; + this.emit('debug', `[MCLC]: Using ${separator} to separate class paths`); + // Handling launch arguments. + const file = modifyJson || versionFile; + // So mods like fabric work. + const jar = existsSync(mcPath) + ? `${separator}${mcPath}` + : `${separator}${join(directory, `${this.options.version.number}.jar`)}`; + classPaths.push(`${this.options.forge ? this.options.forge + separator : ''}${classes.join(separator)}${jar}`); + classPaths.push(file.mainClass); + + this.emit('debug', '[MCLC]: Attempting to download assets'); + await this.handler.getAssets(); + + // Forge -> Custom -> Vanilla + const launchOptions = await this.handler.getLaunchOptions(modifyJson); + + const launchArguments = args.concat(jvm, classPaths, launchOptions); + this.emit('arguments', launchArguments); + this.emit('debug', `[MCLC]: Launching with arguments ${launchArguments.join(' ')}`); + + return this.startMinecraft(launchArguments); + } + + createRootDirectory() { + if (!existsSync(this.options.root)) { + this.emit('debug', '[MCLC]: Attempting to create root folder'); + mkdirSync(this.options.root); + } + } + + createGameDirectory() { + if (this.options.overrides.gameDirectory) { + this.options.overrides.gameDirectory = resolve(this.options.overrides.gameDirectory); + if (!existsSync(this.options.overrides.gameDirectory)) { + mkdirSync(this.options.overrides.gameDirectory, { recursive: true }); + } + } + } + + async extractPackage() { + if (this.options.clientPackage) { + this.emit('debug', `[MCLC]: Extracting client package to ${this.options.root}`); + await this.handler.extractPackage(); + } + } + + async getModifyJson() { + let modifyJson = null; + + if (this.options.forge) { + this.options.forge = resolve(this.options.forge); + this.emit('debug', '[MCLC]: Detected Forge in options, getting dependencies'); + modifyJson = await this.handler.getForgedWrapped(); + } else if (this.options.version.custom) { + this.emit('debug', '[MCLC]: Detected custom in options, setting custom version file'); + modifyJson = + modifyJson || + JSON.parse( + readFileSync( + join( + this.options.root, + 'versions', + this.options.version.custom, + `${this.options.version.custom}.json`, + ), + { encoding: 'utf8' }, + ), + ); + } + + return modifyJson; + } + + startMinecraft(launchArguments) { + const minecraft = spawn(this.options.javaPath ? this.options.javaPath : 'java', launchArguments, { + cwd: this.options.overrides.cwd || this.options.root, + detached: this.options.overrides.detached, + }); + minecraft.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))); + minecraft.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))); + minecraft.on('close', (code) => this.emit('close', code)); + return minecraft; + } + + version() { + // Should be changed each update + return '3.18.0'; + } +} + +export default MCLCore; diff --git a/src/index.cjs b/src/index.cjs new file mode 100644 index 0000000..1c791d8 --- /dev/null +++ b/src/index.cjs @@ -0,0 +1,4 @@ +module.exports = { + Client: require('./src/cjs/launcher'), + Authenticator: require('./src/cjs/authenticator'), +}; diff --git a/src/index.mjs b/src/index.mjs new file mode 100644 index 0000000..172ce2d --- /dev/null +++ b/src/index.mjs @@ -0,0 +1,2 @@ +export { default as Client } from './esm/launcher.mjs'; +export * as Authenticator from './esm/authenticator.mjs'; diff --git a/test.cjs b/test.cjs new file mode 100644 index 0000000..4c8f797 --- /dev/null +++ b/test.cjs @@ -0,0 +1,22 @@ +const { Client, Authenticator } = require('./src/index.cjs'); +const launcher = new Client(); + +launcher.launch({ + authorization: Authenticator.getAuth('username'), + root: './minecraft', + version: { + number: '1.7.10', + type: 'release', + }, + memory: { + max: '4G', + min: '2G', + }, + overrides: { + maxSockets: 32, + }, +}); + +launcher.on('debug', (e) => console.log(e)); +launcher.on('data', (e) => console.log(e)); +launcher.on('progress', (e) => console.log(e)); diff --git a/test.js b/test.mjs similarity index 88% rename from test.js rename to test.mjs index e2a93ad..05dc0e6 100644 --- a/test.js +++ b/test.mjs @@ -1,4 +1,5 @@ -const { Client, Authenticator } = require('.'); +import { Authenticator, Client } from './src/index.mjs'; + const launcher = new Client(); launcher.launch({ From 57237b0405b37911c4e31d3e59b16442388cf989 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 28 Feb 2024 17:10:45 +0300 Subject: [PATCH 10/97] Preparations for rewriting to TS --- src/index.mjs => index.mjs | 0 src/{esm => }/authenticator.mjs | 0 src/cjs/authenticator.cjs | 107 ---- src/cjs/handler.cjs | 832 -------------------------------- src/cjs/launcher.cjs | 220 --------- src/{esm => }/handler.mjs | 0 src/index.cjs | 4 - src/{esm => }/launcher.mjs | 0 test.cjs | 22 - 9 files changed, 1185 deletions(-) rename src/index.mjs => index.mjs (100%) rename src/{esm => }/authenticator.mjs (100%) delete mode 100644 src/cjs/authenticator.cjs delete mode 100644 src/cjs/handler.cjs delete mode 100644 src/cjs/launcher.cjs rename src/{esm => }/handler.mjs (100%) delete mode 100644 src/index.cjs rename src/{esm => }/launcher.mjs (100%) delete mode 100644 test.cjs diff --git a/src/index.mjs b/index.mjs similarity index 100% rename from src/index.mjs rename to index.mjs diff --git a/src/esm/authenticator.mjs b/src/authenticator.mjs similarity index 100% rename from src/esm/authenticator.mjs rename to src/authenticator.mjs diff --git a/src/cjs/authenticator.cjs b/src/cjs/authenticator.cjs deleted file mode 100644 index e478b75..0000000 --- a/src/cjs/authenticator.cjs +++ /dev/null @@ -1,107 +0,0 @@ -const axios = require('axios'); -const { v3 } = require('uuid'); - -let uuid; -let api_url = 'https://authserver.mojang.com'; - -module.exports.getAuth = function (username, password, client_token = null) { - return new Promise((resolve, reject) => { - if (!uuid) uuid = v3(username, v3.DNS); - if (!password) - return resolve({ - access_token: uuid, - client_token: client_token || uuid, - uuid, - name: username, - user_properties: '{}', - }); - - axios - .post(api_url + '/authenticate', { - agent: { - name: 'Minecraft', - version: 1, - }, - username, - password, - clientToken: uuid, - requestUser: true, - }) - .then(({ body }) => { - if (!body || !body.selectedProfile) - return reject(new Error('Validation error: ' + response.statusMessage)); - - return resolve({ - access_token: body.accessToken, - client_token: body.clientToken, - uuid: body.selectedProfile.id, - name: body.selectedProfile.name, - selected_profile: body.selectedProfile, - user_properties: parsePropts(body.user.properties), - }); - }) - .catch((error) => reject(error)); - }); -}; - -module.exports.validate = function (accessToken, clientToken) { - return new Promise((resolve, reject) => - axios - .post(api_url + '/validate', { accessToken, clientToken }) - .then(({ data }) => (!data ? resolve(true) : reject(data))) - .catch((error) => reject(error)), - ); -}; - -module.exports.refreshAuth = function (accessToken, clientToken) { - return new Promise((resolve, reject) => - axios - .post(api_url + '/refresh', { accessToken, clientToken, requestUser: true }) - .then(({ body }) => { - if (!body || !body.selectedProfile) - return reject(new Error('Validation error: ' + response.statusMessage)); - - return resolve({ - access_token: body.accessToken, - client_token: getUUID(body.selectedProfile.name), - uuid: body.selectedProfile.id, - name: body.selectedProfile.name, - user_properties: parsePropts(body.user.properties), - }); - }) - .catch((error) => reject(error)), - ); -}; - -module.exports.invalidate = function (accessToken, clientToken) { - return new Promise((resolve, reject) => - axios - .post(api_url + '/invalidate', { accessToken, clientToken }) - .then(({ data }) => (!data ? resolve(true) : reject(data))) - .catch((error) => reject(error)), - ); -}; - -module.exports.signOut = function (username, password) { - return new Promise((resolve, reject) => - axios - .post(api_url + '/signout', { username, password }) - .then(({ data }) => (!data ? resolve(true) : reject(data))) - .catch((error) => reject(error)), - ); -}; - -module.exports.changeApiUrl = function (url) { - api_url = url; - return; -}; - -const parsePropts = (array) => { - if (!array) return '{}'; - - const newObj = {}; - for (const entry of array) - newObj[entry.name] ? newObj[entry.name].push(entry.value) : (newObj[entry.name] = [entry.value]); - - return JSON.stringify(newObj); -}; diff --git a/src/cjs/handler.cjs b/src/cjs/handler.cjs deleted file mode 100644 index 36f5639..0000000 --- a/src/cjs/handler.cjs +++ /dev/null @@ -1,832 +0,0 @@ -const fs = require('node:fs'); -const path = require('node:path'); -const child = require('node:child_process'); -const http = require('node:http'); -const https = require('node:https'); -const crypto = require('node:crypto'); -const axios = require('axios'); -const Zip = require('adm-zip'); - -let counter = 0; - -class Handler { - constructor(client) { - this.client = client; - this.options = client.options; - this.baseRequest = axios.create({ - timeout: this.options.timeout || 50000, - httpAgent: new http.Agent({ keepAlive: true, maxSockets: this.options.overrides.maxSockets || 2 }), - httpsAgent: new https.Agent({ keepAlive: true, maxSockets: this.options.overrides.maxSockets || 2 }), - }); - } - - checkJava(java) { - return new Promise((resolve) => { - child.exec(`"${java}" -version`, (error, stdout, stderr) => { - if (error) { - resolve({ - run: false, - message: error, - }); - } else { - this.client.emit( - 'debug', - `[MCLC]: Using Java version ${stderr.match(/"(.*?)"/).pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`, - ); - resolve({ - run: true, - }); - } - }); - }); - } - - async downloadAsync(url, directory, name, retry, type) { - try { - fs.mkdirSync(directory, { recursive: true }); - - const response = await this.baseRequest({ - url: url, - method: 'GET', - responseType: 'stream', - }); - - const totalBytes = parseInt(response.headers['content-length']); - let receivedBytes = 0; - - response.data.on('data', (data) => { - receivedBytes += data.length; - this.client.emit('download-status', { - name: name, - type: type, - current: receivedBytes, - total: totalBytes, - }); - }); - - const file = fs.createWriteStream(path.join(directory, name)); - response.data.pipe(file); - - await new Promise((resolve, reject) => { - file.on('finish', resolve); - file.on('error', reject); - }); - - this.client.emit('download', name); - return { - failed: false, - asset: null, - }; - } catch (error) { - this.client.emit( - 'debug', - `[MCLC]: Failed to download asset to ${path.join(directory, name)} due\n${error}. Retrying... ${retry}`, - ); - if (retry) await this.downloadAsync(url, directory, name, false, type); - return; - } - } - - checkSum(hash, file) { - return new Promise((resolve, reject) => { - this.checksumFile(file, (err, sum) => { - if (err) { - this.client.emit('debug', `[MCLC]: Failed to check file hash due to ${err}`); - return reject(); - } - - return resolve(hash === sum); - }); - }); - } - - async getVersion() { - try { - const versionJsonPath = - this.options.overrides.versionJson || - path.join(this.options.directory, `${this.options.version.number}.json`); - if (fs.existsSync(versionJsonPath)) { - this.version = JSON.parse(fs.readFileSync(versionJsonPath)); - return this.version; - } - - const manifest = `${this.options.overrides.url.meta}/mc/game/version_manifest.json`; - const cache = this.options.cache ? `${this.options.cache}/json` : `${this.options.root}/cache/json`; - const { data } = await axios.get(manifest); - - if (!fs.existsSync(cache)) { - fs.mkdirSync(cache, { recursive: true }); - this.client.emit('debug', '[MCLC]: Cache directory created.'); - } - - fs.writeFileSync(path.join(cache, 'version_manifest.json'), JSON.stringify(data)); - this.client.emit('debug', '[MCLC]: Cached version_manifest.json'); - - const desiredVersion = Object.values(data.versions).find( - (version) => version.id === this.options.version.number, - ); - if (desiredVersion) { - const { data } = await axios.get(desiredVersion.url); - fs.writeFileSync(path.join(`${cache}/${this.options.version.number}.json`), JSON.stringify(data)); - this.client.emit('debug', `[MCLC]: Cached ${this.options.version.number}.json`); - - this.client.emit('debug', '[MCLC]: Parsed version from version manifest'); - this.version = data; - return this.version; - } else { - throw Error(`Failed to find version ${this.options.version.number} in version_manifest.json`); - } - } catch (error) { - return error; - } - } - - async getJar() { - await this.downloadAsync( - this.version.downloads.client.url, - this.options.directory, - `${this.options.version.custom ? this.options.version.custom : this.options.version.number}.jar`, - true, - 'version-jar', - ); - fs.writeFileSync( - path.join(this.options.directory, `${this.options.version.number}.json`), - JSON.stringify(this.version, null, 4), - ); - return this.client.emit('debug', '[MCLC]: Downloaded version jar and wrote version json'); - } - - async getAssets() { - const assetDirectory = path.resolve(this.options.overrides.assetRoot || path.join(this.options.root, 'assets')); - const assetId = this.options.version.custom || this.options.version.number; - if (!fs.existsSync(path.join(assetDirectory, 'indexes', `${assetId}.json`))) { - await this.downloadAsync( - this.version.assetIndex.url, - path.join(assetDirectory, 'indexes'), - `${assetId}.json`, - true, - 'asset-json', - ); - } - - const index = JSON.parse( - fs.readFileSync(path.join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' }), - ); - - this.client.emit('progress', { - type: 'assets', - task: 0, - total: Object.keys(index.objects).length, - }); - - await Promise.all( - Object.keys(index.objects).map(async (asset) => { - const hash = index.objects[asset].hash; - const subhash = hash.substring(0, 2); - const subAsset = path.join(assetDirectory, 'objects', subhash); - - if ( - !fs.existsSync(path.join(subAsset, hash)) || - !(await this.checkSum(hash, path.join(subAsset, hash))) - ) { - await this.downloadAsync( - `${this.options.overrides.url.resource}/${subhash}/${hash}`, - subAsset, - hash, - true, - 'assets', - ); - } - counter++; - this.client.emit('progress', { - type: 'assets', - task: counter, - total: Object.keys(index.objects).length, - }); - }), - ); - counter = 0; - - // Copy assets to legacy if it's an older Minecraft version. - if (this.isLegacy()) { - if (fs.existsSync(path.join(assetDirectory, 'legacy'))) { - this.client.emit( - 'debug', - "[MCLC]: The 'legacy' directory is no longer used as Minecraft looks " + - "for the resouces folder regardless of what is passed in the assetDirecotry launch option. I'd " + - `recommend removing the directory (${path.join(assetDirectory, 'legacy')})`, - ); - } - - const legacyDirectory = path.join(this.options.root, 'resources'); - this.client.emit('debug', `[MCLC]: Copying assets over to ${legacyDirectory}`); - - this.client.emit('progress', { - type: 'assets-copy', - task: 0, - total: Object.keys(index.objects).length, - }); - - await Promise.all( - Object.keys(index.objects).map(async (asset) => { - const hash = index.objects[asset].hash; - const subhash = hash.substring(0, 2); - const subAsset = path.join(assetDirectory, 'objects', subhash); - - const legacyAsset = asset.split('/'); - legacyAsset.pop(); - - if (!fs.existsSync(path.join(legacyDirectory, legacyAsset.join('/')))) { - fs.mkdirSync(path.join(legacyDirectory, legacyAsset.join('/')), { recursive: true }); - } - - if (!fs.existsSync(path.join(legacyDirectory, asset))) { - fs.copyFileSync(path.join(subAsset, hash), path.join(legacyDirectory, asset)); - } - counter++; - this.client.emit('progress', { - type: 'assets-copy', - task: counter, - total: Object.keys(index.objects).length, - }); - }), - ); - } - counter = 0; - - this.client.emit('debug', '[MCLC]: Downloaded assets'); - } - - parseRule(lib) { - if (lib.rules) { - if (lib.rules.length > 1) { - if ( - lib.rules[0].action === 'allow' && - lib.rules[1].action === 'disallow' && - lib.rules[1].os.name === 'osx' - ) { - return this.getOS() === 'osx'; - } - return true; - } else { - if (lib.rules[0].action === 'allow' && lib.rules[0].os) return lib.rules[0].os.name !== this.getOS(); - } - } else { - return false; - } - } - - async getNatives() { - const nativeDirectory = path.resolve( - this.options.overrides.natives || path.join(this.options.root, 'natives', this.version.id), - ); - - if (parseInt(this.version.id.split('.')[1]) >= 19) return this.options.overrides.cwd || this.options.root; - - if (!fs.existsSync(nativeDirectory) || !fs.readdirSync(nativeDirectory).length) { - fs.mkdirSync(nativeDirectory, { recursive: true }); - - const natives = async () => { - const natives = []; - await Promise.all( - this.version.libraries.map(async (lib) => { - if (!lib.downloads || !lib.downloads.classifiers) return; - if (this.parseRule(lib)) return; - - const native = - this.getOS() === 'osx' - ? lib.downloads.classifiers['natives-osx'] || lib.downloads.classifiers['natives-macos'] - : lib.downloads.classifiers[`natives-${this.getOS()}`]; - - natives.push(native); - }), - ); - return natives; - }; - const stat = await natives(); - - this.client.emit('progress', { - type: 'natives', - task: 0, - total: stat.length, - }); - - await Promise.all( - stat.map(async (native) => { - if (!native) return; - const name = native.path.split('/').pop(); - await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); - if (!(await this.checkSum(native.sha1, path.join(nativeDirectory, name)))) { - await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); - } - try { - new Zip(path.join(nativeDirectory, name)).extractAllTo(nativeDirectory, true); - } catch (e) { - // Only doing a console.warn since a stupid error happens. You can basically ignore this. - // if it says Invalid file name, just means two files were downloaded and both were deleted. - // All is well. - console.warn(e); - } - fs.unlinkSync(path.join(nativeDirectory, name)); - counter++; - this.client.emit('progress', { - type: 'natives', - task: counter, - total: stat.length, - }); - }), - ); - this.client.emit('debug', '[MCLC]: Downloaded and extracted natives'); - } - - counter = 0; - this.client.emit('debug', `[MCLC]: Set native path to ${nativeDirectory}`); - - return nativeDirectory; - } - - fwAddArgs() { - const forgeWrapperAgrs = [ - `-Dforgewrapper.librariesDir=${path.resolve(this.options.overrides.libraryRoot || path.join(this.options.root, 'libraries'))}`, - `-Dforgewrapper.installer=${this.options.forge}`, - `-Dforgewrapper.minecraft=${this.options.mcPath}`, - ]; - this.options.customArgs - ? (this.options.customArgs = this.options.customArgs.concat(forgeWrapperAgrs)) - : (this.options.customArgs = forgeWrapperAgrs); - } - - isModernForge(json) { - return ( - json.inheritsFrom && - json.inheritsFrom.split('.')[1] >= 12 && - !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') - ); - } - - async getForgedWrapped() { - let json = null; - let installerJson = null; - const versionPath = path.join(this.options.root, 'forge', `${this.version.id}`, 'version.json'); - // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not - // be re-generated on the next run. - if (fs.existsSync(versionPath)) { - try { - json = JSON.parse(fs.readFileSync(versionPath)); - if (!json.forgeWrapperVersion || !(json.forgeWrapperVersion === this.options.overrides.fw.version)) { - this.client.emit( - 'debug', - '[MCLC]: Old ForgeWrapper has generated this version JSON, re-generating', - ); - } else { - // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. - if (this.isModernForge(json)) { - this.fwAddArgs(); - this.options.forge = null; - } - return json; - } - } catch (e) { - console.warn(e); - this.client.emit('debug', '[MCLC]: Failed to parse Forge version JSON, re-generating'); - } - } - - this.client.emit('debug', '[MCLC]: Generating Forge version json, this might take a bit'); - const zipFile = new Zip(this.options.forge); - json = zipFile.readAsText('version.json'); - if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); - - try { - json = JSON.parse(json); - if (installerJson) installerJson = JSON.parse(installerJson); - } catch (e) { - this.client.emit('debug', '[MCLC]: Failed to load json files for ForgeWrapper, using Vanilla instead'); - return null; - } - // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. - if (installerJson) { - json.mavenFiles - ? (json.mavenFiles = json.mavenFiles.concat(installerJson.libraries)) - : (json.mavenFiles = installerJson.libraries); - } - - // Holder for the specifc jar ending which depends on the specifc forge version. - let jarEnding = 'universal'; - // We need to handle modern forge differently than legacy. - if (this.isModernForge(json)) { - // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. - if (json.inheritsFrom !== '1.12.2') { - this.fwAddArgs(); - const fwName = `ForgeWrapper-${this.options.overrides.fw.version}.jar`; - const fwPathArr = ['io', 'github', 'zekerzhayard', 'ForgeWrapper', this.options.overrides.fw.version]; - json.libraries.push({ - name: fwPathArr.join(':'), - downloads: { - artifact: { - path: [...fwPathArr, fwName].join('/'), - url: `${this.options.overrides.fw.baseUrl}${this.options.overrides.fw.version}/${fwName}`, - sha1: this.options.overrides.fw.sh1, - size: this.options.overrides.fw.size, - }, - }, - }); - json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main'; - jarEnding = 'launcher'; - - // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. - for (const library of json.mavenFiles) { - const lib = library.name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - library.downloads.artifact.url = - this.options.overrides.url.mavenForge + library.downloads.artifact.path; - break; - } - } - } else { - // Remove the forge dependent since we're going to overwrite the first entry anyways. - for (const library in json.mavenFiles) { - const lib = json.mavenFiles[library].name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - delete json.mavenFiles[library]; - break; - } - } - } - } else { - // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. - await Promise.all( - json.libraries.map(async (library) => { - const lib = library.name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; - - let url = this.options.overrides.url.mavenForge; - const name = `${lib[1]}-${lib[2]}.jar`; - - if (!library.url) { - if (library.serverreq || library.clientreq) { - url = this.options.overrides.url.defaultRepoForge; - } else { - return; - } - } - library.url = url; - const downloadLink = `${url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; - // Checking if the file still exists on Forge's server, if not, replace it with the fallback. - // Not checking for sucess, only if it 404s. - try { - const response = await axios.head(downloadLink); - if (response.status === 404) library.url = this.options.overrides.url.fallbackMaven; - } catch (error) { - this.client.emit('debug', `[MCLC]: Failed checking request for ${downloadLink}`); - } - }), - ); - } - // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. - // If it doesn't, we simply remove it since we're already providing the universal jar. - if (json.libraries[0].downloads) { - const name = json.libraries[0].name; - if (name.includes('minecraftforge:forge') && !name.includes('universal')) { - json.libraries[0].name = name + `:${jarEnding}`; - json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.path.replace( - '.jar', - `-${jarEnding}.jar`, - ); - json.libraries[0].downloads.artifact.url = - this.options.overrides.url.mavenForge + json.libraries[0].downloads.artifact.path; - } - } else { - delete json.libraries[0]; - } - - // Removing duplicates and null types - json.libraries = this.cleanUp(json.libraries); - if (json.mavenFiles) json.mavenFiles = this.cleanUp(json.mavenFiles); - - json.forgeWrapperVersion = this.options.overrides.fw.version; - - // Saving file for next run! - if (!fs.existsSync(path.join(this.options.root, 'forge', this.version.id))) { - fs.mkdirSync(path.join(this.options.root, 'forge', this.version.id), { recursive: true }); - } - fs.writeFileSync(versionPath, JSON.stringify(json, null, 4)); - - // Make MCLC treat modern forge as a custom version json rather then legacy forge. - if (this.isModernForge(json)) this.options.forge = null; - - return json; - } - - async downloadToDirectory(directory, libraries, eventName) { - const libs = []; - - await Promise.all( - libraries.map(async (library) => { - if (!library) return; - if (this.parseRule(library)) return; - const lib = library.name.split(':'); - - let jarPath; - let name; - if (library.downloads && library.downloads.artifact && library.downloads.artifact.path) { - name = - library.downloads.artifact.path.split('/')[ - library.downloads.artifact.path.split('/').length - 1 - ]; - jarPath = path.join(directory, this.popString(library.downloads.artifact.path)); - } else { - name = `${lib[1]}-${lib[2]}${lib[3] ? '-' + lib[3] : ''}.jar`; - jarPath = path.join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); - } - - const downloadLibrary = async (library) => { - if (library.url) { - const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; - await this.downloadAsync(url, jarPath, name, true, eventName); - } else if (library.downloads && library.downloads.artifact && library.downloads.artifact.url) { - // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. - await this.downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); - } - }; - - if (!fs.existsSync(path.join(jarPath, name))) await downloadLibrary(library); - if (library.downloads && library.downloads.artifact) { - if (!this.checkSum(library.downloads.artifact.sha1, path.join(jarPath, name))) - await downloadLibrary(library); - } - - counter++; - this.client.emit('progress', { - type: eventName, - task: counter, - total: libraries.length, - }); - libs.push(`${jarPath}${path.sep}${name}`); - }), - ); - counter = 0; - - return libs; - } - - async getClasses(classJson) { - let libs = []; - - const libraryDirectory = path.resolve( - this.options.overrides.libraryRoot || path.join(this.options.root, 'libraries'), - ); - - if (classJson) { - if (classJson.mavenFiles) { - await this.downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom'); - } - libs = await this.downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom'); - } - - const parsed = this.version.libraries.map((lib) => { - if (lib.downloads && lib.downloads.artifact && !this.parseRule(lib)) return lib; - }); - - libs = libs.concat(await this.downloadToDirectory(libraryDirectory, parsed, 'classes')); - counter = 0; - - // Temp Quilt support - if (classJson) libs.sort(); - - this.client.emit('debug', '[MCLC]: Collected class paths'); - return libs; - } - - popString(path) { - return path.split('/').slice(0, -1).join('/'); - } - - cleanUp(array) { - return [...new Set(Object.values(array).filter((value) => value !== null))]; - } - - formatQuickPlay() { - const types = { - singleplayer: '--quickPlaySingleplayer', - multiplayer: '--quickPlayMultiplayer', - realms: '--quickPlayRealms', - legacy: null, - }; - const { type, identifier, path } = this.options.quickPlay; - const keys = Object.keys(types); - if (!keys.includes(type)) { - this.client.emit('debug', `[MCLC]: quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); - return null; - } - const returnArgs = - type === 'legacy' - ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] - : [types[type], identifier]; - if (path) returnArgs.push('--quickPlayPath', path); - return returnArgs; - } - - async getLaunchOptions(modification) { - const type = Object.assign({}, this.version, modification); - - let args = type.minecraftArguments ? type.minecraftArguments.split(' ') : type.arguments.game; - const assetRoot = path.resolve(this.options.overrides.assetRoot || path.join(this.options.root, 'assets')); - const assetPath = this.isLegacy() ? path.join(this.options.root, 'resources') : path.join(assetRoot); - - const minArgs = this.options.overrides.minArgs || this.isLegacy() ? 5 : 11; - if (args.length < minArgs) - args = args.concat( - this.version.minecraftArguments - ? this.version.minecraftArguments.split(' ') - : this.version.arguments.game, - ); - if (this.options.customLaunchArgs) args = args.concat(this.options.customLaunchArgs); - - this.options.authorization = await Promise.resolve(this.options.authorization); - this.options.authorization.meta = this.options.authorization.meta - ? this.options.authorization.meta - : { type: 'mojang' }; - const fields = { - '${auth_access_token}': this.options.authorization.access_token, - '${auth_session}': this.options.authorization.access_token, - '${auth_player_name}': this.options.authorization.name, - '${auth_uuid}': this.options.authorization.uuid, - '${auth_xuid}': this.options.authorization.meta.xuid || this.options.authorization.access_token, - '${user_properties}': this.options.authorization.user_properties, - '${user_type}': this.options.authorization.meta.type, - '${version_name}': this.options.version.number || this.options.overrides.versionName, - '${assets_index_name}': - this.options.overrides.assetIndex || this.options.version.custom || this.options.version.number, - '${game_directory}': this.options.overrides.gameDirectory || this.options.root, - '${assets_root}': assetPath, - '${game_assets}': assetPath, - '${version_type}': this.options.version.type, - '${clientid}': - this.options.authorization.meta.clientId || - this.options.authorization.client_token || - this.options.authorization.access_token, - '${resolution_width}': this.options.window ? this.options.window.width : 856, - '${resolution_height}': this.options.window ? this.options.window.height : 482, - }; - - if ( - this.options.authorization.meta.demo && - (this.options.features ? !this.options.features.includes('is_demo_user') : true) - ) { - args.push('--demo'); - } - - const replaceArg = (obj, index) => { - if (Array.isArray(obj.value)) { - for (const arg of obj.value) { - args.push(arg); - } - } else { - args.push(obj.value); - } - delete args[index]; - }; - - for (let index = 0; index < args.length; index++) { - if (typeof args[index] === 'object') { - if (args[index].rules) { - if (!this.options.features) continue; - const featureFlags = []; - for (const rule of args[index].rules) { - featureFlags.push(...Object.keys(rule.features)); - } - let hasAllRules = true; - for (const feature of this.options.features) { - if (!featureFlags.includes(feature)) { - hasAllRules = false; - } - } - if (hasAllRules) replaceArg(args[index], index); - } else { - replaceArg(args[index], index); - } - } else { - if (Object.keys(fields).includes(args[index])) { - args[index] = fields[args[index]]; - } - } - } - if (this.options.window) { - if (this.options.window.fullscreen) { - args.push('--fullscreen'); - } else { - if (this.options.window.width) args.push('--width', this.options.window.width); - if (this.options.window.height) args.push('--height', this.options.window.height); - } - } - if (this.options.server) - this.client.emit('debug', '[MCLC]: server and port are deprecated launch flags. Use the quickPlay field.'); - if (this.options.quickPlay) args = args.concat(this.formatQuickPlay()); - if (this.options.proxy) { - args.push( - '--proxyHost', - this.options.proxy.host, - '--proxyPort', - this.options.proxy.port || '8080', - '--proxyUser', - this.options.proxy.username, - '--proxyPass', - this.options.proxy.password, - ); - } - args = args.filter((value) => typeof value === 'string' || typeof value === 'number'); - this.client.emit('debug', '[MCLC]: Set launch options'); - return args; - } - - async getJVM() { - const opts = { - windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', - osx: '-XstartOnFirstThread', - linux: '-Xss1M', - }; - return opts[this.getOS()]; - } - - isLegacy() { - return this.version.assets === 'legacy' || this.version.assets === 'pre-1.6'; - } - - getOS() { - if (this.options.os) { - return this.options.os; - } else { - switch (process.platform) { - case 'win32': - return 'windows'; - case 'darwin': - return 'osx'; - default: - return 'linux'; - } - } - } - - // To prevent launchers from breaking when they update. Will be reworked with rewrite. - getMemory() { - if (!this.options.memory) { - this.client.emit('debug', '[MCLC]: Memory not set! Setting 1GB as MAX!'); - this.options.memory = { - min: 512, - max: 1023, - }; - } - if (!isNaN(this.options.memory.max) && !isNaN(this.options.memory.min)) { - if (this.options.memory.max < this.options.memory.min) { - this.client.emit('debug', '[MCLC]: MIN memory is higher then MAX! Resetting!'); - this.options.memory.max = 1023; - this.options.memory.min = 512; - } - return [`${this.options.memory.max}M`, `${this.options.memory.min}M`]; - } else { - return [`${this.options.memory.max}`, `${this.options.memory.min}`]; - } - } - - async extractPackage(options = this.options) { - if (options.clientPackage.startsWith('http')) { - await this.downloadAsync(options.clientPackage, options.root, 'clientPackage.zip', true, 'client-package'); - options.clientPackage = path.join(options.root, 'clientPackage.zip'); - } - new Zip(options.clientPackage).extractAllTo(options.root, true); - if (options.removePackage) fs.unlinkSync(options.clientPackage); - - return this.client.emit('package-extract', true); - } - - checksumFile(filename, callback) { - fs.stat(filename, function (err, stat) { - if (!err && !stat.isFile()) err = new Error('Not a file'); - if (err) return callback(err); - - const hash = crypto.createHash('sha1'); - const fileStream = fs.createReadStream(filename); - - if (!hash.write) { - fileStream.on('data', function (data) { - hash.update(data); - }); - - fileStream.on('end', function () { - callback(null, hash.digest('hex')); - }); - } else { - hash.setEncoding('hex'); - fileStream.pipe(hash, { end: false }); - - fileStream.on('end', function () { - hash.end(); - callback(null, hash.read()); - }); - } - }); - } -} - -module.exports = Handler; diff --git a/src/cjs/launcher.cjs b/src/cjs/launcher.cjs deleted file mode 100644 index c4c3338..0000000 --- a/src/cjs/launcher.cjs +++ /dev/null @@ -1,220 +0,0 @@ -const child = require('node:child_process'); -const path = require('node:path'); -const fs = require('node:fs'); -const EventEmitter = require('node:events').EventEmitter; -const Handler = require('./handler'); - -class MCLCore extends EventEmitter { - async launch(options) { - this.options = { ...options }; - this.options.root = path.resolve(this.options.root); - this.options.overrides = { - detached: true, - ...this.options.overrides, - url: { - meta: 'https://launchermeta.mojang.com', - resource: 'https://resources.download.minecraft.net', - mavenForge: 'https://files.minecraftforge.net/maven/', - defaultRepoForge: 'https://libraries.minecraft.net/', - fallbackMaven: 'https://search.maven.org/remotecontent?filepath=', - ...(this.options.overrides ? this.options.overrides.url : undefined), - }, - fw: { - baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', - version: '1.5.7', - sh1: '155ac9f4e5f65288eaacae19025ac4d9da1f0ef2', - size: 34910, - ...(this.options.overrides ? this.options.overrides.fw : undefined), - }, - }; - - this.handler = new Handler(this); - - this.emit('debug', `[MCLC]: MCLC version ${this.version()}`); - - const java = await this.handler.checkJava(this.options.javaPath || 'java'); - if (!java.run) { - this.emit('debug', `[MCLC]: Couldn't start Minecraft due to: ${java.message}`); - this.emit('close', 1); - return null; - } - - this.createRootDirectory(); - this.createGameDirectory(); - - await this.extractPackage(); - - const directory = - this.options.overrides.directory || - path.join( - this.options.root, - 'versions', - this.options.version.custom ? this.options.version.custom : this.options.version.number, - ); - this.options.directory = directory; - - const versionFile = await this.handler.getVersion(); - const mcPath = - this.options.overrides.minecraftJar || - (this.options.version.custom - ? path.join( - this.options.root, - 'versions', - this.options.version.custom, - `${this.options.version.custom}.jar`, - ) - : path.join(directory, `${this.options.version.number}.jar`)); - this.options.mcPath = mcPath; - const nativePath = await this.handler.getNatives(); - - if (!fs.existsSync(mcPath)) { - this.emit('debug', '[MCLC]: Attempting to download Minecraft version jar'); - await this.handler.getJar(); - } - - const modifyJson = await this.getModifyJson(); - - const args = []; - - let jvm = [ - '-XX:-UseAdaptiveSizePolicy', - '-XX:-OmitStackTraceInFastThrow', - '-Dfml.ignorePatchDiscrepancies=true', - '-Dfml.ignoreInvalidMinecraftCertificates=true', - `-Djava.library.path=${nativePath}`, - `-Xmx${this.handler.getMemory()[0]}`, - `-Xms${this.handler.getMemory()[1]}`, - ]; - if (this.handler.getOS() === 'osx') { - if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()); - } else jvm.push(await this.handler.getJVM()); - - if (this.options.customArgs) jvm = jvm.concat(this.options.customArgs); - if (this.options.overrides.logj4ConfigurationFile) { - jvm.push(`-Dlog4j.configurationFile=${path.resolve(this.options.overrides.logj4ConfigurationFile)}`); - } - // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition - if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) - jvm.push('-Dlog4j2.formatMsgNoLookups=true'); - if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); - if (parseInt(versionFile.id.split('.')[1]) < 17) { - if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { - const configPath = path.resolve(this.options.overrides.cwd || this.options.root); - const intVersion = parseInt(versionFile.id.split('.')[1]); - if (intVersion >= 12) { - await this.handler.downloadAsync( - 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', - configPath, - 'log4j2_112-116.xml', - true, - 'log4j', - ); - jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml'); - } else if (intVersion >= 7) { - await this.handler.downloadAsync( - 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', - configPath, - 'log4j2_17-111.xml', - true, - 'log4j', - ); - jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml'); - } - } - } - - const classes = - this.options.overrides.classes || this.handler.cleanUp(await this.handler.getClasses(modifyJson)); - const classPaths = ['-cp']; - const separator = this.handler.getOS() === 'windows' ? ';' : ':'; - this.emit('debug', `[MCLC]: Using ${separator} to separate class paths`); - // Handling launch arguments. - const file = modifyJson || versionFile; - // So mods like fabric work. - const jar = fs.existsSync(mcPath) - ? `${separator}${mcPath}` - : `${separator}${path.join(directory, `${this.options.version.number}.jar`)}`; - classPaths.push(`${this.options.forge ? this.options.forge + separator : ''}${classes.join(separator)}${jar}`); - classPaths.push(file.mainClass); - - this.emit('debug', '[MCLC]: Attempting to download assets'); - await this.handler.getAssets(); - - // Forge -> Custom -> Vanilla - const launchOptions = await this.handler.getLaunchOptions(modifyJson); - - const launchArguments = args.concat(jvm, classPaths, launchOptions); - this.emit('arguments', launchArguments); - this.emit('debug', `[MCLC]: Launching with arguments ${launchArguments.join(' ')}`); - - return this.startMinecraft(launchArguments); - } - - createRootDirectory() { - if (!fs.existsSync(this.options.root)) { - this.emit('debug', '[MCLC]: Attempting to create root folder'); - fs.mkdirSync(this.options.root); - } - } - - createGameDirectory() { - if (this.options.overrides.gameDirectory) { - this.options.overrides.gameDirectory = path.resolve(this.options.overrides.gameDirectory); - if (!fs.existsSync(this.options.overrides.gameDirectory)) { - fs.mkdirSync(this.options.overrides.gameDirectory, { recursive: true }); - } - } - } - - async extractPackage() { - if (this.options.clientPackage) { - this.emit('debug', `[MCLC]: Extracting client package to ${this.options.root}`); - await this.handler.extractPackage(); - } - } - - async getModifyJson() { - let modifyJson = null; - - if (this.options.forge) { - this.options.forge = path.resolve(this.options.forge); - this.emit('debug', '[MCLC]: Detected Forge in options, getting dependencies'); - modifyJson = await this.handler.getForgedWrapped(); - } else if (this.options.version.custom) { - this.emit('debug', '[MCLC]: Detected custom in options, setting custom version file'); - modifyJson = - modifyJson || - JSON.parse( - fs.readFileSync( - path.join( - this.options.root, - 'versions', - this.options.version.custom, - `${this.options.version.custom}.json`, - ), - { encoding: 'utf8' }, - ), - ); - } - - return modifyJson; - } - - startMinecraft(launchArguments) { - const minecraft = child.spawn(this.options.javaPath ? this.options.javaPath : 'java', launchArguments, { - cwd: this.options.overrides.cwd || this.options.root, - detached: this.options.overrides.detached, - }); - minecraft.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))); - minecraft.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))); - minecraft.on('close', (code) => this.emit('close', code)); - return minecraft; - } - - version() { - // Should be changed each update - return '3.18.0'; - } -} - -module.exports = MCLCore; diff --git a/src/esm/handler.mjs b/src/handler.mjs similarity index 100% rename from src/esm/handler.mjs rename to src/handler.mjs diff --git a/src/index.cjs b/src/index.cjs deleted file mode 100644 index 1c791d8..0000000 --- a/src/index.cjs +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - Client: require('./src/cjs/launcher'), - Authenticator: require('./src/cjs/authenticator'), -}; diff --git a/src/esm/launcher.mjs b/src/launcher.mjs similarity index 100% rename from src/esm/launcher.mjs rename to src/launcher.mjs diff --git a/test.cjs b/test.cjs deleted file mode 100644 index 4c8f797..0000000 --- a/test.cjs +++ /dev/null @@ -1,22 +0,0 @@ -const { Client, Authenticator } = require('./src/index.cjs'); -const launcher = new Client(); - -launcher.launch({ - authorization: Authenticator.getAuth('username'), - root: './minecraft', - version: { - number: '1.7.10', - type: 'release', - }, - memory: { - max: '4G', - min: '2G', - }, - overrides: { - maxSockets: 32, - }, -}); - -launcher.on('debug', (e) => console.log(e)); -launcher.on('data', (e) => console.log(e)); -launcher.on('progress', (e) => console.log(e)); From 4f6b2f0af70923bad7889f90a5d31a923fd7c4b5 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Thu, 29 Feb 2024 18:02:23 +0300 Subject: [PATCH 11/97] [WIP] Recode into TS --- .gitignore | 2 +- .travis.yml | 2 - README.md | 4 - index.d.ts | 291 --------------- index.mjs | 2 - package.json | 26 +- src/authenticator.mjs | 107 ------ src/authenticator.ts | 7 + src/handler.mjs | 838 ------------------------------------------ src/handler.ts | 541 +++++++++++++++++++++++++++ src/index.ts | 3 + src/launcher.mjs | 215 ----------- src/launcher.ts | 139 +++++++ src/utils/config.ts | 30 ++ src/utils/index.ts | 45 +++ src/utils/log.ts | 15 + src/utils/types.ts | 266 ++++++++++++++ test.js | 7 + test.mjs | 23 -- tsconfig.json | 24 ++ yarn.lock | 37 +- 21 files changed, 1131 insertions(+), 1493 deletions(-) delete mode 100644 .travis.yml delete mode 100644 index.d.ts delete mode 100644 index.mjs delete mode 100644 src/authenticator.mjs create mode 100644 src/authenticator.ts delete mode 100644 src/handler.mjs create mode 100644 src/handler.ts create mode 100644 src/index.ts delete mode 100644 src/launcher.mjs create mode 100644 src/launcher.ts create mode 100644 src/utils/config.ts create mode 100644 src/utils/index.ts create mode 100644 src/utils/log.ts create mode 100644 src/utils/types.ts create mode 100644 test.js delete mode 100644 test.mjs create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 06d119a..4ef9888 100644 --- a/.gitignore +++ b/.gitignore @@ -33,7 +33,7 @@ bower_components .lock-wscript # Compiled binary addons (http://nodejs.org/api/addons.html) -build/Release +build/ # Dependency directories node_modules/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 93f3350..0000000 --- a/.travis.yml +++ /dev/null @@ -1,2 +0,0 @@ -language: node_js -script: echo "npm test temporarily disabled" diff --git a/README.md b/README.md index 301e700..f93a660 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ ##### Project rewrite coming soon™ -[![Build Status](https://travis-ci.com/Pierce01/MinecraftLauncher-core.svg?branch=master)](https://travis-ci.com/Pierce01/MinecraftLauncher-core) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![version](https://img.shields.io/badge/stable_version-3.18.0-blue) @@ -64,7 +63,6 @@ launcher.on('data', (e) => console.log(e)); | Parameter | Type | Description | Required | | ------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- | -------- | -| `options.clientPackage` | String | Path or URL to a zip file, which will be extracted to the root directory. (Not recommended for production use) | False | | `options.removePackage` | Boolean | Option to remove the client package zip file after its finished extracting. | False | | `options.root` | String | Path where you want the launcher to work in. `C:/Users/user/AppData/Roaming/.mc` | True | | `options.cache` | String | Path where launcher files will be cached in. `C:/Users/user/AppData/Roaming/.mc/cache` | False | @@ -107,7 +105,6 @@ let opts = { assetRoot: '', assetIndex: '', libraryRoot: '', - cwd: '', // working directory of the java process. detached: true, // whether or not the client is detached from the parent / launcher. classes: [], // all class paths are required if you use this. minArgs: 11, // The amount of launch arguments specified in the version file before it adds the default again @@ -212,7 +209,6 @@ MCLC's authenticator module does not support Microsoft authentication. You will | `arguments` | Object | Emitted when launch arguments are set for the Minecraft Jar. | | `data` | String | Emitted when information is returned from the Minecraft Process | | `close` | Integer | Code number that is returned by the Minecraft Process | -| `package-extract` | null | Emitted when `clientPackage` finishes being extracted | | `download` | String | Emitted when a file successfully downloads | | `download-status` | Object | Emitted when data is received while downloading | | `debug` | String | Emitted when functions occur, made to help debug if errors occur | diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index 3f7e665..0000000 --- a/index.d.ts +++ /dev/null @@ -1,291 +0,0 @@ -/// - -declare module 'minecraft-launcher-core' { - interface IOverrides { - /** - * The amount of launch arguments specified in the version file before it adds the default again - */ - minArgs?: number; - minecraftJar?: string; - versionJson?: string; - versionName?: string; - /** - * Folder, where the game process generates folders like saves and resource packs. - */ - gameDirectory?: string; - /** - * Folder, where the Minecraft jar and version json are located. - */ - directory?: string; - natives?: string; - assetRoot?: string; - assetIndex?: string; - libraryRoot?: string; - /** - * Working directory of the java process. - */ - cwd?: string; - /** - * Whether or not the client is detached from the parent / launcher. - */ - detached?: boolean; - /** - * List of classes. - * All class paths are required if you use this. - */ - classes?: Array; - /** - * Max sockets for downloadAsync. - */ - maxSockets?: number; - /** - * Urls to the Minecraft and Forge resource servers - * - * This is for launcher developers located in countries that have the Minecraft and Forge resource servers - * blocked for what ever reason. They obviously need to mirror the formatting of the original JSONs / file structures. - */ - url?: { - /** - * List of versions. - */ - meta?: string; - /** - * Minecraft resources. - */ - resource?: string; - /** - * Forge resources. - */ - mavenForge?: string; - /** - * for Forge only, you need to redefine the library url in the version json. - */ - defaultRepoForge?: string; - /** - * - */ - fallbackMaven?: string; - }; - /** - * Version of the ForgeWrapper which MCLC uses. This allows us to launch modern Forge. - */ - fw?: { - baseUrl?: string; - version?: string; - sh1?: string; - size?: number; - }; - logj4ConfigurationFile?: string; - } - - interface ILauncherOptions { - /** - * Path or URL to the client package zip file. - */ - clientPackage?: string; - /** - * if true MCLC will remove the client package zip file after its finished extracting. - */ - removePackage?: boolean; - /** - * Path where you want the launcher to work in. - * This will usually be your .minecraft folder - */ - root: string; - /** - * OS override for minecraft natives - * - * @default will autodetect - */ - os?: 'windows' | 'osx' | 'linux'; - /** - * Array of custom Minecraft arguments. - */ - customLaunchArgs?: Array; - /** - * Array of custom Java arguments - */ - customArgs?: Array; - /** - * Array of game argument feature flags - */ - features?: Array; - /** - * minecraft version info - */ - version: { - /** - * Actual version. - * - * @example '1.16.4' - */ - number: string; - /** - * type of release, usually `release` or `snapshot` - */ - type: 'release' | 'snapshot' | string; - /** - * The name of the folder, jar file, and version json in the version folder. - * - * ` MCLC will look in the `versions` folder for this name - * @example '1.16.4-fabric' - */ - custom?: string; - }; - memory: { - /** - * Min amount of memory being used by Minecraft. - */ - max: string | number; - /** - * Max amount of memory being used by Minecraft. - */ - min: string | number; - }; - /** - * Path to Forge Jar. - * - * Versions below 1.13 should be the "universal" jar while versions above 1.13+ should be the "installer" jar - */ - forge?: string; - /** - * Path to the JRE executable file, will default to java if not entered. - */ - javaPath?: string; - proxy?: { - /** - * Host url to the proxy, don't include the port. - */ - host: string; - /** - * Username for the proxy. - * - * @default 8080 - */ - port?: string; - /** - * Username for the proxy. - */ - username?: string; - /** - * Password for the proxy. - */ - password?: string; - }; - /** - * Timeout on download requests. - */ - timeout?: number; - window?: { - /** - * Width of the Minecraft Client - */ - width?: number; - /** - * Height of the Minecraft Client - */ - height?: number; - /** - * Fullscreen the Minecraft Client. - */ - fullscreen?: boolean; - }; - - /** - * Allows the game to be launched directly into a world - */ - quickPlay?: { - /** - * The type of world you want to join. - * Note, that versions prior to 1.20 only support "legacy" - */ - type: 'singleplayer' | 'multiplayer' | 'realms' | 'legacy'; - /** - * Represents the world you want to join - * - * For singleplayer this should be the folder name of the world - * For multiplayer this should be the IP address of the server - * For realms this should be the Realms ID - * legacy follows multiplayer format - */ - identifier: string; - /** - * The specified path for logging (relative to the run directory) - */ - path?: string; - }; - /** - * Json object redefining paths for better customization - */ - overrides?: IOverrides; - - authorization: Promise | IUser; - /** - * Path of json cache. - */ - cache?: string; - } - - interface IUser { - access_token: string; - client_token: string; - uuid: string; - name: string; - user_properties: Partial; - meta?: { - type: 'mojang' | 'msa'; - demo?: boolean; - }; - } - - interface IProfile { - id: number; - name: string; - } - - interface IAuthenticator { - /** - * @param username email if using a password, else the username - * @param password password for mojang account - */ - getAuth(username: string, password?: string): Promise; - /** - * - * @param access_token Token being checked if it can be used to login with (online mode) - * @param client_token Client token being checked to see if there was a change of client (online mode) - */ - validate(access_token: string, client_token: string): Promise>; - /** - * - * @param access_token Token being checked if it can be used to login with (online mode) - * @param client_token Client token being checked to see if there was a change of client (online mode) - */ - refreshAuth(access_token: string, client_token: string): Promise; - /** - * - * @param access_token Token being checked if it can be used to login with (online mode) - * @param client_token Client token being checked to see if there was a change of client (online mode) - */ - invalidate(access_token: string, client_token: string): Promise>; - /** - * @param username email if using a password, else the username - * @param password password for mojang account - */ - signOut(username: string, password: string): Promise>; - changeApiUrl(url: string): void; - } - - import { EventEmitter } from 'events'; - import { ChildProcessWithoutNullStreams } from 'child_process'; - - export class Client extends EventEmitter { - launch(options: ILauncherOptions): Promise; - protected createRootDirectory(): void; - protected createGameDirectory(): void; - protected extractPackage(): Promise; - protected getModifyJson(): Promise; - protected startMinecraft(launchArguments: string[]): ChildProcessWithoutNullStreams; - } - - export const Authenticator: IAuthenticator; -} diff --git a/index.mjs b/index.mjs deleted file mode 100644 index 172ce2d..0000000 --- a/index.mjs +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Client } from './esm/launcher.mjs'; -export * as Authenticator from './esm/authenticator.mjs'; diff --git a/package.json b/package.json index ec6b8fb..68dfd9b 100644 --- a/package.json +++ b/package.json @@ -2,25 +2,39 @@ "name": "minecraft-launcher-core", "version": "3.18.0", "description": "Lightweight module that downloads and runs Minecraft using javascript / NodeJS", - "main": "src/esm.js", - "type": "module", + "main": "./build/cjs/index.js", + "module": "./build/esm/index.js", + "types": "./build/esm/index.d.ts", + "files": [ + "./build/" + ], + "type": "commonjs", "dependencies": { - "adm-zip": "^0.4.13", + "adm-zip": "^0.5.10", "axios": "^1.6.7", "uuid": "^8.3.2" }, "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.1.1", + "@types/adm-zip": "^0.5.5", "@types/node": "^14.0.27", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^7.1.0", "@typescript-eslint/parser": "^7.1.0", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "prettier": "^3.2.5" + "prettier": "^3.2.5", + "typescript": "^5.3.3" }, "scripts": { - "test": "eslint ." + "clean": "rm -rf ./lib/", + "build": "yarn clean && yarn build:esm && yarn tsc", + "build:esm": "tsc --module esnext --declaration --outDir ./build/esm", + "lint": "eslint --color .", + "prettier": "prettier --check .", + "prettier:write": "prettier --write .", + "typecheck": "tsc --noEmit" }, "repository": { "type": "git", @@ -39,4 +53,4 @@ "url": "https://github.com/Pierce01/MinecraftLauncher-core/issues" }, "homepage": "https://github.com/Pierce01/MinecraftLauncher-core#readme" -} \ No newline at end of file +} diff --git a/src/authenticator.mjs b/src/authenticator.mjs deleted file mode 100644 index 6e70ab2..0000000 --- a/src/authenticator.mjs +++ /dev/null @@ -1,107 +0,0 @@ -import axios from 'axios'; -import { v3 } from 'uuid'; - -let uuid; -let api_url = 'https://authserver.mojang.com'; - -export function getAuth(username, password, client_token = null) { - return new Promise((resolve, reject) => { - if (!uuid) uuid = v3(username, v3.DNS); - if (!password) - return resolve({ - access_token: uuid, - client_token: client_token || uuid, - uuid, - name: username, - user_properties: '{}', - }); - - axios - .post(api_url + '/authenticate', { - agent: { - name: 'Minecraft', - version: 1, - }, - username, - password, - clientToken: uuid, - requestUser: true, - }) - .then(({ body }) => { - if (!body || !body.selectedProfile) - return reject(new Error('Validation error: ' + response.statusMessage)); - - return resolve({ - access_token: body.accessToken, - client_token: body.clientToken, - uuid: body.selectedProfile.id, - name: body.selectedProfile.name, - selected_profile: body.selectedProfile, - user_properties: parsePropts(body.user.properties), - }); - }) - .catch((error) => reject(error)); - }); -} - -export function validate(accessToken, clientToken) { - return new Promise((resolve, reject) => - axios - .post(api_url + '/validate', { accessToken, clientToken }) - .then(({ data }) => (!data ? resolve(true) : reject(data))) - .catch((error) => reject(error)), - ); -} - -export function refreshAuth(accessToken, clientToken) { - return new Promise((resolve, reject) => - axios - .post(api_url + '/refresh', { accessToken, clientToken, requestUser: true }) - .then(({ body }) => { - if (!body || !body.selectedProfile) - return reject(new Error('Validation error: ' + response.statusMessage)); - - return resolve({ - access_token: body.accessToken, - client_token: getUUID(body.selectedProfile.name), - uuid: body.selectedProfile.id, - name: body.selectedProfile.name, - user_properties: parsePropts(body.user.properties), - }); - }) - .catch((error) => reject(error)), - ); -} - -export function invalidate(accessToken, clientToken) { - return new Promise((resolve, reject) => - axios - .post(api_url + '/invalidate', { accessToken, clientToken }) - .then(({ data }) => (!data ? resolve(true) : reject(data))) - .catch((error) => reject(error)), - ); -} - -export function signOut(username, password) { - return new Promise((resolve, reject) => - axios - .post(api_url + '/signout', { username, password }) - .then(({ data }) => (!data ? resolve(true) : reject(data))) - .catch((error) => reject(error)), - ); -} - -export function changeApiUrl(url) { - api_url = url; - return; -} - -const parsePropts = (array) => { - if (!array) return '{}'; - - const newObj = {}; - for (const entry of array) - newObj[entry.name] ? newObj[entry.name].push(entry.value) : (newObj[entry.name] = [entry.value]); - - return JSON.stringify(newObj); -}; diff --git a/src/authenticator.ts b/src/authenticator.ts new file mode 100644 index 0000000..591cc7a --- /dev/null +++ b/src/authenticator.ts @@ -0,0 +1,7 @@ +import { v3 } from 'uuid'; +import { User } from './utils/types'; + +export const loginOffline = (username: string): User => { + const uuid = v3(username, v3.DNS); + return { access_token: uuid, client_token: uuid, uuid, name: username, user_properties: '{}' }; +}; diff --git a/src/handler.mjs b/src/handler.mjs deleted file mode 100644 index c78fa3b..0000000 --- a/src/handler.mjs +++ /dev/null @@ -1,838 +0,0 @@ -import { - stat as _stat, - copyFileSync, - createReadStream, - createWriteStream, - existsSync, - mkdirSync, - readdirSync, - readFileSync, - unlinkSync, - writeFileSync, -} from 'fs'; -import { exec } from 'node:child_process'; -import { createHash } from 'node:crypto'; -import { Agent } from 'node:http'; -import { Agent as _Agent } from 'node:https'; -import { resolve as _resolve, join, sep } from 'node:path'; -import Zip from 'adm-zip'; -import axios from 'axios'; - -let counter = 0; - -class Handler { - constructor(client) { - this.client = client; - this.options = client.options; - this.baseRequest = axios.create({ - timeout: this.options.timeout || 50000, - httpAgent: new Agent({ keepAlive: true, maxSockets: this.options.overrides.maxSockets || 2 }), - httpsAgent: new _Agent({ keepAlive: true, maxSockets: this.options.overrides.maxSockets || 2 }), - }); - } - - checkJava(java) { - return new Promise((resolve) => { - exec(`"${java}" -version`, (error, stdout, stderr) => { - if (error) { - resolve({ - run: false, - message: error, - }); - } else { - this.client.emit( - 'debug', - `[MCLC]: Using Java version ${stderr.match(/"(.*?)"/).pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`, - ); - resolve({ - run: true, - }); - } - }); - }); - } - - async downloadAsync(url, directory, name, retry, type) { - try { - mkdirSync(directory, { recursive: true }); - - const response = await this.baseRequest({ - url: url, - method: 'GET', - responseType: 'stream', - }); - - const totalBytes = parseInt(response.headers['content-length']); - let receivedBytes = 0; - - response.data.on('data', (data) => { - receivedBytes += data.length; - this.client.emit('download-status', { - name: name, - type: type, - current: receivedBytes, - total: totalBytes, - }); - }); - - const file = createWriteStream(join(directory, name)); - response.data.pipe(file); - - await new Promise((resolve, reject) => { - file.on('finish', resolve); - file.on('error', reject); - }); - - this.client.emit('download', name); - return { - failed: false, - asset: null, - }; - } catch (error) { - this.client.emit( - 'debug', - `[MCLC]: Failed to download asset to ${join(directory, name)} due\n${error}. Retrying... ${retry}`, - ); - if (retry) await this.downloadAsync(url, directory, name, false, type); - return; - } - } - - checkSum(hash, file) { - return new Promise((resolve, reject) => { - this.checksumFile(file, (err, sum) => { - if (err) { - this.client.emit('debug', `[MCLC]: Failed to check file hash due to ${err}`); - return reject(); - } - - return resolve(hash === sum); - }); - }); - } - - async getVersion() { - try { - const versionJsonPath = - this.options.overrides.versionJson || - join(this.options.directory, `${this.options.version.number}.json`); - if (existsSync(versionJsonPath)) { - this.version = JSON.parse(readFileSync(versionJsonPath)); - return this.version; - } - - const manifest = `${this.options.overrides.url.meta}/mc/game/version_manifest.json`; - const cache = this.options.cache ? `${this.options.cache}/json` : `${this.options.root}/cache/json`; - const { data } = await axios.get(manifest); - - if (!existsSync(cache)) { - mkdirSync(cache, { recursive: true }); - this.client.emit('debug', '[MCLC]: Cache directory created.'); - } - - writeFileSync(join(cache, 'version_manifest.json'), JSON.stringify(data)); - this.client.emit('debug', '[MCLC]: Cached version_manifest.json'); - - const desiredVersion = Object.values(data.versions).find( - (version) => version.id === this.options.version.number, - ); - if (desiredVersion) { - const { data } = await axios.get(desiredVersion.url); - writeFileSync(join(`${cache}/${this.options.version.number}.json`), JSON.stringify(data)); - this.client.emit('debug', `[MCLC]: Cached ${this.options.version.number}.json`); - - this.client.emit('debug', '[MCLC]: Parsed version from version manifest'); - this.version = data; - return this.version; - } else { - throw Error(`Failed to find version ${this.options.version.number} in version_manifest.json`); - } - } catch (error) { - return error; - } - } - - async getJar() { - await this.downloadAsync( - this.version.downloads.client.url, - this.options.directory, - `${this.options.version.custom ? this.options.version.custom : this.options.version.number}.jar`, - true, - 'version-jar', - ); - writeFileSync( - join(this.options.directory, `${this.options.version.number}.json`), - JSON.stringify(this.version, null, 4), - ); - return this.client.emit('debug', '[MCLC]: Downloaded version jar and wrote version json'); - } - - async getAssets() { - const assetDirectory = _resolve(this.options.overrides.assetRoot || join(this.options.root, 'assets')); - const assetId = this.options.version.custom || this.options.version.number; - if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) { - await this.downloadAsync( - this.version.assetIndex.url, - join(assetDirectory, 'indexes'), - `${assetId}.json`, - true, - 'asset-json', - ); - } - - const index = JSON.parse( - readFileSync(join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' }), - ); - - this.client.emit('progress', { - type: 'assets', - task: 0, - total: Object.keys(index.objects).length, - }); - - await Promise.all( - Object.keys(index.objects).map(async (asset) => { - const hash = index.objects[asset].hash; - const subhash = hash.substring(0, 2); - const subAsset = join(assetDirectory, 'objects', subhash); - - if (!existsSync(join(subAsset, hash)) || !(await this.checkSum(hash, join(subAsset, hash)))) { - await this.downloadAsync( - `${this.options.overrides.url.resource}/${subhash}/${hash}`, - subAsset, - hash, - true, - 'assets', - ); - } - counter++; - this.client.emit('progress', { - type: 'assets', - task: counter, - total: Object.keys(index.objects).length, - }); - }), - ); - counter = 0; - - // Copy assets to legacy if it's an older Minecraft version. - if (this.isLegacy()) { - if (existsSync(join(assetDirectory, 'legacy'))) { - this.client.emit( - 'debug', - "[MCLC]: The 'legacy' directory is no longer used as Minecraft looks " + - "for the resouces folder regardless of what is passed in the assetDirecotry launch option. I'd " + - `recommend removing the directory (${join(assetDirectory, 'legacy')})`, - ); - } - - const legacyDirectory = join(this.options.root, 'resources'); - this.client.emit('debug', `[MCLC]: Copying assets over to ${legacyDirectory}`); - - this.client.emit('progress', { - type: 'assets-copy', - task: 0, - total: Object.keys(index.objects).length, - }); - - await Promise.all( - Object.keys(index.objects).map(async (asset) => { - const hash = index.objects[asset].hash; - const subhash = hash.substring(0, 2); - const subAsset = join(assetDirectory, 'objects', subhash); - - const legacyAsset = asset.split('/'); - legacyAsset.pop(); - - if (!existsSync(join(legacyDirectory, legacyAsset.join('/')))) { - mkdirSync(join(legacyDirectory, legacyAsset.join('/')), { recursive: true }); - } - - if (!existsSync(join(legacyDirectory, asset))) { - copyFileSync(join(subAsset, hash), join(legacyDirectory, asset)); - } - counter++; - this.client.emit('progress', { - type: 'assets-copy', - task: counter, - total: Object.keys(index.objects).length, - }); - }), - ); - } - counter = 0; - - this.client.emit('debug', '[MCLC]: Downloaded assets'); - } - - parseRule(lib) { - if (lib.rules) { - if (lib.rules.length > 1) { - if ( - lib.rules[0].action === 'allow' && - lib.rules[1].action === 'disallow' && - lib.rules[1].os.name === 'osx' - ) { - return this.getOS() === 'osx'; - } - return true; - } else { - if (lib.rules[0].action === 'allow' && lib.rules[0].os) return lib.rules[0].os.name !== this.getOS(); - } - } else { - return false; - } - } - - async getNatives() { - const nativeDirectory = _resolve( - this.options.overrides.natives || join(this.options.root, 'natives', this.version.id), - ); - - if (parseInt(this.version.id.split('.')[1]) >= 19) return this.options.overrides.cwd || this.options.root; - - if (!existsSync(nativeDirectory) || !readdirSync(nativeDirectory).length) { - mkdirSync(nativeDirectory, { recursive: true }); - - const natives = async () => { - const natives = []; - await Promise.all( - this.version.libraries.map(async (lib) => { - if (!lib.downloads || !lib.downloads.classifiers) return; - if (this.parseRule(lib)) return; - - const native = - this.getOS() === 'osx' - ? lib.downloads.classifiers['natives-osx'] || lib.downloads.classifiers['natives-macos'] - : lib.downloads.classifiers[`natives-${this.getOS()}`]; - - natives.push(native); - }), - ); - return natives; - }; - const stat = await natives(); - - this.client.emit('progress', { - type: 'natives', - task: 0, - total: stat.length, - }); - - await Promise.all( - stat.map(async (native) => { - if (!native) return; - const name = native.path.split('/').pop(); - await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); - if (!(await this.checkSum(native.sha1, join(nativeDirectory, name)))) { - await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); - } - try { - new Zip(join(nativeDirectory, name)).extractAllTo(nativeDirectory, true); - } catch (e) { - // Only doing a console.warn since a stupid error happens. You can basically ignore this. - // if it says Invalid file name, just means two files were downloaded and both were deleted. - // All is well. - console.warn(e); - } - unlinkSync(join(nativeDirectory, name)); - counter++; - this.client.emit('progress', { - type: 'natives', - task: counter, - total: stat.length, - }); - }), - ); - this.client.emit('debug', '[MCLC]: Downloaded and extracted natives'); - } - - counter = 0; - this.client.emit('debug', `[MCLC]: Set native path to ${nativeDirectory}`); - - return nativeDirectory; - } - - fwAddArgs() { - const forgeWrapperAgrs = [ - `-Dforgewrapper.librariesDir=${_resolve(this.options.overrides.libraryRoot || join(this.options.root, 'libraries'))}`, - `-Dforgewrapper.installer=${this.options.forge}`, - `-Dforgewrapper.minecraft=${this.options.mcPath}`, - ]; - this.options.customArgs - ? (this.options.customArgs = this.options.customArgs.concat(forgeWrapperAgrs)) - : (this.options.customArgs = forgeWrapperAgrs); - } - - isModernForge(json) { - return ( - json.inheritsFrom && - json.inheritsFrom.split('.')[1] >= 12 && - !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') - ); - } - - async getForgedWrapped() { - let json = null; - let installerJson = null; - const versionPath = join(this.options.root, 'forge', `${this.version.id}`, 'version.json'); - // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not - // be re-generated on the next run. - if (existsSync(versionPath)) { - try { - json = JSON.parse(readFileSync(versionPath)); - if (!json.forgeWrapperVersion || !(json.forgeWrapperVersion === this.options.overrides.fw.version)) { - this.client.emit( - 'debug', - '[MCLC]: Old ForgeWrapper has generated this version JSON, re-generating', - ); - } else { - // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. - if (this.isModernForge(json)) { - this.fwAddArgs(); - this.options.forge = null; - } - return json; - } - } catch (e) { - console.warn(e); - this.client.emit('debug', '[MCLC]: Failed to parse Forge version JSON, re-generating'); - } - } - - this.client.emit('debug', '[MCLC]: Generating Forge version json, this might take a bit'); - const zipFile = new Zip(this.options.forge); - json = zipFile.readAsText('version.json'); - if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); - - try { - json = JSON.parse(json); - if (installerJson) installerJson = JSON.parse(installerJson); - } catch (e) { - this.client.emit('debug', '[MCLC]: Failed to load json files for ForgeWrapper, using Vanilla instead'); - return null; - } - // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. - if (installerJson) { - json.mavenFiles - ? (json.mavenFiles = json.mavenFiles.concat(installerJson.libraries)) - : (json.mavenFiles = installerJson.libraries); - } - - // Holder for the specifc jar ending which depends on the specifc forge version. - let jarEnding = 'universal'; - // We need to handle modern forge differently than legacy. - if (this.isModernForge(json)) { - // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. - if (json.inheritsFrom !== '1.12.2') { - this.fwAddArgs(); - const fwName = `ForgeWrapper-${this.options.overrides.fw.version}.jar`; - const fwPathArr = ['io', 'github', 'zekerzhayard', 'ForgeWrapper', this.options.overrides.fw.version]; - json.libraries.push({ - name: fwPathArr.join(':'), - downloads: { - artifact: { - path: [...fwPathArr, fwName].join('/'), - url: `${this.options.overrides.fw.baseUrl}${this.options.overrides.fw.version}/${fwName}`, - sha1: this.options.overrides.fw.sh1, - size: this.options.overrides.fw.size, - }, - }, - }); - json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main'; - jarEnding = 'launcher'; - - // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. - for (const library of json.mavenFiles) { - const lib = library.name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - library.downloads.artifact.url = - this.options.overrides.url.mavenForge + library.downloads.artifact.path; - break; - } - } - } else { - // Remove the forge dependent since we're going to overwrite the first entry anyways. - for (const library in json.mavenFiles) { - const lib = json.mavenFiles[library].name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - delete json.mavenFiles[library]; - break; - } - } - } - } else { - // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. - await Promise.all( - json.libraries.map(async (library) => { - const lib = library.name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; - - let url = this.options.overrides.url.mavenForge; - const name = `${lib[1]}-${lib[2]}.jar`; - - if (!library.url) { - if (library.serverreq || library.clientreq) { - url = this.options.overrides.url.defaultRepoForge; - } else { - return; - } - } - library.url = url; - const downloadLink = `${url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; - // Checking if the file still exists on Forge's server, if not, replace it with the fallback. - // Not checking for sucess, only if it 404s. - try { - const response = await axios.head(downloadLink); - if (response.status === 404) library.url = this.options.overrides.url.fallbackMaven; - } catch (error) { - this.client.emit('debug', `[MCLC]: Failed checking request for ${downloadLink}`); - } - }), - ); - } - // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. - // If it doesn't, we simply remove it since we're already providing the universal jar. - if (json.libraries[0].downloads) { - const name = json.libraries[0].name; - if (name.includes('minecraftforge:forge') && !name.includes('universal')) { - json.libraries[0].name = name + `:${jarEnding}`; - json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.path.replace( - '.jar', - `-${jarEnding}.jar`, - ); - json.libraries[0].downloads.artifact.url = - this.options.overrides.url.mavenForge + json.libraries[0].downloads.artifact.path; - } - } else { - delete json.libraries[0]; - } - - // Removing duplicates and null types - json.libraries = this.cleanUp(json.libraries); - if (json.mavenFiles) json.mavenFiles = this.cleanUp(json.mavenFiles); - - json.forgeWrapperVersion = this.options.overrides.fw.version; - - // Saving file for next run! - if (!existsSync(join(this.options.root, 'forge', this.version.id))) { - mkdirSync(join(this.options.root, 'forge', this.version.id), { recursive: true }); - } - writeFileSync(versionPath, JSON.stringify(json, null, 4)); - - // Make MCLC treat modern forge as a custom version json rather then legacy forge. - if (this.isModernForge(json)) this.options.forge = null; - - return json; - } - - async downloadToDirectory(directory, libraries, eventName) { - const libs = []; - - await Promise.all( - libraries.map(async (library) => { - if (!library) return; - if (this.parseRule(library)) return; - const lib = library.name.split(':'); - - let jarPath; - let name; - if (library.downloads && library.downloads.artifact && library.downloads.artifact.path) { - name = - library.downloads.artifact.path.split('/')[ - library.downloads.artifact.path.split('/').length - 1 - ]; - jarPath = join(directory, this.popString(library.downloads.artifact.path)); - } else { - name = `${lib[1]}-${lib[2]}${lib[3] ? '-' + lib[3] : ''}.jar`; - jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); - } - - const downloadLibrary = async (library) => { - if (library.url) { - const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; - await this.downloadAsync(url, jarPath, name, true, eventName); - } else if (library.downloads && library.downloads.artifact && library.downloads.artifact.url) { - // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. - await this.downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); - } - }; - - if (!existsSync(join(jarPath, name))) await downloadLibrary(library); - if (library.downloads && library.downloads.artifact) { - if (!this.checkSum(library.downloads.artifact.sha1, join(jarPath, name))) - await downloadLibrary(library); - } - - counter++; - this.client.emit('progress', { - type: eventName, - task: counter, - total: libraries.length, - }); - libs.push(`${jarPath}${sep}${name}`); - }), - ); - counter = 0; - - return libs; - } - - async getClasses(classJson) { - let libs = []; - - const libraryDirectory = _resolve(this.options.overrides.libraryRoot || join(this.options.root, 'libraries')); - - if (classJson) { - if (classJson.mavenFiles) { - await this.downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom'); - } - libs = await this.downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom'); - } - - const parsed = this.version.libraries.map((lib) => { - if (lib.downloads && lib.downloads.artifact && !this.parseRule(lib)) return lib; - }); - - libs = libs.concat(await this.downloadToDirectory(libraryDirectory, parsed, 'classes')); - counter = 0; - - // Temp Quilt support - if (classJson) libs.sort(); - - this.client.emit('debug', '[MCLC]: Collected class paths'); - return libs; - } - - popString(path) { - return path.split('/').slice(0, -1).join('/'); - } - - cleanUp(array) { - return [...new Set(Object.values(array).filter((value) => value !== null))]; - } - - formatQuickPlay() { - const types = { - singleplayer: '--quickPlaySingleplayer', - multiplayer: '--quickPlayMultiplayer', - realms: '--quickPlayRealms', - legacy: null, - }; - const { type, identifier, path } = this.options.quickPlay; - const keys = Object.keys(types); - if (!keys.includes(type)) { - this.client.emit('debug', `[MCLC]: quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); - return null; - } - const returnArgs = - type === 'legacy' - ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] - : [types[type], identifier]; - if (path) returnArgs.push('--quickPlayPath', path); - return returnArgs; - } - - async getLaunchOptions(modification) { - const type = Object.assign({}, this.version, modification); - - let args = type.minecraftArguments ? type.minecraftArguments.split(' ') : type.arguments.game; - const assetRoot = _resolve(this.options.overrides.assetRoot || join(this.options.root, 'assets')); - const assetPath = this.isLegacy() ? join(this.options.root, 'resources') : join(assetRoot); - - const minArgs = this.options.overrides.minArgs || this.isLegacy() ? 5 : 11; - if (args.length < minArgs) - args = args.concat( - this.version.minecraftArguments - ? this.version.minecraftArguments.split(' ') - : this.version.arguments.game, - ); - if (this.options.customLaunchArgs) args = args.concat(this.options.customLaunchArgs); - - this.options.authorization = await Promise.resolve(this.options.authorization); - this.options.authorization.meta = this.options.authorization.meta - ? this.options.authorization.meta - : { type: 'mojang' }; - const fields = { - '${auth_access_token}': this.options.authorization.access_token, - '${auth_session}': this.options.authorization.access_token, - '${auth_player_name}': this.options.authorization.name, - '${auth_uuid}': this.options.authorization.uuid, - '${auth_xuid}': this.options.authorization.meta.xuid || this.options.authorization.access_token, - '${user_properties}': this.options.authorization.user_properties, - '${user_type}': this.options.authorization.meta.type, - '${version_name}': this.options.version.number || this.options.overrides.versionName, - '${assets_index_name}': - this.options.overrides.assetIndex || this.options.version.custom || this.options.version.number, - '${game_directory}': this.options.overrides.gameDirectory || this.options.root, - '${assets_root}': assetPath, - '${game_assets}': assetPath, - '${version_type}': this.options.version.type, - '${clientid}': - this.options.authorization.meta.clientId || - this.options.authorization.client_token || - this.options.authorization.access_token, - '${resolution_width}': this.options.window ? this.options.window.width : 856, - '${resolution_height}': this.options.window ? this.options.window.height : 482, - }; - - if ( - this.options.authorization.meta.demo && - (this.options.features ? !this.options.features.includes('is_demo_user') : true) - ) { - args.push('--demo'); - } - - const replaceArg = (obj, index) => { - if (Array.isArray(obj.value)) { - for (const arg of obj.value) { - args.push(arg); - } - } else { - args.push(obj.value); - } - delete args[index]; - }; - - for (let index = 0; index < args.length; index++) { - if (typeof args[index] === 'object') { - if (args[index].rules) { - if (!this.options.features) continue; - const featureFlags = []; - for (const rule of args[index].rules) { - featureFlags.push(...Object.keys(rule.features)); - } - let hasAllRules = true; - for (const feature of this.options.features) { - if (!featureFlags.includes(feature)) { - hasAllRules = false; - } - } - if (hasAllRules) replaceArg(args[index], index); - } else { - replaceArg(args[index], index); - } - } else { - if (Object.keys(fields).includes(args[index])) { - args[index] = fields[args[index]]; - } - } - } - if (this.options.window) { - if (this.options.window.fullscreen) { - args.push('--fullscreen'); - } else { - if (this.options.window.width) args.push('--width', this.options.window.width); - if (this.options.window.height) args.push('--height', this.options.window.height); - } - } - if (this.options.server) - this.client.emit('debug', '[MCLC]: server and port are deprecated launch flags. Use the quickPlay field.'); - if (this.options.quickPlay) args = args.concat(this.formatQuickPlay()); - if (this.options.proxy) { - args.push( - '--proxyHost', - this.options.proxy.host, - '--proxyPort', - this.options.proxy.port || '8080', - '--proxyUser', - this.options.proxy.username, - '--proxyPass', - this.options.proxy.password, - ); - } - args = args.filter((value) => typeof value === 'string' || typeof value === 'number'); - this.client.emit('debug', '[MCLC]: Set launch options'); - return args; - } - - async getJVM() { - const opts = { - windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', - osx: '-XstartOnFirstThread', - linux: '-Xss1M', - }; - return opts[this.getOS()]; - } - - isLegacy() { - return this.version.assets === 'legacy' || this.version.assets === 'pre-1.6'; - } - - getOS() { - if (this.options.os) { - return this.options.os; - } else { - switch (process.platform) { - case 'win32': - return 'windows'; - case 'darwin': - return 'osx'; - default: - return 'linux'; - } - } - } - - // To prevent launchers from breaking when they update. Will be reworked with rewrite. - getMemory() { - if (!this.options.memory) { - this.client.emit('debug', '[MCLC]: Memory not set! Setting 1GB as MAX!'); - this.options.memory = { - min: 512, - max: 1023, - }; - } - if (!isNaN(this.options.memory.max) && !isNaN(this.options.memory.min)) { - if (this.options.memory.max < this.options.memory.min) { - this.client.emit('debug', '[MCLC]: MIN memory is higher then MAX! Resetting!'); - this.options.memory.max = 1023; - this.options.memory.min = 512; - } - return [`${this.options.memory.max}M`, `${this.options.memory.min}M`]; - } else { - return [`${this.options.memory.max}`, `${this.options.memory.min}`]; - } - } - - async extractPackage(options = this.options) { - if (options.clientPackage.startsWith('http')) { - await this.downloadAsync(options.clientPackage, options.root, 'clientPackage.zip', true, 'client-package'); - options.clientPackage = join(options.root, 'clientPackage.zip'); - } - new Zip(options.clientPackage).extractAllTo(options.root, true); - if (options.removePackage) unlinkSync(options.clientPackage); - - return this.client.emit('package-extract', true); - } - - checksumFile(filename, callback) { - _stat(filename, function (err, stat) { - if (!err && !stat.isFile()) err = new Error('Not a file'); - if (err) return callback(err); - - const hash = createHash('sha1'); - const fileStream = createReadStream(filename); - - if (!hash.write) { - fileStream.on('data', function (data) { - hash.update(data); - }); - - fileStream.on('end', function () { - callback(null, hash.digest('hex')); - }); - } else { - hash.setEncoding('hex'); - fileStream.pipe(hash, { end: false }); - - fileStream.on('end', function () { - hash.end(); - callback(null, hash.read()); - }); - } - }); - } -} - -export default Handler; diff --git a/src/handler.ts b/src/handler.ts new file mode 100644 index 0000000..95a1cd6 --- /dev/null +++ b/src/handler.ts @@ -0,0 +1,541 @@ +import { + copyFileSync, + createWriteStream, + existsSync, + mkdirSync, + readdirSync, + readFileSync, + unlinkSync, + writeFileSync, +} from 'fs'; +import { exec, ExecException } from 'node:child_process'; +import { Agent as http } from 'node:http'; +import { Agent as https } from 'node:https'; +import { resolve as _resolve, join, sep } from 'node:path'; +import Zip from 'adm-zip'; +import axios from 'axios'; +import { checksumFile, getOS, isLegacy, popString } from './utils'; +import { config, setConfig } from './utils/config'; +import { log } from './utils/log'; +import { artifactType, Fields, libType, Version } from './utils/types'; + +let counter = 0; +let parsedVersion: Version; + +const checkJava = ( + java: string, +): Promise<{ + run: boolean; + message?: ExecException; +}> => + new Promise((resolve) => { + exec(`"${java}" -version`, (error, _, stderr) => { + if (error) + return resolve({ + run: false, + message: error, + }); + + log( + 'debug', + `Using Java version ${stderr.match(/"(.*?)"/)?.pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`, + ); + resolve({ run: true }); + }); + }); + +const downloadAsync = async (url: string, directory: string, name: string, retry: boolean, type: string) => { + try { + mkdirSync(directory, { recursive: true }); + + const response = await axios.get(url, { + responseType: 'stream', + timeout: config.timeout || 50000, + httpAgent: new http({ keepAlive: true, maxSockets: config.maxSockets || 2 }), + httpsAgent: new https({ keepAlive: true, maxSockets: config.maxSockets || 2 }), + }); + + const totalBytes = parseInt(response.headers['content-length']); + let receivedBytes = 0; + + response.data.on('data', (data: Buffer | string) => { + typeof data === 'string' ? (receivedBytes += Buffer.byteLength(data)) : (receivedBytes += data.length); + + log('download-status', { + name: name, + type: type, + current: receivedBytes, + total: totalBytes, + }); + }); + + const file = createWriteStream(join(directory, name)); + response.data.pipe(file); + + await new Promise((resolve, reject) => { + file.on('finish', resolve); + file.on('error', reject); + }); + + log('download', name); + return { + failed: false, + asset: null, + }; + } catch (error) { + log('debug', `Failed to download asset to ${join(directory, name)} due\n${error}. Retrying... ${retry}`); + if (retry) await downloadAsync(url, directory, name, false, type); + return; + } +}; + +const checkSum = (hash: string, file: string) => + new Promise((resolve, reject) => { + checksumFile(file, (err, sum) => { + if (err) { + log('debug', `Failed to check file hash due to ${err}`); + return reject(); + } + + return resolve(hash === sum); + }); + }); + +const getVersion = async () => { + const versionJsonPath = config.versionJson || join(config.directory!, `${config.version.number}.json`); + if (existsSync(versionJsonPath)) { + parsedVersion = JSON.parse(readFileSync(versionJsonPath).toString()); + return parsedVersion; + } + + const manifest = `${config.url?.meta}/mc/game/version_manifest.json`; + const cache = config.cache ? `${config.cache}/json` : `${config.root}/cache/json`; + const { data } = await axios.get(manifest); + + if (!existsSync(cache)) { + mkdirSync(cache, { recursive: true }); + log('debug', 'Cache directory created.'); + } + + writeFileSync(join(cache, 'version_manifest.json'), JSON.stringify(data)); + log('debug', 'Cached version_manifest.json'); + + const desiredVersion = data.versions.find((version: { id: string }) => version.id === config.version.number); + if (desiredVersion) { + const { data } = await axios.get(desiredVersion.url); + writeFileSync(join(`${cache}/${config.version.number}.json`), JSON.stringify(data)); + log('debug', `Cached ${config.version.number}.json`); + + log('debug', 'Parsed version from version manifest'); + parsedVersion = data; + return parsedVersion; + } else { + throw Error(`Failed to find version ${config.version.number} in version_manifest.json`); + } +}; + +const getJar = async () => { + await downloadAsync( + parsedVersion.downloads.client.url, + config.directory!, + `${config.version.custom ? config.version.custom : config.version.number}.jar`, + true, + 'version-jar', + ); + writeFileSync(join(config.directory!, `${config.version.number}.json`), JSON.stringify(parsedVersion, null, 4)); + return log('debug', 'Downloaded version jar and wrote version json'); +}; + +const getAssets = async () => { + const assetDirectory = _resolve(config.assetRoot || join(config.root, 'assets')); + const assetId = config.version.custom || config.version.number; + + if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) { + await downloadAsync( + parsedVersion.assetIndex.url, + join(assetDirectory, 'indexes'), + `${assetId}.json`, + true, + 'asset-json', + ); + } + + const index = JSON.parse(readFileSync(join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' })); + + log('progress', { + type: 'assets', + task: 0, + total: Object.keys(index.objects).length, + }); + + await Promise.all( + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = join(assetDirectory, 'objects', subhash); + + if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) { + await downloadAsync(`${config.url?.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets'); + } + counter++; + log('progress', { + type: 'assets', + task: counter, + total: Object.keys(index.objects).length, + }); + }), + ); + counter = 0; + + // Copy assets to legacy if it's an older Minecraft version. + if (isLegacy(parsedVersion)) { + if (existsSync(join(assetDirectory, 'legacy'))) { + log( + 'debug', + "The 'legacy' directory is no longer used as Minecraft looks " + + "for the resouces folder regardless of what is passed in the assetDirecotry launch option. I'd " + + `recommend removing the directory (${join(assetDirectory, 'legacy')})`, + ); + } + + const legacyDirectory = join(config.root, 'resources'); + log('debug', `Copying assets over to ${legacyDirectory}`); + + log('progress', { + type: 'assets-copy', + task: 0, + total: Object.keys(index.objects).length, + }); + + await Promise.all( + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = join(assetDirectory, 'objects', subhash); + + const legacyAsset = asset.split('/'); + legacyAsset.pop(); + + if (!existsSync(join(legacyDirectory, legacyAsset.join('/')))) { + mkdirSync(join(legacyDirectory, legacyAsset.join('/')), { recursive: true }); + } + + if (!existsSync(join(legacyDirectory, asset))) { + copyFileSync(join(subAsset, hash), join(legacyDirectory, asset)); + } + counter++; + log('progress', { + type: 'assets-copy', + task: counter, + total: Object.keys(index.objects).length, + }); + }), + ); + } + counter = 0; + + log('debug', 'Downloaded assets'); +}; + +const parseRule = (lib: libType) => { + if (!lib.rules) return false; + if (lib.rules.length <= 1 && lib.rules[0].action === 'allow' && lib.rules[0].os) + return lib.rules[0].os.name !== getOS(); + if (lib.rules[0].action === 'allow' && lib.rules[1].action === 'disallow' && lib.rules[1].os.name === 'osx') + return getOS() === 'osx'; + + return true; +}; + +const getNatives = async () => { + const nativeDirectory = _resolve(config.natives || join(config.root, 'natives', parsedVersion.id)); + + if (parseInt(parsedVersion.id.split('.')[1]) >= 19) return config.root; + + if (!existsSync(nativeDirectory) || !readdirSync(nativeDirectory).length) { + mkdirSync(nativeDirectory, { recursive: true }); + + const natives = async () => { + const natives: artifactType[] = []; + await Promise.all( + parsedVersion.libraries.map(async (lib: libType) => { + if (!lib.downloads || !lib.downloads.classifiers) return; + if (parseRule(lib)) return; + + const native = + getOS() === 'osx' + ? lib.downloads.classifiers['natives-osx'] + ? (lib.downloads.classifiers['natives-osx'] as artifactType) + : (lib.downloads.classifiers['natives-macos'] as artifactType) + : (lib.downloads.classifiers[`natives-${getOS()}`] as artifactType); + + natives.push(native); + }), + ); + return natives; + }; + const stat = await natives(); + + log('progress', { + type: 'natives', + task: 0, + total: stat.length, + }); + + await Promise.all( + stat.map(async (native) => { + if (!native) return; + const name = native.path.split('/').pop()!; + await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); + if (!(await checkSum(native.sha1, join(nativeDirectory, name)))) { + await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); + } + try { + new Zip(join(nativeDirectory, name)).extractAllTo(nativeDirectory, true); + } catch (e) { + // Only doing a console.warn since a stupid error happens. You can basically ignore + // if it says Invalid file name, just means two files were downloaded and both were deleted. + // All is well. + console.warn(e); + } + unlinkSync(join(nativeDirectory, name)); + counter++; + log('progress', { + type: 'natives', + task: counter, + total: stat.length, + }); + }), + ); + log('debug', 'Downloaded and extracted natives'); + } + + counter = 0; + log('debug', `Set native path to ${nativeDirectory}`); + + return nativeDirectory; +}; + +const downloadToDirectory = async (directory: string, libraries: libType[], eventName: string) => { + const libs: string[] = []; + + await Promise.all( + libraries.map(async (library) => { + if (!library) return; + if (parseRule(library)) return; + const lib = library.name.split(':'); + + let jarPath: string; + let name: string; + if (library.downloads && library.downloads.artifact && library.downloads.artifact.path) { + name = + library.downloads.artifact.path.split('/')[library.downloads.artifact.path.split('/').length - 1]; + jarPath = join(directory, popString(library.downloads.artifact.path)); + } else { + name = `${lib[1]}-${lib[2]}${lib[3] ? '-' + lib[3] : ''}.jar`; + jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); + } + + const downloadLibrary = async (library: libType) => + await downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); + + if (!existsSync(join(jarPath, name))) await downloadLibrary(library); + if (library.downloads && library.downloads.artifact) + if (!checkSum(library.downloads.artifact.sha1, join(jarPath, name))) await downloadLibrary(library); + + counter++; + log('progress', { + type: eventName, + task: counter, + total: libraries.length, + }); + libs.push(`${jarPath}${sep}${name}`); + }), + ); + counter = 0; + + return libs; +}; + +const getClasses = async () => { + let libs: string[] = []; + + const libraryDirectory = _resolve(config.libraryRoot || join(config.root, 'libraries')); + + const parsed = parsedVersion.libraries + .filter((lib: libType | undefined) => lib !== undefined) + .map((lib: libType) => { + if (lib.downloads && lib.downloads.artifact && !parseRule(lib)) return lib; + }); + + libs = libs.concat(await downloadToDirectory(libraryDirectory, parsed as libType[], 'classes')); + counter = 0; + + log('debug', 'Collected class paths'); + return libs; +}; + +const formatQuickPlay = () => { + if (!config.quickPlay) return; + + const types = { + singleplayer: '--quickPlaySingleplayer', + multiplayer: '--quickPlayMultiplayer', + realms: '--quickPlayRealms', + legacy: null, + }; + const { type, identifier, path } = config.quickPlay; + const keys = Object.keys(types); + if (!keys.includes(type)) { + log('debug', `quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); + return null; + } + const returnArgs = + type === 'legacy' + ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] + : [types[type], identifier]; + if (path) returnArgs.push('--quickPlayPath', path); + return returnArgs; +}; + +const getLaunchOptions = async () => { + const type = Object.assign({}, parsedVersion); + + let args = type.minecraftArguments ? type.minecraftArguments.split(' ') : type.arguments.game; + const assetRoot = join(_resolve(config.assetRoot || join(config.root, 'assets'))); + const assetPath = isLegacy(parsedVersion) ? join(config.root, 'resources') : join(assetRoot); + + const minArgs = config.minArgs || isLegacy(parsedVersion) ? 5 : 11; + if (args.length < minArgs) + args = args.concat( + parsedVersion.minecraftArguments + ? parsedVersion.minecraftArguments.split(' ') + : parsedVersion.arguments.game, + ); + if (config.customLaunchArgs) args = args.concat(config.customLaunchArgs); + + config.authorization = await Promise.resolve(config.authorization); + config.authorization.meta = config.authorization.meta ? config.authorization.meta : { type: 'mojang' }; + const fields: Fields = { + '${auth_access_token}': config.authorization.access_token, + '${auth_session}': config.authorization.access_token, + '${auth_player_name}': config.authorization.name, + '${auth_uuid}': config.authorization.uuid, + '${auth_xuid}': config.authorization.access_token, + '${user_properties}': config.authorization.user_properties, + '${user_type}': config.authorization.meta.type, + '${version_name}': config.version.number || config.versionName, + '${assets_index_name}': config.assetIndex || config.version.custom || config.version.number, + '${game_directory}': config.gameDirectory || _resolve(config.root), + '${assets_root}': assetPath, + '${game_assets}': assetPath, + '${version_type}': config.version.type, + '${clientid}': config.authorization.client_token || config.authorization.access_token, + '${resolution_width}': config.window ? config.window.width : 856, + '${resolution_height}': config.window ? config.window.height : 482, + }; + + if (config.authorization.meta.demo && (config.features ? !config.features.includes('is_demo_user') : true)) + args.push('--demo'); + + const replaceArg = (obj: { value: string | string[] }, index: number) => { + if (!Array.isArray(obj.value)) { + for (const arg of obj.value) args.push(arg); + } else { + args.push(obj.value); + } + delete args[index]; + }; + + for (let index = 0; index < args.length; index++) { + if (typeof args[index] === 'object') { + if (args[index].rules) { + if (!config.features) continue; + const featureFlags = []; + for (const rule of args[index].rules) { + featureFlags.push(...Object.keys(rule.features)); + } + let hasAllRules = true; + for (const feature of config.features) { + if (!featureFlags.includes(feature)) { + hasAllRules = false; + } + } + if (hasAllRules) replaceArg(args[index], index); + } else { + replaceArg(args[index], index); + } + } else { + if (Object.keys(fields).includes(args[index] as keyof Fields)) + args[index] = fields[args[index] as keyof Fields]; + } + } + if (config.window) { + if (config.window.fullscreen) { + args.push('--fullscreen'); + } else { + if (config.window.width) args.push('--width', config.window.width); + if (config.window.height) args.push('--height', config.window.height); + } + } + if (config.quickPlay) args = args.concat(formatQuickPlay()); + if (config.proxy) { + args.push( + '--proxyHost', + config.proxy.host, + '--proxyPort', + config.proxy.port || '8080', + '--proxyUser', + config.proxy.username, + '--proxyPass', + config.proxy.password, + ); + } + args = args.filter((value: string | number) => typeof value === 'string' || typeof value === 'number'); + log('debug', 'Set launch options'); + return args; +}; + +const getJVM = async () => + ({ + windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', + osx: '-XstartOnFirstThread', + linux: '-Xss1M', + })[getOS()]; + +// To prevent launchers from breaking when they update. Will be reworked with rewrite. +const getMemory = () => { + if (typeof config.memory.min === 'number' && typeof config.memory.max === 'number') { + if (!isNaN(config.memory.max) && !isNaN(config.memory.min)) { + if (config.memory.max < config.memory.min) { + log('debug', 'MIN memory is higher then MAX! Resetting!'); + setConfig('memory', { min: Math.pow(2, 9), max: Math.pow(2, 10) }); + } + return [`${config.memory.max}M`, `${config.memory.min}M`]; + } + } else if (typeof config.memory.min === 'string' && typeof config.memory.max === 'string') { + return [`${config.memory.max}`, `${config.memory.min}`]; + } else { + log( + 'debug', + `MIN memory is a ${typeof config.memory.min} while MAX is ${typeof config.memory.max}! Resetting!`, + ); + setConfig('memory', { min: Math.pow(2, 9), max: Math.pow(2, 10) }); + return [`${config.memory.max}M`, `${config.memory.min}M`]; + } + + return [`${config.memory.max}M`, `${config.memory.min}M`]; +}; + +export { + checkJava, + downloadAsync, + getVersion, + getJar, + getAssets, + getNatives, + getClasses, + getLaunchOptions, + getJVM, + getMemory, +}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a3595c2 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,3 @@ +export * as Client from './launcher'; +export * as Authenticator from './authenticator'; +export { onLog } from './utils/log'; diff --git a/src/launcher.mjs b/src/launcher.mjs deleted file mode 100644 index 61a13d5..0000000 --- a/src/launcher.mjs +++ /dev/null @@ -1,215 +0,0 @@ -import { spawn } from 'node:child_process'; -import { EventEmitter } from 'node:events'; -import { existsSync, mkdirSync, readFileSync } from 'node:fs'; -import { join, resolve } from 'node:path'; -import Handler from './handler.mjs'; - -class MCLCore extends EventEmitter { - async launch(options) { - this.options = { ...options }; - this.options.root = resolve(this.options.root); - this.options.overrides = { - detached: true, - ...this.options.overrides, - url: { - meta: 'https://launchermeta.mojang.com', - resource: 'https://resources.download.minecraft.net', - mavenForge: 'https://files.minecraftforge.net/maven/', - defaultRepoForge: 'https://libraries.minecraft.net/', - fallbackMaven: 'https://search.maven.org/remotecontent?filepath=', - ...(this.options.overrides ? this.options.overrides.url : undefined), - }, - fw: { - baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', - version: '1.5.7', - sh1: '155ac9f4e5f65288eaacae19025ac4d9da1f0ef2', - size: 34910, - ...(this.options.overrides ? this.options.overrides.fw : undefined), - }, - }; - - this.handler = new Handler(this); - - this.emit('debug', `[MCLC]: MCLC version ${this.version()}`); - - const java = await this.handler.checkJava(this.options.javaPath || 'java'); - if (!java.run) { - this.emit('debug', `[MCLC]: Couldn't start Minecraft due to: ${java.message}`); - this.emit('close', 1); - return null; - } - - this.createRootDirectory(); - this.createGameDirectory(); - - await this.extractPackage(); - - const directory = - this.options.overrides.directory || - join( - this.options.root, - 'versions', - this.options.version.custom ? this.options.version.custom : this.options.version.number, - ); - this.options.directory = directory; - - const versionFile = await this.handler.getVersion(); - const mcPath = - this.options.overrides.minecraftJar || - (this.options.version.custom - ? join(this.options.root, 'versions', this.options.version.custom, `${this.options.version.custom}.jar`) - : join(directory, `${this.options.version.number}.jar`)); - this.options.mcPath = mcPath; - const nativePath = await this.handler.getNatives(); - - if (!existsSync(mcPath)) { - this.emit('debug', '[MCLC]: Attempting to download Minecraft version jar'); - await this.handler.getJar(); - } - - const modifyJson = await this.getModifyJson(); - - const args = []; - - let jvm = [ - '-XX:-UseAdaptiveSizePolicy', - '-XX:-OmitStackTraceInFastThrow', - '-Dfml.ignorePatchDiscrepancies=true', - '-Dfml.ignoreInvalidMinecraftCertificates=true', - `-Djava.library.path=${nativePath}`, - `-Xmx${this.handler.getMemory()[0]}`, - `-Xms${this.handler.getMemory()[1]}`, - ]; - if (this.handler.getOS() === 'osx') { - if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()); - } else jvm.push(await this.handler.getJVM()); - - if (this.options.customArgs) jvm = jvm.concat(this.options.customArgs); - if (this.options.overrides.logj4ConfigurationFile) { - jvm.push(`-Dlog4j.configurationFile=${resolve(this.options.overrides.logj4ConfigurationFile)}`); - } - // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition - if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) - jvm.push('-Dlog4j2.formatMsgNoLookups=true'); - if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); - if (parseInt(versionFile.id.split('.')[1]) < 17) { - if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { - const configPath = resolve(this.options.overrides.cwd || this.options.root); - const intVersion = parseInt(versionFile.id.split('.')[1]); - if (intVersion >= 12) { - await this.handler.downloadAsync( - 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', - configPath, - 'log4j2_112-116.xml', - true, - 'log4j', - ); - jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml'); - } else if (intVersion >= 7) { - await this.handler.downloadAsync( - 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', - configPath, - 'log4j2_17-111.xml', - true, - 'log4j', - ); - jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml'); - } - } - } - - const classes = - this.options.overrides.classes || this.handler.cleanUp(await this.handler.getClasses(modifyJson)); - const classPaths = ['-cp']; - const separator = this.handler.getOS() === 'windows' ? ';' : ':'; - this.emit('debug', `[MCLC]: Using ${separator} to separate class paths`); - // Handling launch arguments. - const file = modifyJson || versionFile; - // So mods like fabric work. - const jar = existsSync(mcPath) - ? `${separator}${mcPath}` - : `${separator}${join(directory, `${this.options.version.number}.jar`)}`; - classPaths.push(`${this.options.forge ? this.options.forge + separator : ''}${classes.join(separator)}${jar}`); - classPaths.push(file.mainClass); - - this.emit('debug', '[MCLC]: Attempting to download assets'); - await this.handler.getAssets(); - - // Forge -> Custom -> Vanilla - const launchOptions = await this.handler.getLaunchOptions(modifyJson); - - const launchArguments = args.concat(jvm, classPaths, launchOptions); - this.emit('arguments', launchArguments); - this.emit('debug', `[MCLC]: Launching with arguments ${launchArguments.join(' ')}`); - - return this.startMinecraft(launchArguments); - } - - createRootDirectory() { - if (!existsSync(this.options.root)) { - this.emit('debug', '[MCLC]: Attempting to create root folder'); - mkdirSync(this.options.root); - } - } - - createGameDirectory() { - if (this.options.overrides.gameDirectory) { - this.options.overrides.gameDirectory = resolve(this.options.overrides.gameDirectory); - if (!existsSync(this.options.overrides.gameDirectory)) { - mkdirSync(this.options.overrides.gameDirectory, { recursive: true }); - } - } - } - - async extractPackage() { - if (this.options.clientPackage) { - this.emit('debug', `[MCLC]: Extracting client package to ${this.options.root}`); - await this.handler.extractPackage(); - } - } - - async getModifyJson() { - let modifyJson = null; - - if (this.options.forge) { - this.options.forge = resolve(this.options.forge); - this.emit('debug', '[MCLC]: Detected Forge in options, getting dependencies'); - modifyJson = await this.handler.getForgedWrapped(); - } else if (this.options.version.custom) { - this.emit('debug', '[MCLC]: Detected custom in options, setting custom version file'); - modifyJson = - modifyJson || - JSON.parse( - readFileSync( - join( - this.options.root, - 'versions', - this.options.version.custom, - `${this.options.version.custom}.json`, - ), - { encoding: 'utf8' }, - ), - ); - } - - return modifyJson; - } - - startMinecraft(launchArguments) { - const minecraft = spawn(this.options.javaPath ? this.options.javaPath : 'java', launchArguments, { - cwd: this.options.overrides.cwd || this.options.root, - detached: this.options.overrides.detached, - }); - minecraft.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))); - minecraft.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))); - minecraft.on('close', (code) => this.emit('close', code)); - return minecraft; - } - - version() { - // Should be changed each update - return '3.18.0'; - } -} - -export default MCLCore; diff --git a/src/launcher.ts b/src/launcher.ts new file mode 100644 index 0000000..113a6a8 --- /dev/null +++ b/src/launcher.ts @@ -0,0 +1,139 @@ +import { spawn } from 'node:child_process'; +import { existsSync, mkdirSync } from 'node:fs'; +import { join, resolve } from 'node:path'; +import { + checkJava, + downloadAsync, + extractPackage, + getAssets, + getClasses, + getJar, + getJVM, + getLaunchOptions, + getMemory, + getNatives, + getVersion, +} from './handler'; +import { cleanUp, getOS } from './utils'; +import { config, setConfig } from './utils/config'; +import { log } from './utils/log'; + +// Should be changed each update +const version = '3.18.0'; + +export const launch = async () => { + log('debug', `MCLC version ${version}`); + + const java = await checkJava(config.javaPath || 'java'); + // if (!java || !java.run) { + if (!java) { + // log('debug', `Couldn't start Minecraft due to: ${java.message}`); + return log('close', 1); + } + + if (!existsSync(config.root)) { + log('debug', 'Attempting to create root folder'); + mkdirSync(config.root); + } + + if (config.gameDirectory) { + setConfig('gameDirectory', resolve(config.gameDirectory)); + if (!existsSync(config.gameDirectory)) mkdirSync(config.gameDirectory, { recursive: true }); + } + + const directory = + config.directory || + join(config.root, 'versions', config.version.custom ? config.version.custom : config.version.number); + setConfig('directory', directory); + + const versionFile = await getVersion(); + const mcPath = + config.minecraftJar || + (config.version.custom + ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) + : join(directory, `${config.version.number}.jar`)); + const nativePath = await getNatives(); + + if (!existsSync(mcPath)) { + log('debug', 'Attempting to download Minecraft version jar'); + await getJar(); + } + + const args: string[] = []; + + let jvm = [ + '-XX:-UseAdaptiveSizePolicy', + '-XX:-OmitStackTraceInFastThrow', + '-Dfml.ignorePatchDiscrepancies=true', + '-Dfml.ignoreInvalidMinecraftCertificates=true', + `-Djava.library.path=${nativePath}`, + `-Xmx${getMemory()[0]}`, + `-Xms${getMemory()[1]}`, + ]; + if (getOS() === 'osx') { + if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await getJVM()); + } else jvm.push(await getJVM()); + + if (config.customArgs) jvm = jvm.concat(config.customArgs); + if (config.logj4ConfigurationFile) { + jvm.push(`-Dlog4j.configurationFile=${resolve(config.logj4ConfigurationFile)}`); + } + // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition + if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) + jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) < 17) { + if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { + const configPath = resolve(config.root); + const intVersion = parseInt(versionFile.id.split('.')[1]); + if (intVersion >= 12) { + await downloadAsync( + 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', + configPath, + 'log4j2_112-116.xml', + true, + 'log4j', + ); + jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml'); + } else if (intVersion >= 7) { + await downloadAsync( + 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', + configPath, + 'log4j2_17-111.xml', + true, + 'log4j', + ); + jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml'); + } + } + } + + const classes = config.classes || cleanUp(await getClasses()); + const classPaths = ['-cp']; + const separator = getOS() === 'windows' ? ';' : ':'; + log('debug', `Using ${separator} to separate class paths`); + // Handling launch arguments. + // So mods like fabric work. + const jar = existsSync(mcPath) + ? `${separator}${mcPath}` + : `${separator}${join(directory, `${config.version.number}.jar`)}`; + classPaths.push(`${classes.join(separator)}${jar}`); + classPaths.push(versionFile.mainClass); + + log('debug', 'Attempting to download assets'); + await getAssets(); + + const launchconfig = await getLaunchOptions(); + + const launchArguments = args.concat(jvm, classPaths, launchconfig); + log('arguments', launchArguments); + log('debug', `Launching with arguments ${launchArguments.join(' ')}`); + + const minecraft = spawn(config.javaPath ? config.javaPath : 'java', launchArguments, { + detached: config.detached, + }); + minecraft.stdout.on('data', (data) => log('data', data.toString('utf-8'))); + minecraft.stderr.on('data', (data) => log('data', data.toString('utf-8'))); + minecraft.on('close', (code) => log('close', code)); + return minecraft; +}; diff --git a/src/utils/config.ts b/src/utils/config.ts new file mode 100644 index 0000000..0b7ec0d --- /dev/null +++ b/src/utils/config.ts @@ -0,0 +1,30 @@ +import { Options } from './types'; + +let config: Options = { + root: './minecraft', + authorization: { + access_token: 'e9df5bd1-28bb-31c6-8eb0-4ad41f47d874', + client_token: 'e9df5bd1-28bb-31c6-8eb0-4ad41f47d874', + uuid: 'e9df5bd1-28bb-31c6-8eb0-4ad41f47d874', + name: 'Steve', + user_properties: '{}', + }, + detached: true, + version: { + number: '1.7.10', + type: 'release', + }, + url: { + meta: 'https://launchermeta.mojang.com', + resource: 'https://resources.download.minecraft.net', + }, + memory: { + min: '2G', + max: '4G', + }, + maxSockets: 32, +}; + +const setConfig = (key: K, value: Options[K]) => (config[key] = value); + +export { config, setConfig }; diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..3ce39d1 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,45 @@ +import { createHash } from 'node:crypto'; +import { createReadStream, stat } from 'node:fs'; +import { resolve as _resolve } from 'node:path'; +import { config } from './config'; +import { Version } from './types'; + +const popString = (path: string) => path.split('/').slice(0, -1).join('/'); +const cleanUp = (array: string[]) => [...new Set(Object.values(array).filter((value) => value !== null))]; + +const getOS = () => { + if (config.os) { + return config.os; + } else { + switch (process.platform) { + case 'win32': + return 'windows'; + case 'darwin': + return 'osx'; + default: + return 'linux'; + } + } +}; + +const checksumFile = (filename: string, callback: (error: Error | null, hash?: string) => void) => { + stat(filename, (err, stat) => { + if (!err && !stat.isFile()) err = new Error('Not a file'); + if (err) return callback(err); + + const hash = createHash('sha1'); + const fileStream = createReadStream(filename); + + hash.setEncoding('hex'); + fileStream.pipe(hash, { end: false }); + + fileStream.on('end', function () { + hash.end(); + callback(null, hash.read()); + }); + }); +}; + +const isLegacy = (version: Version) => version.assets === 'legacy' || version.assets === 'pre-1.6'; + +export { popString, cleanUp, getOS, checksumFile, isLegacy }; diff --git a/src/utils/log.ts b/src/utils/log.ts new file mode 100644 index 0000000..30815ef --- /dev/null +++ b/src/utils/log.ts @@ -0,0 +1,15 @@ +import EventEmitter from 'events'; + +const eventEmitter = new EventEmitter(); + +const log = (type: string, message: any) => { + eventEmitter.emit(type, `[MCLC]: ${message}`); + return; +}; + +const onLog = (type: string, callback: (message: string) => void) => { + eventEmitter.on(type, callback); + return; +}; + +export { log, onLog }; diff --git a/src/utils/types.ts b/src/utils/types.ts new file mode 100644 index 0000000..3f775df --- /dev/null +++ b/src/utils/types.ts @@ -0,0 +1,266 @@ +export interface Options { + /** + * if true MCLC will remove the client package zip file after its finished extracting. + */ + removePackage?: boolean; + /** + * Path where you want the launcher to work in. + * This will usually be your .minecraft folder + */ + root: string; + /** + * OS override for minecraft natives + * + * @default will autodetect + */ + os?: 'windows' | 'osx' | 'linux'; + /** + * Array of custom Minecraft arguments. + */ + customLaunchArgs?: Array; + /** + * Array of custom Java arguments + */ + customArgs?: Array; + /** + * Array of game argument feature flags + */ + features?: Array; + /** + * minecraft version info + */ + version: { + /** + * Actual version. + * + * @example '1.16.4' + */ + number: string; + /** + * type of release, usually `release` or `snapshot` + */ + type: 'release' | 'snapshot' | string; + /** + * The name of the folder, jar file, and version json in the version folder. + * + * ` MCLC will look in the `versions` folder for this name + * @example '1.16.4-fabric' + */ + custom?: string; + }; + memory: { + /** + * Max amount of memory being used by Minecraft. + */ + min: string | number; + /** + * Min amount of memory being used by Minecraft. + */ + max: string | number; + }; + /** + * Path to the JRE executable file, will default to java if not entered. + */ + javaPath?: string; + proxy?: { + /** + * Host url to the proxy, don't include the port. + */ + host: string; + /** + * Username for the proxy. + * + * @default 8080 + */ + port?: string; + /** + * Username for the proxy. + */ + username?: string; + /** + * Password for the proxy. + */ + password?: string; + }; + /** + * Timeout on download requests. + */ + timeout?: number; + window?: { + /** + * Width of the Minecraft Client + */ + width?: number; + /** + * Height of the Minecraft Client + */ + height?: number; + /** + * Fullscreen the Minecraft Client. + */ + fullscreen?: boolean; + }; + + /** + * Allows the game to be launched directly into a world + */ + quickPlay?: { + /** + * The type of world you want to join. + * Note, that versions prior to 1.20 only support "legacy" + */ + type: 'singleplayer' | 'multiplayer' | 'realms' | 'legacy'; + /** + * Represents the world you want to join + * + * For singleplayer this should be the folder name of the world + * For multiplayer this should be the IP address of the server + * For realms this should be the Realms ID + * legacy follows multiplayer format + */ + identifier: string; + /** + * The specified path for logging (relative to the run directory) + */ + path?: string; + }; + /** + * The amount of launch arguments specified in the version file before it adds the default again + */ + minArgs?: number; + minecraftJar?: string; + versionJson?: string; + versionName?: string; + /** + * Folder, where the game process generates folders like saves and resource packs. + */ + gameDirectory?: string; + /** + * Folder, where the Minecraft jar and version json are located. + */ + directory?: string; + natives?: string; + assetRoot?: string; + assetIndex?: string; + libraryRoot?: string; + /** + * Whether or not the client is detached from the parent / launcher. + */ + detached?: boolean; + /** + * List of classes. + * All class paths are required if you use this. + */ + classes?: Array; + /** + * Max sockets for downloadAsync. + */ + maxSockets?: number; + /** + * Urls to the Minecraft resource servers + * + * This is for launcher developers located in countries that have the Minecraft resource servers + * blocked for what ever reason. They obviously need to mirror the formatting of the original JSONs / file structures. + */ + url?: { + /** + * List of versions. + */ + meta: string; + /** + * Minecraft resources. + */ + resource?: string; + }; + logj4ConfigurationFile?: string; + + authorization: Promise | User; + /** + * Path of json cache. + */ + cache?: string; +} + +export interface User { + access_token: string; + client_token: string; + uuid: string; + name: string; + user_properties: Partial | string; + meta?: { + type: 'mojang' | 'msa'; + demo?: boolean; + }; +} + +export type artifactType = { + path: string; + sha1: string; + size: number; + url: string; +}; + +export type libType = { + downloads: { + artifact: artifactType; + classifiers?: { + 'natives-linux'?: artifactType; + 'natives-osx'?: artifactType; + 'natives-macos'?: artifactType; + 'natives-windows'?: artifactType; + 'natives-windows-64'?: artifactType; + 'natives-windows-32'?: artifactType; + }; + }; + name: string; + rules?: { + action: 'allow' | 'disallow'; + os: { + name?: string; + }; + }[]; +}; + +export interface Version { + assetIndex: { + id: string; + sha1: string; + size: number; + totalSize: number; + url: string; + }; + assets: string; + complianceLevel: number; + downloads: { + client: { + sha1: string; + size: number; + url: string; + }; + }; + id: string; + libraries: libType[]; + minecraftArguments?: any; + arguments?: any; + type: string; + mainClass: string; +} + +export interface Fields { + '${auth_access_token}': string; + '${auth_session}': string; + '${auth_player_name}': string; + '${auth_uuid}': string; + '${auth_xuid}': string; + '${user_properties}': string | Partial; + '${user_type}': string; + '${version_name}'?: string; + '${assets_index_name}': string; + '${game_directory}': string; + '${assets_root}': string; + '${game_assets}': string; + '${version_type}': string; + '${clientid}': string; + '${resolution_width}'?: number; + '${resolution_height}'?: number; +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..28900b6 --- /dev/null +++ b/test.js @@ -0,0 +1,7 @@ +const { Client, onLog } = require('./build/cjs/index.js'); + +Client.launch(); + +onLog('debug', (e) => console.log(e)); +onLog('data', (e) => console.log(e)); +onLog('progress', (e) => console.log(e)); diff --git a/test.mjs b/test.mjs deleted file mode 100644 index 05dc0e6..0000000 --- a/test.mjs +++ /dev/null @@ -1,23 +0,0 @@ -import { Authenticator, Client } from './src/index.mjs'; - -const launcher = new Client(); - -launcher.launch({ - authorization: Authenticator.getAuth('username'), - root: './minecraft', - version: { - number: '1.7.10', - type: 'release', - }, - memory: { - max: '4G', - min: '2G', - }, - overrides: { - maxSockets: 32, - }, -}); - -launcher.on('debug', (e) => console.log(e)); -launcher.on('data', (e) => console.log(e)); -launcher.on('progress', (e) => console.log(e)); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..48cea65 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "allowJs": true, + "baseUrl": ".", + "outDir": "./build/cjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "incremental": true, + "isolatedModules": true, + "module": "CommonJS", + "moduleResolution": "node", + "noEmit": false, + "noImplicitAny": true, + "noImplicitThis": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "resolveJsonModule": true, + "strict": true, + "target": "ESNext", + "types": ["node"] + }, + "exclude": ["./build/"], + "include": ["./src/"] +} diff --git a/yarn.lock b/yarn.lock index b710218..988fb2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -315,11 +315,25 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@types/adm-zip@^0.5.5": + version "0.5.5" + resolved "https://registry.yarnpkg.com/@types/adm-zip/-/adm-zip-0.5.5.tgz#4588042726aa5f351d7ea88232e4a952f60e7c1a" + integrity sha512-YCGstVMjc4LTY5uK9/obvxBya93axZOVOyf2GSUulADzmLhYE45u2nAssCs/fWBs1Ifq5Vat75JTPwd5XZoPJw== + dependencies: + "@types/node" "*" + "@types/json-schema@^7.0.12": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== +"@types/node@*": + version "20.11.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.21.tgz#ad67e65652f7be15686e2df87a38076a81c5e9c5" + integrity sha512-/ySDLGscFPNasfqStUuWWPfL78jompfIoVzLJPVVAHBh6rpG68+pI2Gk+fNLeI8/f1yPYL4s46EleVIc20F1Ow== + dependencies: + undici-types "~5.26.4" + "@types/node@^14.0.27": version "14.18.63" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b" @@ -330,6 +344,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== +"@types/uuid@^9.0.8": + version "9.0.8" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" + integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== + "@typescript-eslint/eslint-plugin@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz#22bb999a8d59893c0ea07923e8a21f9d985ad740" @@ -431,10 +450,10 @@ acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== -adm-zip@^0.4.13: - version "0.4.16" - resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.16.tgz#cf4c508fdffab02c269cbc7f471a875f05570365" - integrity sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg== +adm-zip@^0.5.10: + version "0.5.10" + resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.10.tgz#4a51d5ab544b1f5ce51e1b9043139b639afff45b" + integrity sha512-x0HvcHqVJNTPk/Bw8JbLWlWoo6Wwnsug0fnYYro1HBrjxZ3G7/AZk7Ahv8JwDe1uIcz8eBqvu86FuF1POiG7vQ== ajv@^6.12.4: version "6.12.6" @@ -1338,6 +1357,16 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +typescript@^5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + update-browserslist-db@^1.0.13: version "1.0.13" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4" From 273c0d258612b8a127bce5db3fbb7ddaacde3d7c Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Thu, 29 Feb 2024 18:04:44 +0300 Subject: [PATCH 12/97] 'config' is never reassigned --- src/utils/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/config.ts b/src/utils/config.ts index 0b7ec0d..deba876 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,6 +1,6 @@ import { Options } from './types'; -let config: Options = { +const config: Options = { root: './minecraft', authorization: { access_token: 'e9df5bd1-28bb-31c6-8eb0-4ad41f47d874', From 57232bc63e8261191a271adf96c12856c72c8c40 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Thu, 29 Feb 2024 18:16:28 +0300 Subject: [PATCH 13/97] Fix logging --- src/launcher.ts | 3 +-- src/utils/log.ts | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/launcher.ts b/src/launcher.ts index 113a6a8..ac6eac1 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -4,7 +4,6 @@ import { join, resolve } from 'node:path'; import { checkJava, downloadAsync, - extractPackage, getAssets, getClasses, getJar, @@ -134,6 +133,6 @@ export const launch = async () => { }); minecraft.stdout.on('data', (data) => log('data', data.toString('utf-8'))); minecraft.stderr.on('data', (data) => log('data', data.toString('utf-8'))); - minecraft.on('close', (code) => log('close', code)); + minecraft.on('close', (code) => code && log('close', code)); return minecraft; }; diff --git a/src/utils/log.ts b/src/utils/log.ts index 30815ef..e8c44c2 100644 --- a/src/utils/log.ts +++ b/src/utils/log.ts @@ -2,8 +2,11 @@ import EventEmitter from 'events'; const eventEmitter = new EventEmitter(); -const log = (type: string, message: any) => { - eventEmitter.emit(type, `[MCLC]: ${message}`); +const log = (type: string, message: string | number | Record) => { + let msg = message; + if (typeof message === 'object') msg = JSON.stringify(msg); + + eventEmitter.emit(type, `[MCLC]: ${msg}`); return; }; From c054a079f869992c5885c09ee28683d7a1c3d319 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Thu, 29 Feb 2024 18:30:31 +0300 Subject: [PATCH 14/97] Fixed some things about the memory --- src/handler.ts | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 95a1cd6..b6cea23 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -506,13 +506,11 @@ const getJVM = async () => // To prevent launchers from breaking when they update. Will be reworked with rewrite. const getMemory = () => { if (typeof config.memory.min === 'number' && typeof config.memory.max === 'number') { - if (!isNaN(config.memory.max) && !isNaN(config.memory.min)) { - if (config.memory.max < config.memory.min) { - log('debug', 'MIN memory is higher then MAX! Resetting!'); - setConfig('memory', { min: Math.pow(2, 9), max: Math.pow(2, 10) }); - } - return [`${config.memory.max}M`, `${config.memory.min}M`]; + if (config.memory.max < config.memory.min) { + log('debug', 'MIN memory is higher then MAX! Resetting!'); + setConfig('memory', { min: Math.pow(2, 9), max: Math.pow(2, 10) }); } + return [`${config.memory.max}M`, `${config.memory.min}M`]; } else if (typeof config.memory.min === 'string' && typeof config.memory.max === 'string') { return [`${config.memory.max}`, `${config.memory.min}`]; } else { @@ -523,8 +521,6 @@ const getMemory = () => { setConfig('memory', { min: Math.pow(2, 9), max: Math.pow(2, 10) }); return [`${config.memory.max}M`, `${config.memory.min}M`]; } - - return [`${config.memory.max}M`, `${config.memory.min}M`]; }; export { From 946e95d91a0984861efa9334acfabd33651f85f7 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Thu, 29 Feb 2024 18:37:37 +0300 Subject: [PATCH 15/97] Update handler.ts --- src/handler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/handler.ts b/src/handler.ts index b6cea23..d95c5a8 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -503,7 +503,6 @@ const getJVM = async () => linux: '-Xss1M', })[getOS()]; -// To prevent launchers from breaking when they update. Will be reworked with rewrite. const getMemory = () => { if (typeof config.memory.min === 'number' && typeof config.memory.max === 'number') { if (config.memory.max < config.memory.min) { From 86d1775c1110d008e4e0620e1b185dd7dd5a6327 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Thu, 29 Feb 2024 20:32:32 +0300 Subject: [PATCH 16/97] Unbundle launch to install and start --- src/launcher.ts | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/launcher.ts b/src/launcher.ts index ac6eac1..4854577 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -20,7 +20,13 @@ import { log } from './utils/log'; // Should be changed each update const version = '3.18.0'; -export const launch = async () => { +export const launch = () => { + throw Error( + 'This function is no longer used. In order to install Minecraft, use the install function. To start Minecraft, use the start function', + ); +}; + +export const install = async () => { log('debug', `MCLC version ${version}`); const java = await checkJava(config.javaPath || 'java'); @@ -45,19 +51,51 @@ export const launch = async () => { join(config.root, 'versions', config.version.custom ? config.version.custom : config.version.number); setConfig('directory', directory); - const versionFile = await getVersion(); + await getVersion(); const mcPath = config.minecraftJar || (config.version.custom ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) : join(directory, `${config.version.number}.jar`)); - const nativePath = await getNatives(); + await getNatives(); if (!existsSync(mcPath)) { log('debug', 'Attempting to download Minecraft version jar'); await getJar(); } + cleanUp(await getClasses()); + + log('debug', 'Attempting to download assets'); + await getAssets(); + + log('debug', `Successfully installed Minecraft ${config.version.number}`); + return; +}; + +export const start = async () => { + log('debug', `MCLC version ${version}`); + + const java = await checkJava(config.javaPath || 'java'); + // if (!java || !java.run) { + if (!java) { + // log('debug', `Couldn't start Minecraft due to: ${java.message}`); + return log('close', 1); + } + + const directory = + config.directory || + join(config.root, 'versions', config.version.custom ? config.version.custom : config.version.number); + setConfig('directory', directory); + + const versionFile = await getVersion(); + const mcPath = + config.minecraftJar || + (config.version.custom + ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) + : join(directory, `${config.version.number}.jar`)); + const nativePath = await getNatives(); + const args: string[] = []; let jvm = [ @@ -119,9 +157,6 @@ export const launch = async () => { classPaths.push(`${classes.join(separator)}${jar}`); classPaths.push(versionFile.mainClass); - log('debug', 'Attempting to download assets'); - await getAssets(); - const launchconfig = await getLaunchOptions(); const launchArguments = args.concat(jvm, classPaths, launchconfig); From 0db2b498fb11b6f8dc09bcd71ee5ec29e4a06f0e Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Thu, 29 Feb 2024 20:37:26 +0300 Subject: [PATCH 17/97] Fix having MC the MCLC prefix --- src/utils/log.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/log.ts b/src/utils/log.ts index e8c44c2..7b1cd3f 100644 --- a/src/utils/log.ts +++ b/src/utils/log.ts @@ -6,7 +6,7 @@ const log = (type: string, message: string | number | Record) => { let msg = message; if (typeof message === 'object') msg = JSON.stringify(msg); - eventEmitter.emit(type, `[MCLC]: ${msg}`); + eventEmitter.emit(type, type !== 'data' ? `[MCLC]: ${msg}` : msg); return; }; From 72458b9b00aa02bccf5e240fa00db466a068c4c8 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Fri, 1 Mar 2024 22:14:36 +0300 Subject: [PATCH 18/97] Fix MC not properly downloading natives on Windows --- src/handler.ts | 10 +++++----- test.js | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index d95c5a8..3800c47 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -287,7 +287,8 @@ const getNatives = async () => { if (!native) return; const name = native.path.split('/').pop()!; await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); - if (!(await checkSum(native.sha1, join(nativeDirectory, name)))) { + const downloaded = await checkSum(native.sha1, join(nativeDirectory, name)); + if (!existsSync(join(nativeDirectory, name)) || !downloaded) { await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); } try { @@ -336,12 +337,11 @@ const downloadToDirectory = async (directory: string, libraries: libType[], even jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); } - const downloadLibrary = async (library: libType) => + if (!existsSync(join(jarPath, name))) await downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); - - if (!existsSync(join(jarPath, name))) await downloadLibrary(library); if (library.downloads && library.downloads.artifact) - if (!checkSum(library.downloads.artifact.sha1, join(jarPath, name))) await downloadLibrary(library); + if (!checkSum(library.downloads.artifact.sha1, join(jarPath, name))) + await downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); counter++; log('progress', { diff --git a/test.js b/test.js index 28900b6..6b3756f 100644 --- a/test.js +++ b/test.js @@ -1,6 +1,9 @@ const { Client, onLog } = require('./build/cjs/index.js'); -Client.launch(); +(async () => { + await Client.install(); + await Client.start(); +})(); onLog('debug', (e) => console.log(e)); onLog('data', (e) => console.log(e)); From f8cff872fba519e17c6fd64601ef10b21132a248 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Fri, 1 Mar 2024 22:42:23 +0300 Subject: [PATCH 19/97] Bring back java check --- src/launcher.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/launcher.ts b/src/launcher.ts index 4854577..b6675fb 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -77,9 +77,8 @@ export const start = async () => { log('debug', `MCLC version ${version}`); const java = await checkJava(config.javaPath || 'java'); - // if (!java || !java.run) { - if (!java) { - // log('debug', `Couldn't start Minecraft due to: ${java.message}`); + if (!java || !java.run) { + log('debug', `Couldn't start Minecraft due to: ${java.message}`); return log('close', 1); } From 84f6ceff2990b12b348a078c7fb3a6dade856196 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Fri, 1 Mar 2024 23:18:04 +0300 Subject: [PATCH 20/97] Uncomment this also --- src/launcher.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/launcher.ts b/src/launcher.ts index b6675fb..2e533af 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -30,9 +30,8 @@ export const install = async () => { log('debug', `MCLC version ${version}`); const java = await checkJava(config.javaPath || 'java'); - // if (!java || !java.run) { - if (!java) { - // log('debug', `Couldn't start Minecraft due to: ${java.message}`); + if (!java || !java.run) { + log('debug', `Couldn't start Minecraft due to: ${java.message}`); return log('close', 1); } From 70f518ca4480f9e18dddef993895d9207c3302b6 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 2 Mar 2024 00:46:47 +0300 Subject: [PATCH 21/97] [WIP] Forge installer --- package.json | 1 + src/index.ts | 1 + src/launcher.ts | 4 +- src/modLoader.ts | 53 ++++++++++++++++++++++ test.js | 17 +++---- yarn.lock | 113 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 src/modLoader.ts diff --git a/package.json b/package.json index 68dfd9b..e699792 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "adm-zip": "^0.5.10", "axios": "^1.6.7", + "cheerio": "^1.0.0-rc.12", "uuid": "^8.3.2" }, "devDependencies": { diff --git a/src/index.ts b/src/index.ts index a3595c2..6721513 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ export * as Client from './launcher'; export * as Authenticator from './authenticator'; export { onLog } from './utils/log'; +export { installForge } from './modLoader'; diff --git a/src/launcher.ts b/src/launcher.ts index 2e533af..9ea9a59 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -18,7 +18,7 @@ import { config, setConfig } from './utils/config'; import { log } from './utils/log'; // Should be changed each update -const version = '3.18.0'; +export const version = '3.18.0'; export const launch = () => { throw Error( @@ -31,7 +31,7 @@ export const install = async () => { const java = await checkJava(config.javaPath || 'java'); if (!java || !java.run) { - log('debug', `Couldn't start Minecraft due to: ${java.message}`); + log('debug', `Couldn't install Minecraft due to: ${java.message}`); return log('close', 1); } diff --git a/src/modLoader.ts b/src/modLoader.ts new file mode 100644 index 0000000..b9ac898 --- /dev/null +++ b/src/modLoader.ts @@ -0,0 +1,53 @@ +import axios from 'axios'; +import { load } from 'cheerio'; +import { checkJava } from './handler'; +import { version } from './launcher'; +import { config } from './utils/config'; +import { log } from './utils/log'; + +type Version = 'latest' | 'recommended' | string; + +export const installForge = async () => { + log('debug', `MCLC version ${version}`); + + const java = await checkJava(config.javaPath || 'java'); + if (!java || !java.run) { + log('debug', `Couldn't install Forge due to: ${java.message}`); + return log('close', 1); + } + + const toGet: Version = '14.23.5.2851'; // 14.23.4.2756 + + axios.get('https://files.minecraftforge.net/net/minecraftforge/forge/index_1.12.2.html').then(({ data }) => { + const $ = load(data); + const forgeVersions = $('tbody tr') + .map((_, row) => { + const $row = $(row); + const versions = $row.find('td.download-version').text().split(/\s+/).filter(Boolean); + const sha1 = $row.find('strong:contains("SHA1")').next().text().trim(); + + return versions.map((version) => ({ version, sha1 })); + }) + .toArray() + .flat(); + + console.log(forgeVersions); + + if (toGet === 'latest' || toGet === 'recommended') { + const description = $('meta[property="og:description"]') + .attr('content') + ?.match(/Latest:\s+(\d+\.\d+\.\d+\.\d+)\s+Recommended:\s+(\d+\.\d+\.\d+\.\d+)/); + + if (toGet === 'latest' && description) + return console.log(forgeVersions.find((o) => o.version === description[1])); + if (toGet === 'recommended' && description) + return console.log(forgeVersions.find((o) => o.version === description[2])); + + throw Error('nuh uh'); + } + + return console.log(forgeVersions.find((o) => o.version === toGet)); + }); + + return; +}; diff --git a/test.js b/test.js index 6b3756f..ad4d31c 100644 --- a/test.js +++ b/test.js @@ -1,10 +1,11 @@ -const { Client, onLog } = require('./build/cjs/index.js'); +const { installForge } = require('./build/cjs/index.js'); -(async () => { - await Client.install(); - await Client.start(); -})(); +// (async () => { +// await Client.install(); +// await Client.start(); +// })(); +installForge(); -onLog('debug', (e) => console.log(e)); -onLog('data', (e) => console.log(e)); -onLog('progress', (e) => console.log(e)); +// onLog('debug', (e) => console.log(e)); +// onLog('data', (e) => console.log(e)); +// onLog('progress', (e) => console.log(e)); diff --git a/yarn.lock b/yarn.lock index 988fb2e..18c9a5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -513,6 +513,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +boolbase@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -572,6 +577,31 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== + dependencies: + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@^1.0.0-rc.12: + version "1.0.0-rc.12" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -622,6 +652,22 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== + dependencies: + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" + +css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== + debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -653,11 +699,46 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" + +domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== + +domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== + dependencies: + domelementtype "^2.3.0" + +domutils@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" + integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + electron-to-chromium@^1.4.668: version "1.4.683" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.683.tgz#b68167ed66dbea01feb86915aca92c09bc1b651a" integrity sha512-FmopjiJjkUzqa5F5Sv+wxd8KimtCxyLFOFgRPwEeMLVmP+vHH/GjNGCuIYrCIchbMSiOe+nG/OPBbR/XoExBNA== +entities@^4.2.0, entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + escalade@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" @@ -939,6 +1020,16 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +htmlparser2@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" + integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + entities "^4.4.0" + ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -1129,6 +1220,13 @@ node-releases@^2.0.14: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== + dependencies: + boolbase "^1.0.0" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1169,6 +1267,21 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== + dependencies: + domhandler "^5.0.2" + parse5 "^7.0.0" + +parse5@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" From 73f6e0b024d37463ba01379221f95ae60b29d69d Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 4 Mar 2024 19:17:18 +0300 Subject: [PATCH 22/97] [WIP] Forge instlaler --- src/handler.ts | 33 ++++----- src/index.ts | 1 + src/launcher.ts | 8 +-- src/mclc.ts | 2 + src/modLoader.ts | 169 +++++++++++++++++++++++++++++++++++--------- src/utils/config.ts | 2 +- src/utils/index.ts | 30 ++++---- src/utils/log.ts | 4 +- test.js | 21 +++--- 9 files changed, 186 insertions(+), 84 deletions(-) create mode 100644 src/mclc.ts diff --git a/src/handler.ts b/src/handler.ts index 3800c47..615b8be 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -14,7 +14,7 @@ import { Agent as https } from 'node:https'; import { resolve as _resolve, join, sep } from 'node:path'; import Zip from 'adm-zip'; import axios from 'axios'; -import { checksumFile, getOS, isLegacy, popString } from './utils'; +import { checkSum, getOS, isLegacy, popString } from './utils'; import { config, setConfig } from './utils/config'; import { log } from './utils/log'; import { artifactType, Fields, libType, Version } from './utils/types'; @@ -51,8 +51,8 @@ const downloadAsync = async (url: string, directory: string, name: string, retry const response = await axios.get(url, { responseType: 'stream', timeout: config.timeout || 50000, - httpAgent: new http({ keepAlive: true, maxSockets: config.maxSockets || 2 }), - httpsAgent: new https({ keepAlive: true, maxSockets: config.maxSockets || 2 }), + httpAgent: new http({ maxSockets: config.maxSockets || 2 }), + httpsAgent: new https({ maxSockets: config.maxSockets || 2 }), }); const totalBytes = parseInt(response.headers['content-length']); @@ -72,9 +72,18 @@ const downloadAsync = async (url: string, directory: string, name: string, retry const file = createWriteStream(join(directory, name)); response.data.pipe(file); - await new Promise((resolve, reject) => { + await new Promise((resolve) => { file.on('finish', resolve); - file.on('error', reject); + file.on('error', async (e) => { + log( + 'debug', + `[MCLC]: Failed to download asset to ${join(directory, name)} due to\n${e}.` + + ` Retrying... ${retry}`, + ); + if (existsSync(join(directory, name))) unlinkSync(join(directory, name)); + if (retry) await downloadAsync(url, directory, name, false, type); + return resolve(e); + }); }); log('download', name); @@ -89,18 +98,6 @@ const downloadAsync = async (url: string, directory: string, name: string, retry } }; -const checkSum = (hash: string, file: string) => - new Promise((resolve, reject) => { - checksumFile(file, (err, sum) => { - if (err) { - log('debug', `Failed to check file hash due to ${err}`); - return reject(); - } - - return resolve(hash === sum); - }); - }); - const getVersion = async () => { const versionJsonPath = config.versionJson || join(config.directory!, `${config.version.number}.json`); if (existsSync(versionJsonPath)) { @@ -415,7 +412,7 @@ const getLaunchOptions = async () => { if (config.customLaunchArgs) args = args.concat(config.customLaunchArgs); config.authorization = await Promise.resolve(config.authorization); - config.authorization.meta = config.authorization.meta ? config.authorization.meta : { type: 'mojang' }; + config.authorization.meta = config.authorization.meta ?? { demo: false, type: 'mojang' }; const fields: Fields = { '${auth_access_token}': config.authorization.access_token, '${auth_session}': config.authorization.access_token, diff --git a/src/index.ts b/src/index.ts index 6721513..7553071 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ export * as Client from './launcher'; export * as Authenticator from './authenticator'; +export * as Config from './utils/config'; export { onLog } from './utils/log'; export { installForge } from './modLoader'; diff --git a/src/launcher.ts b/src/launcher.ts index 9ea9a59..a78c7bd 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -13,13 +13,11 @@ import { getNatives, getVersion, } from './handler'; +import mclc from './mclc'; import { cleanUp, getOS } from './utils'; import { config, setConfig } from './utils/config'; import { log } from './utils/log'; -// Should be changed each update -export const version = '3.18.0'; - export const launch = () => { throw Error( 'This function is no longer used. In order to install Minecraft, use the install function. To start Minecraft, use the start function', @@ -27,7 +25,7 @@ export const launch = () => { }; export const install = async () => { - log('debug', `MCLC version ${version}`); + log('version', `MCLC version ${mclc}`); const java = await checkJava(config.javaPath || 'java'); if (!java || !java.run) { @@ -73,7 +71,7 @@ export const install = async () => { }; export const start = async () => { - log('debug', `MCLC version ${version}`); + log('version', `MCLC version ${mclc}`); const java = await checkJava(config.javaPath || 'java'); if (!java || !java.run) { diff --git a/src/mclc.ts b/src/mclc.ts new file mode 100644 index 0000000..6e19b9f --- /dev/null +++ b/src/mclc.ts @@ -0,0 +1,2 @@ +// Should be changed each update +export default '3.18.0'; diff --git a/src/modLoader.ts b/src/modLoader.ts index b9ac898..6ade4ad 100644 --- a/src/modLoader.ts +++ b/src/modLoader.ts @@ -1,53 +1,152 @@ +import { spawn } from 'node:child_process'; +import { join, resolve } from 'node:path'; import axios from 'axios'; import { load } from 'cheerio'; -import { checkJava } from './handler'; -import { version } from './launcher'; +import { checkJava, downloadAsync } from './handler'; +import mclc from './mclc'; +import { checkSum } from './utils'; import { config } from './utils/config'; import { log } from './utils/log'; type Version = 'latest' | 'recommended' | string; -export const installForge = async () => { - log('debug', `MCLC version ${version}`); +export const getForgeVersion = async ( + versionToInstall: Version, +): Promise => { + // These versions do not have a changelog, so the installer is in the first place + const specialVersions = ['14.23.5.2855', '14.23.5.2854', '14.23.5.2852', '14.23.5.2851']; - const java = await checkJava(config.javaPath || 'java'); - if (!java || !java.run) { - log('debug', `Couldn't install Forge due to: ${java.message}`); - return log('close', 1); - } + return await axios + .get(`https://files.minecraftforge.net/net/minecraftforge/forge/index_${config.version.number}.html`) + .then(({ data }) => { + const $ = load(data); + const forgeVersions = $('tbody tr') + .map((_, row) => { + const $row = $(row); + const versions = $row.find('td.download-version').text().split(/\s+/).filter(Boolean); + const sha1 = $row + .find('div.info-tooltip:contains("SHA1")') + .text() + .trim() + .split('\n') + .filter((item) => item.includes('SHA1')) + .map((item) => item.split(': ')[1])[ + versionToInstall !== 'latest' && versionToInstall !== 'recommended' + ? specialVersions.includes(versionToInstall) + ? 0 + : 1 + : 1 + ]; + return versions.map((version) => ({ version, sha1 })); + }) + .toArray() + .flat(); + + if (versionToInstall === 'latest' || versionToInstall === 'recommended') { + const description = $('meta[property="og:description"]').attr('content'); + + if (!description) { + log('debug', 'Unable to receive latest/recommended version'); + return false; + } + + const latest = description.match(/Latest: (\d+\.\d+\.\d+)/); + const recommended = description.match(/Recommended: (\d+\.\d+\.\d+)/); + + if (versionToInstall === 'latest' && latest) { + const found = forgeVersions.find((o) => o.version === latest[1]); + if (!found) { + log('debug', `Latest version was not found`); + return false; + } + + return found; + } + if (versionToInstall === 'recommended' && recommended) { + const found = forgeVersions.find((o) => o.version === recommended[1]); + if (!found) { + log('debug', `Recommended version was not found`); + return false; + } - const toGet: Version = '14.23.5.2851'; // 14.23.4.2756 + return found; + } - axios.get('https://files.minecraftforge.net/net/minecraftforge/forge/index_1.12.2.html').then(({ data }) => { - const $ = load(data); - const forgeVersions = $('tbody tr') - .map((_, row) => { - const $row = $(row); - const versions = $row.find('td.download-version').text().split(/\s+/).filter(Boolean); - const sha1 = $row.find('strong:contains("SHA1")').next().text().trim(); + log('debug', `No ${versionToInstall} version found`); + return false; + } - return versions.map((version) => ({ version, sha1 })); - }) - .toArray() - .flat(); + const found = forgeVersions.find((o) => o.version === versionToInstall); + if (!found) { + log('debug', `Version ${versionToInstall} was not found`); + return false; + } - console.log(forgeVersions); + return found; + }) + .catch((error) => { + log('debug', `Couldn't access Forge's website due to: ${error}`); + return false; + }); +}; + +export const installForge = async (forgeVersion?: Version) => { + log('version', `MCLC version ${mclc}`); + + const acceptedVersions = [ + '1.20.4', + '1.20.3', + '1.20.2', + '1.20.1', + '1.20', + '1.19.4', + '1.19.3', + '1.19.2', + '1.19.1', + '1.19', + '1.18.2', + '1.18.1', + '1.18', + '1.17.1', + '1.16.5', + '1.16.4', + '1.16.3', + '1.16.2', + '1.16.1', + '1.15.2', + '1.15.1', + '1.15', + '1.14.4', + '1.14.3', + '1.14.2', + '1.13.2', + '1.12.2', + ]; + if (!acceptedVersions.includes(config.version.number)) { + log('debug', `Forge doesn't support Minecraft Version ${config.version.number}`); + return log('close', 1); + } - if (toGet === 'latest' || toGet === 'recommended') { - const description = $('meta[property="og:description"]') - .attr('content') - ?.match(/Latest:\s+(\d+\.\d+\.\d+\.\d+)\s+Recommended:\s+(\d+\.\d+\.\d+\.\d+)/); + const java = await checkJava(config.javaPath || 'java'); + if (!java || !java.run) { + log('debug', `Couldn't install Forge due to: ${java.message}`); + return log('close', 1); + } - if (toGet === 'latest' && description) - return console.log(forgeVersions.find((o) => o.version === description[1])); - if (toGet === 'recommended' && description) - return console.log(forgeVersions.find((o) => o.version === description[2])); + const version = await getForgeVersion(forgeVersion || 'recommended'); + if (!version) return log('close', 1); - throw Error('nuh uh'); - } + const url = `https://maven.minecraftforge.net/net/minecraftforge/forge/${config.version.number}-${version.version}/forge-${config.version.number}-${version.version}-installer.jar`; + const name = url.split('/').pop() as string; - return console.log(forgeVersions.find((o) => o.version === toGet)); - }); + await downloadAsync(url, resolve(config.root), name, true, 'forge'); + if (!(await checkSum(version.sha1, join(config.root, name)))) + await downloadAsync(url, resolve(config.root), name, true, 'forge'); - return; + const launchArguments = ['-jar', resolve(join(config.root, name)), '--installClient', resolve(config.root)]; + const minecraft = spawn(config.javaPath ? config.javaPath : 'java', launchArguments); + minecraft.stdout.on('data', (data) => log('data', data.toString('utf-8'))); + minecraft.stderr.on('data', (data) => log('data', data.toString('utf-8'))); + minecraft.on('close', (code) => code && log('close', code)); + return minecraft; }; diff --git a/src/utils/config.ts b/src/utils/config.ts index deba876..b7ffc59 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -22,7 +22,7 @@ const config: Options = { min: '2G', max: '4G', }, - maxSockets: 32, + maxSockets: Infinity, }; const setConfig = (key: K, value: Options[K]) => (config[key] = value); diff --git a/src/utils/index.ts b/src/utils/index.ts index 3ce39d1..31e83f5 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,6 +2,7 @@ import { createHash } from 'node:crypto'; import { createReadStream, stat } from 'node:fs'; import { resolve as _resolve } from 'node:path'; import { config } from './config'; +import { log } from './log'; import { Version } from './types'; const popString = (path: string) => path.split('/').slice(0, -1).join('/'); @@ -22,24 +23,27 @@ const getOS = () => { } }; -const checksumFile = (filename: string, callback: (error: Error | null, hash?: string) => void) => { - stat(filename, (err, stat) => { - if (!err && !stat.isFile()) err = new Error('Not a file'); - if (err) return callback(err); +const checkSum = (hash: string, file: string): Promise => + new Promise((resolve, reject) => { + stat(file, (err, stat) => { + if (err || !stat.isFile()) { + log('debug', `Failed to check file due to ${err}`); + return reject(err || new Error('Not a file')); + } - const hash = createHash('sha1'); - const fileStream = createReadStream(filename); + const hashStream = createHash('sha1'); + const fileStream = createReadStream(file); - hash.setEncoding('hex'); - fileStream.pipe(hash, { end: false }); + hashStream.setEncoding('hex'); + fileStream.pipe(hashStream, { end: false }); - fileStream.on('end', function () { - hash.end(); - callback(null, hash.read()); + fileStream.on('end', () => { + hashStream.end(); + resolve(hash === hashStream.read()); + }); }); }); -}; const isLegacy = (version: Version) => version.assets === 'legacy' || version.assets === 'pre-1.6'; -export { popString, cleanUp, getOS, checksumFile, isLegacy }; +export { popString, cleanUp, getOS, isLegacy, checkSum }; diff --git a/src/utils/log.ts b/src/utils/log.ts index 7b1cd3f..dc9e16c 100644 --- a/src/utils/log.ts +++ b/src/utils/log.ts @@ -3,9 +3,7 @@ import EventEmitter from 'events'; const eventEmitter = new EventEmitter(); const log = (type: string, message: string | number | Record) => { - let msg = message; - if (typeof message === 'object') msg = JSON.stringify(msg); - + const msg = typeof message === 'object' ? JSON.stringify(message) : message; eventEmitter.emit(type, type !== 'data' ? `[MCLC]: ${msg}` : msg); return; }; diff --git a/test.js b/test.js index ad4d31c..e679b76 100644 --- a/test.js +++ b/test.js @@ -1,11 +1,14 @@ -const { installForge } = require('./build/cjs/index.js'); +const { installForge, Config, onLog, Client } = require('./build/cjs/index.js'); -// (async () => { -// await Client.install(); -// await Client.start(); -// })(); -installForge(); +Config.setConfig('version', { number: '1.15.2', type: 'release' }); +// Config.setConfig('configPath', '/usr/lib/jvm/java-8-openjdk-amd64/bin/java'); -// onLog('debug', (e) => console.log(e)); -// onLog('data', (e) => console.log(e)); -// onLog('progress', (e) => console.log(e)); +(async () => { + await Client.install(); + await installForge(); + await Client.start(); +})(); + +onLog('debug', (e) => console.log(e)); +onLog('data', (e) => console.log(e)); +onLog('progress', (e) => console.log(e)); From d69c475c16252a4a8fc73e037c34f7b2282713f9 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 5 Mar 2024 19:18:33 +0300 Subject: [PATCH 23/97] Remove forge mod loader --- src/handler.ts | 2 +- src/index.ts | 1 - src/modLoader.ts | 152 ----------------------------------------------- test.js | 3 +- 4 files changed, 2 insertions(+), 156 deletions(-) delete mode 100644 src/modLoader.ts diff --git a/src/handler.ts b/src/handler.ts index 615b8be..7847089 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -135,7 +135,7 @@ const getJar = async () => { await downloadAsync( parsedVersion.downloads.client.url, config.directory!, - `${config.version.custom ? config.version.custom : config.version.number}.jar`, + `${config.version.custom ?? config.version.number}.jar`, true, 'version-jar', ); diff --git a/src/index.ts b/src/index.ts index 7553071..bdb5096 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,4 +2,3 @@ export * as Client from './launcher'; export * as Authenticator from './authenticator'; export * as Config from './utils/config'; export { onLog } from './utils/log'; -export { installForge } from './modLoader'; diff --git a/src/modLoader.ts b/src/modLoader.ts deleted file mode 100644 index 6ade4ad..0000000 --- a/src/modLoader.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { spawn } from 'node:child_process'; -import { join, resolve } from 'node:path'; -import axios from 'axios'; -import { load } from 'cheerio'; -import { checkJava, downloadAsync } from './handler'; -import mclc from './mclc'; -import { checkSum } from './utils'; -import { config } from './utils/config'; -import { log } from './utils/log'; - -type Version = 'latest' | 'recommended' | string; - -export const getForgeVersion = async ( - versionToInstall: Version, -): Promise => { - // These versions do not have a changelog, so the installer is in the first place - const specialVersions = ['14.23.5.2855', '14.23.5.2854', '14.23.5.2852', '14.23.5.2851']; - - return await axios - .get(`https://files.minecraftforge.net/net/minecraftforge/forge/index_${config.version.number}.html`) - .then(({ data }) => { - const $ = load(data); - const forgeVersions = $('tbody tr') - .map((_, row) => { - const $row = $(row); - const versions = $row.find('td.download-version').text().split(/\s+/).filter(Boolean); - const sha1 = $row - .find('div.info-tooltip:contains("SHA1")') - .text() - .trim() - .split('\n') - .filter((item) => item.includes('SHA1')) - .map((item) => item.split(': ')[1])[ - versionToInstall !== 'latest' && versionToInstall !== 'recommended' - ? specialVersions.includes(versionToInstall) - ? 0 - : 1 - : 1 - ]; - return versions.map((version) => ({ version, sha1 })); - }) - .toArray() - .flat(); - - if (versionToInstall === 'latest' || versionToInstall === 'recommended') { - const description = $('meta[property="og:description"]').attr('content'); - - if (!description) { - log('debug', 'Unable to receive latest/recommended version'); - return false; - } - - const latest = description.match(/Latest: (\d+\.\d+\.\d+)/); - const recommended = description.match(/Recommended: (\d+\.\d+\.\d+)/); - - if (versionToInstall === 'latest' && latest) { - const found = forgeVersions.find((o) => o.version === latest[1]); - if (!found) { - log('debug', `Latest version was not found`); - return false; - } - - return found; - } - if (versionToInstall === 'recommended' && recommended) { - const found = forgeVersions.find((o) => o.version === recommended[1]); - if (!found) { - log('debug', `Recommended version was not found`); - return false; - } - - return found; - } - - log('debug', `No ${versionToInstall} version found`); - return false; - } - - const found = forgeVersions.find((o) => o.version === versionToInstall); - if (!found) { - log('debug', `Version ${versionToInstall} was not found`); - return false; - } - - return found; - }) - .catch((error) => { - log('debug', `Couldn't access Forge's website due to: ${error}`); - return false; - }); -}; - -export const installForge = async (forgeVersion?: Version) => { - log('version', `MCLC version ${mclc}`); - - const acceptedVersions = [ - '1.20.4', - '1.20.3', - '1.20.2', - '1.20.1', - '1.20', - '1.19.4', - '1.19.3', - '1.19.2', - '1.19.1', - '1.19', - '1.18.2', - '1.18.1', - '1.18', - '1.17.1', - '1.16.5', - '1.16.4', - '1.16.3', - '1.16.2', - '1.16.1', - '1.15.2', - '1.15.1', - '1.15', - '1.14.4', - '1.14.3', - '1.14.2', - '1.13.2', - '1.12.2', - ]; - if (!acceptedVersions.includes(config.version.number)) { - log('debug', `Forge doesn't support Minecraft Version ${config.version.number}`); - return log('close', 1); - } - - const java = await checkJava(config.javaPath || 'java'); - if (!java || !java.run) { - log('debug', `Couldn't install Forge due to: ${java.message}`); - return log('close', 1); - } - - const version = await getForgeVersion(forgeVersion || 'recommended'); - if (!version) return log('close', 1); - - const url = `https://maven.minecraftforge.net/net/minecraftforge/forge/${config.version.number}-${version.version}/forge-${config.version.number}-${version.version}-installer.jar`; - const name = url.split('/').pop() as string; - - await downloadAsync(url, resolve(config.root), name, true, 'forge'); - if (!(await checkSum(version.sha1, join(config.root, name)))) - await downloadAsync(url, resolve(config.root), name, true, 'forge'); - - const launchArguments = ['-jar', resolve(join(config.root, name)), '--installClient', resolve(config.root)]; - const minecraft = spawn(config.javaPath ? config.javaPath : 'java', launchArguments); - minecraft.stdout.on('data', (data) => log('data', data.toString('utf-8'))); - minecraft.stderr.on('data', (data) => log('data', data.toString('utf-8'))); - minecraft.on('close', (code) => code && log('close', code)); - return minecraft; -}; diff --git a/test.js b/test.js index e679b76..6fd6506 100644 --- a/test.js +++ b/test.js @@ -1,11 +1,10 @@ -const { installForge, Config, onLog, Client } = require('./build/cjs/index.js'); +const { Config, onLog, Client } = require('./build/cjs/index.js'); Config.setConfig('version', { number: '1.15.2', type: 'release' }); // Config.setConfig('configPath', '/usr/lib/jvm/java-8-openjdk-amd64/bin/java'); (async () => { await Client.install(); - await installForge(); await Client.start(); })(); From c8bdb0e4422ee294114e2355f40ebc989bc70688 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 6 Mar 2024 20:59:05 +0300 Subject: [PATCH 24/97] Finish all mod loaders (except Neoforge) --- src/handler.ts | 261 ++++++++++++++++++++++++++++++++++++++++----- src/launcher.ts | 45 ++++++-- src/utils/types.ts | 24 +++++ test.js | 10 +- 4 files changed, 299 insertions(+), 41 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 7847089..43e49f6 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -11,13 +11,13 @@ import { import { exec, ExecException } from 'node:child_process'; import { Agent as http } from 'node:http'; import { Agent as https } from 'node:https'; -import { resolve as _resolve, join, sep } from 'node:path'; +import { join, resolve, sep } from 'node:path'; import Zip from 'adm-zip'; import axios from 'axios'; -import { checkSum, getOS, isLegacy, popString } from './utils'; +import { checkSum, cleanUp, getOS, isLegacy, popString } from './utils'; import { config, setConfig } from './utils/config'; import { log } from './utils/log'; -import { artifactType, Fields, libType, Version } from './utils/types'; +import { artifactType, customArtifactType, Fields, libType, Version } from './utils/types'; let counter = 0; let parsedVersion: Version; @@ -77,8 +77,7 @@ const downloadAsync = async (url: string, directory: string, name: string, retry file.on('error', async (e) => { log( 'debug', - `[MCLC]: Failed to download asset to ${join(directory, name)} due to\n${e}.` + - ` Retrying... ${retry}`, + `Failed to download asset to ${join(directory, name)} due to\n${e}.` + ` Retrying... ${retry}`, ); if (existsSync(join(directory, name))) unlinkSync(join(directory, name)); if (retry) await downloadAsync(url, directory, name, false, type); @@ -144,7 +143,7 @@ const getJar = async () => { }; const getAssets = async () => { - const assetDirectory = _resolve(config.assetRoot || join(config.root, 'assets')); + const assetDirectory = resolve(config.assetRoot || join(config.root, 'assets')); const assetId = config.version.custom || config.version.number; if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) { @@ -171,9 +170,8 @@ const getAssets = async () => { const subhash = hash.substring(0, 2); const subAsset = join(assetDirectory, 'objects', subhash); - if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) { + if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) await downloadAsync(`${config.url?.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets'); - } counter++; log('progress', { type: 'assets', @@ -245,7 +243,7 @@ const parseRule = (lib: libType) => { }; const getNatives = async () => { - const nativeDirectory = _resolve(config.natives || join(config.root, 'natives', parsedVersion.id)); + const nativeDirectory = resolve(config.natives || join(config.root, 'natives', parsedVersion.id)); if (parseInt(parsedVersion.id.split('.')[1]) >= 19) return config.root; @@ -285,9 +283,8 @@ const getNatives = async () => { const name = native.path.split('/').pop()!; await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); const downloaded = await checkSum(native.sha1, join(nativeDirectory, name)); - if (!existsSync(join(nativeDirectory, name)) || !downloaded) { + if (!existsSync(join(nativeDirectory, name)) || !downloaded) await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); - } try { new Zip(join(nativeDirectory, name)).extractAllTo(nativeDirectory, true); } catch (e) { @@ -314,18 +311,193 @@ const getNatives = async () => { return nativeDirectory; }; -const downloadToDirectory = async (directory: string, libraries: libType[], eventName: string) => { +const fwAddArgs = () => { + const forgeWrapperAgrs = [ + `-Dforgewrapper.librariesDir=${resolve(config.libraryRoot || join(config.root, 'libraries'))}`, + `-Dforgewrapper.installer=${config.forge}`, + `-Dforgewrapper.minecraft=${resolve(join(config.directory!, `${config.version.number}.jar`))}`, + ]; + config.customArgs + ? setConfig('customArgs', config.customArgs.concat(forgeWrapperAgrs)) + : setConfig('customArgs', forgeWrapperAgrs); + + return; +}; + +const getForgedWrapped = async () => { + let json = null; + let installerJson = null; + const versionPath = join(config.root, 'forge', `${parsedVersion.id}`, 'version.json'); + // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not + // be re-generated on the next run. + if (existsSync(versionPath)) { + try { + json = JSON.parse(readFileSync(versionPath).toString()); + if (!json.forgeWrapperVersion || !(json.forgeWrapperVersion === '1.6.0')) { + log('debug', 'Old ForgeWrapper has generated this version JSON, re-generating'); + } else { + // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. + if ( + json.inheritsFrom && + json.inheritsFrom.split('.')[1] >= 12 && + !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') + ) { + fwAddArgs(); + setConfig('forge', undefined); + } + return json; + } + } catch (e) { + console.warn(e); + log('debug', 'Failed to parse Forge version JSON, re-generating'); + } + } + + log('debug', 'Generating Forge version json, this might take a bit'); + const zipFile = new Zip(config.forge); + json = zipFile.readAsText('version.json'); + if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); + + try { + json = JSON.parse(json); + if (installerJson) installerJson = JSON.parse(installerJson); + } catch (e) { + log('debug', 'Failed to load json files for ForgeWrapper, using Vanilla instead'); + return null; + } + // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. + if (installerJson) { + json.mavenFiles + ? (json.mavenFiles = json.mavenFiles.concat(installerJson.libraries)) + : (json.mavenFiles = installerJson.libraries); + } + + // Holder for the specifc jar ending which depends on the specifc forge version. + let jarEnding = 'universal'; + // We need to handle modern forge differently than legacy. + if ( + json.inheritsFrom && + json.inheritsFrom.split('.')[1] >= 12 && + !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') + ) { + // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. + if (json.inheritsFrom !== '1.12.2') { + fwAddArgs(); + json.libraries.push({ + name: 'io:github:zekerzhayard:ForgeWrapper:1.6.0', + downloads: { + artifact: { + path: 'io/github/zekerzhayard/ForgeWrapper/1.6.0/ForgeWrapper-1.6.0.jar', + url: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/1.6.0/ForgeWrapper-1.6.0.jar', + sha1: '035a51fe6439792a61507630d89382f621da0f1f', + size: 28679, + }, + }, + }); + json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main'; + jarEnding = 'launcher'; + + // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. + for (const library of json.mavenFiles) { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { + library.downloads.artifact.url = + 'https://files.minecraftforge.net/maven/' + library.downloads.artifact.path; + break; + } + } + } else { + // Remove the forge dependent since we're going to overwrite the first entry anyways. + for (const library in json.mavenFiles) { + const lib = json.mavenFiles[library].name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { + delete json.mavenFiles[library]; + break; + } + } + } + } else { + // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. + await Promise.all( + json.libraries.map(async (library: any) => { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; + if (!library.url && !(library.serverreq || library.clientreq)) return; + + library.url = library.url + ? 'https://files.minecraftforge.net/maven/' + : 'https://libraries.minecraft.net/'; + const downloadLink = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${lib[1]}-${lib[2]}.jar`; + // Checking if the file still exists on Forge's server, if not, replace it with the fallback. + // Not checking for sucess, only if it 404s. + await axios + .get(downloadLink, { + timeout: config.timeout || 50000, + httpAgent: new http({ maxSockets: config.maxSockets || 2 }), + httpsAgent: new https({ maxSockets: config.maxSockets || 2 }), + }) + .then( + ({ status }) => + status === 404 && (library.url = 'https://search.maven.org/remotecontent?filepath='), + ) + .catch(() => log('debug', `Failed checking request for ${downloadLink}`)); + }), + ); + } + // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. + // If it doesn't, we simply remove it since we're already providing the universal jar. + if (json.libraries[0].downloads) { + const name = json.libraries[0].name; + if (name.includes('minecraftforge:forge') && !name.includes('universal')) { + json.libraries[0].name = name + `:${jarEnding}`; + json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.replace( + '.jar', + `-${jarEnding}.jar`, + ); + json.libraries[0].downloads.artifact.url = + 'https://files.minecraftforge.net/maven/' + json.libraries[0].downloads.artifact.path; + } + } else { + delete json.libraries[0]; + } + + // Removing duplicates and null types + json.libraries = cleanUp(json.libraries); + if (json.mavenFiles) json.mavenFiles = cleanUp(json.mavenFiles); + + // Saving file for next run! + if (!existsSync(join(config.root, 'forge', parsedVersion.id))) { + mkdirSync(join(config.root, 'forge', parsedVersion.id), { recursive: true }); + } + writeFileSync(versionPath, JSON.stringify(json, null, 4)); + + // Make MCLC treat modern forge as a custom version json rather then legacy forge. + if ( + json.inheritsFrom && + json.inheritsFrom.split('.')[1] >= 12 && + !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') + ) + setConfig('forge', undefined); + + return json; +}; + +const downloadToDirectory = async ( + directory: string, + libraries: libType[] | customArtifactType[], + eventName: string, +) => { const libs: string[] = []; await Promise.all( libraries.map(async (library) => { if (!library) return; - if (parseRule(library)) return; + if ('downloads' in library && parseRule(library)) return; const lib = library.name.split(':'); let jarPath: string; let name: string; - if (library.downloads && library.downloads.artifact && library.downloads.artifact.path) { + if ('downloads' in library && library.downloads.artifact && library.downloads.artifact.path) { name = library.downloads.artifact.path.split('/')[library.downloads.artifact.path.split('/').length - 1]; jarPath = join(directory, popString(library.downloads.artifact.path)); @@ -334,11 +506,19 @@ const downloadToDirectory = async (directory: string, libraries: libType[], even jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); } - if (!existsSync(join(jarPath, name))) - await downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); - if (library.downloads && library.downloads.artifact) - if (!checkSum(library.downloads.artifact.sha1, join(jarPath, name))) + const downloadLibrary = async (library: libType | customArtifactType) => { + if ('url' in library) { + const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; + await downloadAsync(url, jarPath, name, true, eventName); + } else if ('downloads' in library && library.downloads.artifact && library.downloads.artifact.url) { + // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. await downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); + } + }; + + if (!existsSync(join(jarPath, name))) await downloadLibrary(library); + if ('downloads' in library && library.downloads.artifact) + if (!checkSum(library.downloads.artifact.sha1, join(jarPath, name))) await downloadLibrary(library); counter++; log('progress', { @@ -354,20 +534,41 @@ const downloadToDirectory = async (directory: string, libraries: libType[], even return libs; }; -const getClasses = async () => { +// TODO: figure out the right type +const getClasses = async (classJson: { + id: string; + mainClass: string; + arguments: { + game: string[]; + jvm: string[]; + }; + mavenFiles?: any; + libraries: { + name: string; + url: string; + sha1?: string; + size?: number; + }[]; +}) => { let libs: string[] = []; - const libraryDirectory = _resolve(config.libraryRoot || join(config.root, 'libraries')); + const libraryDirectory = resolve(config.libraryRoot || join(config.root, 'libraries')); - const parsed = parsedVersion.libraries - .filter((lib: libType | undefined) => lib !== undefined) - .map((lib: libType) => { - if (lib.downloads && lib.downloads.artifact && !parseRule(lib)) return lib; - }); + if (classJson) { + if (classJson.mavenFiles) + await downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom'); + libs = await downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom'); + } + + const parsed = parsedVersion.libraries.filter(Boolean).map((lib: libType) => { + if (lib.downloads && lib.downloads.artifact && !parseRule(lib)) return lib; + }); libs = libs.concat(await downloadToDirectory(libraryDirectory, parsed as libType[], 'classes')); counter = 0; + if (classJson) libs.sort(); + log('debug', 'Collected class paths'); return libs; }; @@ -395,11 +596,12 @@ const formatQuickPlay = () => { return returnArgs; }; -const getLaunchOptions = async () => { - const type = Object.assign({}, parsedVersion); +// TODO: figure out the right type +const getLaunchOptions = async (modification: any) => { + const type = Object.assign({}, parsedVersion, modification); let args = type.minecraftArguments ? type.minecraftArguments.split(' ') : type.arguments.game; - const assetRoot = join(_resolve(config.assetRoot || join(config.root, 'assets'))); + const assetRoot = join(resolve(config.assetRoot || join(config.root, 'assets'))); const assetPath = isLegacy(parsedVersion) ? join(config.root, 'resources') : join(assetRoot); const minArgs = config.minArgs || isLegacy(parsedVersion) ? 5 : 11; @@ -423,7 +625,7 @@ const getLaunchOptions = async () => { '${user_type}': config.authorization.meta.type, '${version_name}': config.version.number || config.versionName, '${assets_index_name}': config.assetIndex || config.version.custom || config.version.number, - '${game_directory}': config.gameDirectory || _resolve(config.root), + '${game_directory}': config.gameDirectory || resolve(config.root), '${assets_root}': assetPath, '${game_assets}': assetPath, '${version_type}': config.version.type, @@ -526,6 +728,7 @@ export { getJar, getAssets, getNatives, + getForgedWrapped, getClasses, getLaunchOptions, getJVM, diff --git a/src/launcher.ts b/src/launcher.ts index a78c7bd..f6be630 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -1,11 +1,12 @@ import { spawn } from 'node:child_process'; -import { existsSync, mkdirSync } from 'node:fs'; +import { existsSync, mkdirSync, readFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; import { checkJava, downloadAsync, getAssets, getClasses, + getForgedWrapped, getJar, getJVM, getLaunchOptions, @@ -43,9 +44,7 @@ export const install = async () => { if (!existsSync(config.gameDirectory)) mkdirSync(config.gameDirectory, { recursive: true }); } - const directory = - config.directory || - join(config.root, 'versions', config.version.custom ? config.version.custom : config.version.number); + const directory = config.directory || join(config.root, 'versions', config.version.custom ?? config.version.number); setConfig('directory', directory); await getVersion(); @@ -61,7 +60,17 @@ export const install = async () => { await getJar(); } - cleanUp(await getClasses()); + let modifyJson = null; + if (config.version.custom) { + log('debug', 'Detected custom in options, setting custom version file'); + modifyJson = JSON.parse( + readFileSync(join(config.root, 'versions', config.version.custom, `${config.version.custom}.json`), { + encoding: 'utf8', + }), + ); + } + + cleanUp(await getClasses(modifyJson)); log('debug', 'Attempting to download assets'); await getAssets(); @@ -94,12 +103,26 @@ export const start = async () => { const args: string[] = []; + let modifyJson = null; + if (config.version.custom) { + log('debug', 'Detected custom in options, setting custom version file'); + modifyJson = JSON.parse( + readFileSync(join(config.root, 'versions', config.version.custom, `${config.version.custom}.json`), { + encoding: 'utf8', + }), + ); + } else if (config.forge) { + setConfig('forge', resolve(config.forge)); + log('debug', '[MCLC]: Detected Forge in options, getting dependencies'); + modifyJson = await getForgedWrapped(); + } + let jvm = [ '-XX:-UseAdaptiveSizePolicy', '-XX:-OmitStackTraceInFastThrow', '-Dfml.ignorePatchDiscrepancies=true', '-Dfml.ignoreInvalidMinecraftCertificates=true', - `-Djava.library.path=${nativePath}`, + `-Djava.library.path=${resolve(nativePath)}`, `-Xmx${getMemory()[0]}`, `-Xms${getMemory()[1]}`, ]; @@ -141,20 +164,20 @@ export const start = async () => { } } - const classes = config.classes || cleanUp(await getClasses()); + const classes = config.classes || cleanUp(await getClasses(modifyJson)); const classPaths = ['-cp']; const separator = getOS() === 'windows' ? ';' : ':'; log('debug', `Using ${separator} to separate class paths`); // Handling launch arguments. + const file = modifyJson || versionFile; // So mods like fabric work. const jar = existsSync(mcPath) ? `${separator}${mcPath}` : `${separator}${join(directory, `${config.version.number}.jar`)}`; - classPaths.push(`${classes.join(separator)}${jar}`); - classPaths.push(versionFile.mainClass); - - const launchconfig = await getLaunchOptions(); + classPaths.push(`${config.forge ? config.forge + separator : ''}${classes.join(separator)}${jar}`); + classPaths.push(file.mainClass); + const launchconfig = await getLaunchOptions(modifyJson); const launchArguments = args.concat(jvm, classPaths, launchconfig); log('arguments', launchArguments); log('debug', `Launching with arguments ${launchArguments.join(' ')}`); diff --git a/src/utils/types.ts b/src/utils/types.ts index 3f775df..f49c366 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -179,6 +179,12 @@ export interface Options { * Path of json cache. */ cache?: string; + /** + * Path to Forge Jar. + * + * Versions below 1.13 should be the "universal" jar while versions above 1.13+ should be the "installer" jar + */ + forge?: string; } export interface User { @@ -221,6 +227,24 @@ export type libType = { }[]; }; +export type customArtifactType = { + name: string; + url: string; + sha1?: string; + size?: number; +}; + +export type customLibType = { + id: string; + mainClass: string; + arguments: { + game: string[]; + jvm: string[]; + }; + mavenFiles?: any; + libraries: customArtifactType[]; +}; + export interface Version { assetIndex: { id: string; diff --git a/test.js b/test.js index 6fd6506..d74c445 100644 --- a/test.js +++ b/test.js @@ -1,9 +1,17 @@ +const { forge } = require('tomate-loaders'); const { Config, onLog, Client } = require('./build/cjs/index.js'); +const { join, dirname } = require('node:path'); +const { mkdirSync, writeFileSync } = require('node:fs'); -Config.setConfig('version', { number: '1.15.2', type: 'release' }); +Config.setConfig('version', { number: '1.19.4', type: 'release' }); // Config.setConfig('configPath', '/usr/lib/jvm/java-8-openjdk-amd64/bin/java'); (async () => { + const versionPath = join(Config.config.root, 'versions', `forge-1.19.4`, 'forge.jar'); + await forge.downloadForge(versionPath, '1.19.4'); + Config.setConfig('forge', versionPath); + + // console.log(Config.config); await Client.install(); await Client.start(); })(); From 2cd814253b8e14638ac4872ac060f542ba14a4bf Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Fri, 8 Mar 2024 12:41:12 +0300 Subject: [PATCH 25/97] Some outside of code changes --- .github/FUNDING.yml | 12 --- LICENSE | 2 +- README.md | 208 ++++++++++++++++---------------------------- imgs/header.png | Bin 0 -> 28978 bytes package.json | 55 ++++++------ 5 files changed, 104 insertions(+), 173 deletions(-) create mode 100644 imgs/header.png diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 7856ad2..f2bebfb 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,13 +1 @@ -# These are supported funding model platforms - github: Pierce01 -patreon: # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/LICENSE b/LICENSE index d97e37d..9059f3e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 Pierce Harriz +Copyright (c) 2024 Pierce Harriz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index f93a660..2d18942 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,112 @@ -![logo](https://owo.whats-th.is/8mT5kxc.png) +![Main Logo](/imgs/header.png) -##### Project rewrite coming soon™ - -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -![version](https://img.shields.io/badge/stable_version-3.18.0-blue) +[![MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +![Version](https://img.shields.io/badge/stable_version-3.18.0-blue) MCLC (Minecraft Launcher Core) is a NodeJS solution for launching modded and vanilla Minecraft without having to download and format everything yourself. Basically a core for your Electron or script based launchers. ### Getting support -I've created a Discord server for anyone who needs to get in contact with me or get help! +Do you need to get in contact with me or get help? Join my Discord Server -

- - chat on Discord -

+[![Discord](https://img.shields.io/discord/568550848871923723?logo=discord)](https://discord.gg/8uYVbXP) ### Installing -`npm i minecraft-launcher-core` +```bash +# npm +npm i minecraft-launcher-core + +# Yarn +yarn add minecraft-launcher-core + +# pnpm +pnpm add minecraft-launcher-core +``` -### Standard Example +### Example + +```js +import { Authenticator, Client } from 'minecraft-launcher-core'; -```javascript -const { Client, Authenticator } = require('minecraft-launcher-core'); const launcher = new Client(); +const options = { + // This will launch in offline mode, if you want + // to use a Microsoft Account, see details below + authorization: Authenticator.getAuth('Steve'), + root: './minecraft', + version: { + number: '1.14.4', + type: 'release', + }, + memory: { + max: '4G', + min: '2G', + }, +}; -let opts = { - // For production launchers, I recommend not passing - // the getAuth function through the authorization field and instead - // handling authentication outside before you initialize - // MCLC so you can handle auth based errors and validation! - authorization: Authenticator.getAuth('username', 'password'), +launcher.launch(options); + +launcher.on('debug', (e) => console.log(e)); +launcher.on('data', (e) => console.log(e)); +``` + +### Using a Microsoft Account + +In order to authenticate with a Microsoft Account, you would need to use [MSMC](https://github.com/Hanro50/MSMC). +Make sure to install it, as it doesn't come by default + +#### Example + +```js +import { Authenticator, Client } from 'minecraft-launcher-core'; +import { Auth } from 'msmc'; + +const authManager = new Auth('select_account'); +const xboxManager = await authManager.launch('raw'); // Can be 'electron' or 'nwjs' +const token = await xboxManager.getMinecraft(); + +const launcher = new Client(); +const options = { + authorization: token.mclc(), root: './minecraft', version: { - number: '1.14', + number: '1.14.4', type: 'release', }, memory: { - max: '6G', - min: '4G', + max: '4G', + min: '2G', }, }; -launcher.launch(opts); +launcher.launch(options); launcher.on('debug', (e) => console.log(e)); launcher.on('data', (e) => console.log(e)); ``` +### Having modded version + + + +MCLC by default only has Vanilla. In order to automate the process of installing [Forge](https://minecraftforge.net), [Fabric](https://fabricmc.net) and [Quilt](https://quiltmc.org) you would need to use lorem ipsum + ### Documentation #### Client Functions + + | Function | Type | Description | | -------- | ------- | ------------------------------------------------------------------------------------------ | | `launch` | Promise | Launches the client with the specified `options` as a parameter. Returns child the process | ##### launch + + | Parameter | Type | Description | Required | | ------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- | -------- | | `options.removePackage` | Boolean | Option to remove the client package zip file after its finished extracting. | False | @@ -90,117 +136,13 @@ launcher.on('data', (e) => console.log(e)); | `options.window.fullscreen` | Boolean | Fullscreen the Minecraft Client. | False | | `options.overrides` | Object | Json object redefining paths for better customization. Example below. | False | -#### IF YOU'RE NEW TO MCLC, LET IT HANDLE EVERYTHING! DO NOT USE OVERRIDES! - -```js -let opts = { - otherOps..., - overrides: { - gameDirectory: '', // where the game process generates folders like saves and resource packs. - minecraftJar: '', - versionName: '', // replaces the value after the version flag. - versionJson: '', - directory: '', // where the Minecraft jar and version json are located. - natives: '', // native directory path. - assetRoot: '', - assetIndex: '', - libraryRoot: '', - detached: true, // whether or not the client is detached from the parent / launcher. - classes: [], // all class paths are required if you use this. - minArgs: 11, // The amount of launch arguments specified in the version file before it adds the default again - maxSockets: 2, // max sockets for downloadAsync. - // The following is for launcher developers located in countries that have the Minecraft and Forge resource servers - // blocked for what ever reason. They obviously need to mirror the formatting of the original JSONs / file structures. - url: { - meta: 'https://launchermeta.mojang.com', // List of versions. - resource: 'https://resources.download.minecraft.net', // Minecraft resources. - mavenForge: 'http://files.minecraftforge.net/maven/', // Forge resources. - defaultRepoForge: 'https://libraries.minecraft.net/', // for Forge only, you need to redefine the library url - // in the version json. - fallbackMaven: 'https://search.maven.org/remotecontent?filepath=' - }, - // The following is options for which version of ForgeWrapper MCLC uses. This allows us to launch modern Forge. - fw: { - baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', - version: '1.5.1', - sh1: '90104e9aaa8fbedf6c3d1f6d0b90cabce080b5a9', - size: 29892, - }, - logj4ConfigurationFile: '' - } -} -``` - -#### Notes - -##### Custom - -If you are loading up a client outside of vanilla Minecraft or Forge (Optifine and for an example), you'll need to download the needed files yourself if you don't provide downloads url downloads like Forge and Fabric. If no version jar is specified, MCLC will default back to the normal MC jar so mods like Fabric work. - -#### Authentication (Deprecated) - -MCLC's authenticator module does not support Microsoft authentication. You will need to use a library like [MSMC](https://github.com/Hanro50/MSMC). If you want to create your own solution, the following is the authorization JSON object format. - -```js -{ - access_token: '', - client_token: '', - uuid: '', - name: '', - user_properties: '{}', - meta: { - type: 'mojang' || 'msa', - demo: true || false, // Demo can also be specified by adding 'is_demo_user' to the options.feature array - // properties only exists for specific Minecraft versions. - xuid: '', - clientId: '' - } -} -``` - #### Authenticator Functions ##### getAuth -| Parameter | Type | Description | Required | -| -------------- | ------ | ------------------------------------------------------------------------------ | -------- | -| `username` | String | Email or username | True | -| `password` | String | Password for the Mojang account being used if online mode. | False | -| `client_token` | String | Client token that will be used. If one is not specified, one will be generated | False | - -##### validate - -| Parameter | Type | Description | Required | -| -------------- | ------ | -------------------------------------------------------------------------------- | -------- | -| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | -| `client_token` | String | Client token being checked to see if there was a change of client (online mode). | True | - -##### refreshAuth - -| Parameter | Type | Description | Required | -| -------------- | ------ | ----------------------------------------------------------------------------------- | -------- | -| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | -| `client_token` | String | Token being checked if it's the same client that the access_token was created from. | True | - -##### invalidate - -| Parameter | Type | Description | Required | -| -------------- | ------ | ----------------------------------------------------------------------------------- | -------- | -| `access_token` | String | Token being checked if it can be used to login with (online mode). | True | -| `client_token` | String | Token being checked if it's the same client that the access_token was created from. | True | - -##### signOut - -| Parameter | Type | Description | Required | -| ---------- | ------ | --------------------------- | -------- | -| `username` | String | Username used to login with | True | -| `password` | String | Password used to login with | True | - -##### changeApiUrl - -| Parameter | Type | Description | Required | -| --------- | ------ | ------------------------------------------------------------ | -------- | -| `url` | String | New URL that MCLC will make calls to authenticate the login. | True | +| Parameter | Type | Description | Required | +| ---------- | ------ | ----------------- | -------- | +| `username` | String | Email or username | True | #### Events @@ -224,7 +166,7 @@ The `pid` is printed in console after the process is launched. These are the people that helped out that aren't listed [here](https://github.com/Pierce01/MinecraftLauncher-core/graphs/contributors)! - [Pyker](https://github.com/Pyker) - Forge dependency parsing. -- [Khionu](https://github.com/khionu) - Research on how Minecraft's`natives` are handled. +- [Khionu](https://github.com/khionu) - Research on how Minecraft's `natives` are handled. - [Coding-Kiwi](https://github.com/Coding-Kiwi) - Pointed out I didn't pass `clientToken` in initial authentication function. - maxbsoft - Pointed out that a certain JVM option causes OSX Minecraft to bug out. - [Noé](https://github.com/NoXeDev) - Pointed out launch args weren't being passed for Forge 1.13+. diff --git a/imgs/header.png b/imgs/header.png new file mode 100644 index 0000000000000000000000000000000000000000..1bd0b6c4a24c67da3a62e0a8317ff5ecca6308d3 GIT binary patch literal 28978 zcmcF~WmH_<(k3AUC%6-&@!;<65UgbfXCp0yOUK5C{?+f(3U^a0%L2aMx+x z+Qp@?Crm?40SlcB9RUFWOG!}{h=70ye<1jxBEz5awoEAC zFK8}`2JQ$582C?*X9#H-BnSvEI&HP}J@i%I2!os*+087R%`Mr%jxO-k2neDQU>7rx zy`=}WxuvzOlNjKzxg9`lYas^E<5T5Sb&;{Ou~qbTv()ld(*}9lgM=&q65`aNU|~1` zM@tVgYOte≤ij4Db(KVfg!}uQ>qJ|19ya7XwH=ose2zRfAf_+0BxgkDZ?l#Kp@^ zEg;0s#m_0k&C5#7&B-Oe!70GO#lyzQCCte$%p*kouRj3%Y;G1-!a!O1f1L~dNep1) z;o&08!QtiQ#qPz!?(AmG!6hUl#KFnU!OhJEU%}=Maq=(&vpKob{+oiVr8~&Y*2Tlt z*@^mzqM5n#dk--HoYTKsaCG?(Sts{@i3u(+4zQUE2Nyf%)0Y0dP*wH6Uh3%hpVjUj za-Q(B{EOfJBVl)Kh>Il$(9+%cy&K3<&ePJ#gZAGivjF|)SeN&14*%@b0>okIVCe{7 z<_>3!>p!P*v2pfrcDHfDfA2 zID5G>Kk@Ug<(9H$9+qMNxXy&wxVYi}+T2{iTztY@0&JXo!knCcm#V_8z{1SK?7z3z z*}~Qe^50pisw%AHC&L+ggW65U8ZzaIb%g<%OWe(@c0wiqZ?B-|&w-Q@NGiyr@7bj}~_5b8X#@WHy zP1V@~E_0qITZU7I??Tbm9j-XYzpf4~OV@wBbFiiU$K-^~Ku?w~1^_*&*b>g~->+@| z57PVZ@%i_7FB?lZ(f>mEf0wyCTX}eyxmikC!zKOyFfES%8|&_7p8qxD|2?(;e`EY# zA_du)Iayo6T_y+MX)7F0&gHK{IR1BC{qx)Z;)wpe9PZto-u}m}!aw}SF*GHaO$Yy;q9G3}iXtVcJkcXMb@jo-2p~StynoH4sTD2FV@Bsbnyq z+*TjG?`}zD;P30}cRvf$ueP8X_^!+#H!zH(^ns2<5`ZVvM>>qjFy>KaEK*)~K-K*H zJNffK1h!ZQm-{1xl%4rH`#(!!I)}b1&CBZg_O5~yd+{r`H$GMKoP^UtvAk$v17Phf zmwZ)%*MQBM1kW#9>sMJDVBdrRo4`ej;RbStC2o0l=E8Ia2MHK25jF+w31;zVLQ{ZO zJQI#X#$tcIx`g!mHDfCV{_$P$jwrQY*2Gj=#wIJq)n&OgnZBy%?4W=P+?H*G$L-zF zD`!)P$fcui8VZL-DWE+lF*7zhzKG&Gu!L^6zw8BA;7k6x{qmVHEN{671K(l0-KSS<7lpY(T~Y zWlQg+mrH8Il_v6xq#I;AdgBJsh1bZBtJcmpu8&MY6j4-ohkdOGp6g*OP93%Q_?vkc zxjn*17(`Yxn30fZ+%SHR0)*L1=23C{Ty8EJM|pheI2H2!tU0^U{=^GLe$r(4^TA=v z=ql-C4JO8djlMDzyVmE6Lh-Wi>np|r_{)kAP~T4TQ(~YY#h+Pku!Hr`g^6?3p=06F z+j+7CZGvgUk3E18>LcF-piMrPVZ1e|K~{bpa!#SUuxqq;p<11`Rn<}s@#PP z!qH&XI}(+PvMMlPM3?ct7nk~tA3{T|ZvS=PwBIM|fq3xJbLh)iA|!Fe3TX^1z0cKo zE&U3<+gECePwJzzuZl%c4zvu-$`X;l&HS3C1YV-@yDW>ydq-q?BU=|k8i2Q=MPfEE zz$ICy-H}X*E+wJ5Q|xzR8+by%*B*|8NMkWE&y&VGrf7uaJ0^o3Hp+(@qZ~&rBcb-W z6K9hdRm@G0R^@y9eJx`^vqdXo(4zkk*`u2M2&l7qp+Sy(V%0^^Uq2%TE|p4Dj4NI0 z*xx?ISGU9*4doA;x}OCKiVs=~l2NsDW}7;?;?vP|B&j2m2@x@qep;b2Go#Sk6{6=- z#nGX;m%oT=fb~bpGh;K;zdH`;#HW-epTB=uu9i+WbR-%=b%jcER2WKigZg6LCKyMN z23H!uwy^=*N)?=;yDT@O#e^f@cWIn=HG|`pEEE&A= z2H^~|{$)74j;K&Hk6L!XrFj6h{PWL_N*!+UtMeKaLLoDCKsnt`k;kpr8Y|5dsX-hr zBlEc(*2>_TF%S>}Q0F0vPZ3lfa8QdY?uJO4iJ-)j%jc14opVV`bYJ=w;CRGSDj2Hp zim(~B^7oQ)mp@a%L4qdOy_sPkDVdH{j@yMgwW}~5OzhU#dKhjPs7dVO7NgYxU#y(k zz88UU)RDt3r%32G^VMJZ-cZu?$i!0l_nqE}Nh^;_Y&n1GTD=PEL1PZ>szPR_KBLb% zY2e^bbKbd#pXp|3r*@)fY5XOmtX+x+rc52RwU7LjM5m%yL-3LM==lwUSw*wtO83YI0L}oeMY5cR(;PIO)rcx8qO$==&)N*x!KNH(^1`Yzp3Ef)aN=bpik`M&q z{q&^(DFS)z{F8Nzh(4;(skw@L(93EZIVU8LbELHLdGEUUP_H?`?uZhh(N z@$j{-Ylnk7C5WvPJ>e6p5@(PiVvrm)QwY6XA{h`}baVBZQW~|IHGjcAwwP2{z=DCX zfsBSOQ0kY8B2pmhSbv>7f@|7%xCpBU87j?oAy?`&(jaK48`-Y#_2xHdT->mow{5lw z(bOJmPK+Ehknn1?exJPkhl@FX?V*JcUr%lA&EkrNm%p;Hu zmij#LsmC)Yf$5PAqfRmX)D9SNqU&`-%y<0w-n0-(~$n%%?O1i9#(y2KBx`Bj~H z?vY$Xxe@jWS)H8_G4*W5+IyG9Loxf|kHtThOAA`&;&*>UUp8;UeNe`eOTJ5>36Vu> z(o{MgrR__uh_1OSGv0eu-lQ8$pxudA_f1+N%D_fo{QK-P>zcfq4G5(s2_Et@RL%Xe znwSD+CA|0oWeLe%whh)IN-HUNrPkf4tt zJVRHKx2E7gu^?GzOnK0$G8w$C;?DZsNY03BY+OFxlCMS=x-l!B9$VZt+WUV=i%60in14)`wtQ8B=#e}572C@tjW`}%Y!dRvPnP%Q@k? zSgds|Boj#-B)PPvs&1uWU-ww6cGa|EaOsipTpQab0wb9UzG*|@qP~YF8EE3(o9RBG zi4^OSDe9UYR8j;Q`YcvNk>rK&tV2y8t__Cny8=1pkdDdEMjkbkn>m=sL2V?Qv;6cCslI0a`ez61Hc$3;I#nKh09+_d&qSC7$khNoi`h*uA)6YxC6S8# zB}>CzkPtF^B8n8qi8?+%et22ciT8;{xukO;fwA`Xt^8L?;hD2ZN=OzcvO@+>F?zO0 z?pJ?!-i@5uc6|`3FI;~dI;7>($D+|;^CXD+yZjOBmNfWSNgm_qXV0T0uVtk|G;ZE? zygd18o*B0dr5oF}MAKJP4etOX%I@V=C&EG$jfgaL%_}%u)|%;9fRI^%?M^v zR!YkAFVY%hJ@M$wbZ$5ashdLOjWPm%;9(f31 z8k1oTgF&`Mi>Zi@vGhL)0hM3N59;)O1?k({UM}$ZIO1jIYCsd^X9YEDDRo@cReIC@ zNPk<}xV9%ICVp5Ep7AM&6F@XYdWpDo>-QWkh?`D$Fai0|e*9tBEQjtYBQdn>$7G*T zSw(2?AUJG=D7~t6J_we^lCLB{>^c>l6b0qZ zWhpdfdLU|9T|yV$FJR*J1wfZ5;wQ-sMEMO3(4%PQLgXwSDdH6-vu;BE>*BGDK1h1y zyS=MaXkrl#D%rh|TJ7Zo6q{>B0?JRC758&c=XD`^eyea_I>yGfRAHH-#$j48@07NV ztjNLm=VlwNTFkoXS;5{E^Sd_{r+jnBu~gi;q-M3oP4}8qOgzg;>Y1|J&j~Du(Z1*Y_3h2?Td+TuNspmQh5J@|M1~C; z!7s-4E1&6VQ$_MfX>LO@vohhpN>LoSO?h(FxFU}!%B9-qdNLlcbJeuDs_O&mP=6$4 zJzC`SJ2s$qM(d87)9g9Meuf}WkVLW>L2i5qB}?k$;Xy3?Wp%v%HU+E=reEa7BUBmG?-|EJ=gCs^G?kGXTs zQ*R6l42d0OOGwyeNGhWy)Im`Ku!yBkoq54|8==}kc=QsoN;=T8SZO1b(z+&R*EY!d z<9Tf5eRBJ4_Dguik^ke#R$iTo2(+KRE2=5yxR|X5;}Ikl$5Clw3~A?aXKDA03g!<) zGN_rSwGydh5)J&gdm9cwTwxq@U!!9f<7?td2>gI`uGFj0%Q^pT+{Ctut-B z6ok^=r5YWOk^jd}(XvEd2l`33Sx(^KW1V&&cmAgExiS_reFBrI4!xoGmC{ zmu^;7(l`bQ8{F?i5wOXTpo*we@MYGj2t*F3s^$2?y}6r4r}>UG+Mh-h4wlh~x*jI- z5~fi4*CxRnh~DMFpwJ}!j6Dyhn|lTO04fQpryPuGX5L+JT7ct5fac>5e01y(4zW_R zRJ+1Jpoyl~AP|ly<{WE&I!>yrOS7U%ZM?W@8?({Q*Dak4^GO-bu?&>>qQ>^#ND)aX ztNN#XEEaT5!{QAoNJ{@iRDt|C5tPl)CeuG%S!3&GB+UJM=Wr{p+*xiQu^~^Fd#J59 zh{8ckS|s(wv$}U_f6g)HxV+KMUC3~ZtN%o1v|rn`9iKgJ#CEMPpmKY=CU;|Sw$YDh z-3Zg{u}v`2L#1`~_C(b+Un?-F#}yf9at*m7#q2<@O@b&%LBE6v30IY{nbGs_Ed)nv zwVBk--?(P#NAQ1wOX$+~u1rNjl~bPhk4m|1tuTdATCvF2f$u$r!2}1+H81;wdv)Lu z<^AyC;@#-;)Y1C#hqN9%)adV~9m(R-1Zxa4Lb{R}#kJnAgq2WeC9yDJL=lVxKK$rigi} zuG|>1YXlw(X&+XEn1hWu?7vmIQe9G9^VYQbF>xKySFv_-^J}YbhO1Ip!L}_E?k85= zwU*W&x=hU;JG*$-@LB89hxwBv(KOu-Ho8%$tau zDL1n$lzG$pE`_~-83}T@y(k2Ig`u zO%odo99v5UBUQaBLv>AV1(yCufD zMgG9HxfCAuN`i;*HbyjGs!V&~h)>gDlzo@{+x7SfjImjgrG$?&)hHvYE@kRZd76nO zYXB=FKka}Ubh`HT)r~C`Js~I&J(h}~d9M?_WMG>?%si7Qk(3$bW8!_@xTBqmFK( z7Gn09FUh1*A<42|sa7F**9_qE@niZQl>?6TcW*YRDmfPccO03gBoiuC#iJ|6Qg zNy$w*14CIlrb^BvZ0PhzffA!F*V~l=`i150Jpx$CBDHZan` z2a=D_X;h{N`q70eZi~MD!Vi|Fr&4b5IFLHNDpW)%yPLCWWa5a>71c#`1@O`Of z2oNW)JU5%+tQuanI7(EQi)OmUZ37n6_i6j_z($Qnnt1ehGz|=rdQLVL8^9ags{3!h zW7GR7FQeKEyg~;q(f{HqhMEjtPtCX=bl3H`!<;vdn~cD1$DAL-QMESBzh^A;Jx z-t@%7EkUP66-M#0@5@?~TU9QPepZR3I#ST*$fnsEx~7j(S4b*Kk;n!6Oa4ZAD)DIK z;U#UK-@skp4J6xXvapq4%5->}-Qp~XyOtmPFn~Bn62VIFC&C}QFyeAO;@W6@J~PpC;Je$C2ORa2!~UURY?XB1;#2ZYtq z87XMBsaK3*N3>(Pr&%bVYhhN%n-qcEzPP%|^K~)QxSv+RX*0{OfpZ}ve?cWIz5qv( zC{8ff#lnS7XP55FN?Q+N{piet9i#u4{~Gz1q> zCJjacnob*f(e*0iB^<@Cy#~VL?$+bgZu85t8gM!xqR^LiR*Vwdc4axaZif8qKDeZX zZQ*HdG7Hs>vf^N(+XUhpE#W0fgDg$Y^JfdXB?lR0 zI=m7$pZ|)uWD!$7MUlBAVW_7}kTugY*{M>6nN_nS;rMxgVEU+yOz}$YlIicY^2${< z*d1%Jb7O{KqcC>qfJ|TeFb_t9YuPDl8~U;3Szsb@xnRU!#D$RB@y=y8~`N$Xo+ zedPocZx5&P);{@M9gc2FkYmB+A@GazUNjfq%a&d&IN|44!h#qQkd2qHNAp{Fe%JYV zVnP$jb#^0`3n;fWse56aIh9_MG&*d!hv#@}FI z7+r9nY6@l%2>AReKN+WV_vo|yq2Q%h08g{^;rd)tvErM-tqCn5=P7$|*C;lp=A57? z|ES2mv*-^o1@V!O)3gaKWNn!0+?B=OL-EAZ?P1^Scgu~xtvcEtteYRA`Vb$kPvo!A z@jF5<=9*!s3fS!9&RYeofP^VbD|GhkcAFKc-=U~d695VeTRBbHChbncW?e-Ho;y<) z#c0*rAWWTGpD_wocvVur_;1Kz-rpcnhm60mr2CO2qc` z`q@FJW3DZbn57zQ_lY8VNSEy)$`z3lW}@}3ggarp7eSDq z+|qXrqaU|uhtDr+e2&%Fm(Kh>p~jd$zz`nL=B3NvcF*F)PvWaZwt%6#Fotj(ninP- zwbC`UjiJ+q1qs1Y8gwZv(Z==;aT&av-VmmW{rH%rF4`jKHgog*7eV2FxyO&yUkWuG8x+ zBYJL2q!L3>Rqkl5lSk(;@3GU?{OmQ!bsFIvQ6M*IMH)P7$jCHsaJ+xw|3znpGj)XM#Zn6&u7BXugD(EvN=@c)S;FdNgwi*tJ^rULJEBNj*f)p>+Bk z7kOv~o3#|>_rbuXxCN9P;C@N0Q(nb|=m3|j$0jcYmwlqNyT;*sA(VPo&W4oo@lIdfn~7#F z^G6R})w4-Dv#E_8-|dr?jYU;GAeJt$&&MF%C(1wEn)o0mbr|sN`9!rLsebJ*rrcS+ zb0YSYvu6xL#ngH)><`id63D6UF|vdna9o#V&_m+HG0n-7S`8rZ=9|2}oE^|J8yqYX z;nQe;sCWIlu)TL@iuf5Pk>l2GIo0NH*o^z*#8|b@@#rd9(#+NXLWsJ++l_%HXSc?4 z5^HtiF2Z#2Hv^Sg%roFWFJ|0EM==^N!xpZxSFW^PzFLVsd;x9?h54Y;s8#TCfzibL(Bbw?W?h)Qx}QX)#Qj@nV)3WGP2o*=d_DPn%uz!?)ngdM7~au3 zq>t`O6JlZSNUZ1dzzKH*FTcu68*Vj+ULRzsA8%JR+jd7VVFNTN!$s`FZIHzj?@b)H zE_4vk@m`%CeOwUYd?ZLd^rbzVJ&$ns;w*z6ojPdS@*XC!xj3-b2-_|enuZjSJOYr0 z96t?)H-R7EhSDxr(*(bCu4mIZ1al&nw&d`1 zqCSftF4(R|dS^UzXwA6|5WO+wX{hagm2?e)xUF;%Y7jmMeW@#SG zB5}vRd^{Rmm0SHni1TQJ!7|`f>OlNVVEE#~yb6`>gzlMT%p{06Wpy(0a2>8|d`RNz z`h8i?Tc7s+SGUeZnXG2tn0CscHC1t*4JySeQsnNFPK}!z??JjP%JW;OG$o<=Ee}wy z2rGPU4ejQMAt^IhS?3oc~NdSnU35D;spX-P0wA;>a7S zz7IQX@Xu(byeG=^$6(g=JU}yz8)4u*G+@26lFu1E(=5K4?S9GfNuQHVW(QTehc&1U9 zW)x1aAv0jm9QjhI6Yg>MVlMc}`HZ|P>v@+_>a><^vEyzneteWwkr^Qfk$6!OPc z9}b9js{dSn{my@7m*hFmVr&EG49}$b8kSm-Axxm%Gyw4(yZ2q&lGvJi9!+Qflm_@I zd5Y$`!T{4O2XVq(3V)8O{4mHIWb(0L+eubs6q-@t{9m6gtDD}x2&byyEtp#UjQ<&q zPSv_mRj*{07R&oN56$kg7wI+ysxNt?VsQEZp^P6`5`?(wfeJ)rO|vUH05*s%Q|?{RONM`nI(A4Mz&+-ON#kg zFJxBnq`;;I67oggagl$1+=dTcxra+Db;AD5=@8d*1KnDL&{&ktI0jM?JD6Knh3Q7# zl!;2Yp=sMYq8k)=E@?fx(3tE$jYOl-Y3lx#D58pt-p^CDEkwm?xeIK2sv*fgA91&t z?4Rwtd})cGozovh&wF6ljmc`iT=L8=B2+vL6lLcy^8pFO21@+ww*Az4v-?+ha__MD zPO>=BVd#{?ptPf#|69>jgHVJ?N@2Zg!pSwEHxF77I(J+QF~jMb;ufog^Se%+$MA6u z(KjPkNa}2h@LafEQNXk_c@@J%C&y9V2?)=GjCNrz*S*-)ejA;uxFu?{5|0E8qUQpl z9^1_c_uS;YMev#`+8u&ABt*ZOMSkDX%mPZIsx`^`_WJvD?Ib0r|9u|)cWAZ5H2vvcE_xBo$T`|w<`iQ;x8QV^w$_^_XX#L()6*4ZgT7A8ud z-5(!wEA!F^q+~~532Su|6){#((0##Bz(ab#h!@oznWoU|;GeHBaFl(St91IcFkUrV zg=Rfj$ybc0PRILUs=KXo6f5HI3q*!*%?$wLOM%~z&G_>8Ff!%JG-kU2rFid)qPU(q((7#Y| zgCN46(dPD??J1f^4=;Cz9Z=#eF#-vLnYh2`zT_!@M6;crHhL~pR=qFipAhB`_#ANk zc!yq-2}jODQpmNH>K>9Iv-%T!)SD-v` z!c#SNQGP5ukEL8(8lW8Z;=6xJB#OMUL z4b`^CUbb9N9c?wVr$>@Eyo?@r-wO{?UGeTKRu%13_E@ocpdR`*U*k?i-mcrxJFho- zY8{3{GY2=Kj}MoR0)r~genm+_;ucBBT7%Ujj(3Lm5I`F=)SQ9_0y9x*1KI44dI}2XS(#Qwijd$ zw@S)NmHJpPSc%RL8sJyL;KIlwQhQ0IenN?oM7jC!T;O!^Sb+(GTl~hsx?~10pjFEZ zz)bq8(gp)nW!Q}H%w!d>C6;`mfBjUxAS`bcEzG9(h@-4hJN69$;uX-0a({Q{S_%{&DGN!P5r=Z*^W|n`q1!SrHm;AG9v@5v5UXDse>(^Mbc!}v zG_&|F{w9W)wRj*RSLvbWVeLkGB^4gZP5)xP1e~5268iyFE}X)&1`^G;8#am@WY$$v z#Y^fP`iQ0<14Y&6gxc&=fZ{U?eegu)YbW=MX)^PrqK#j3eCN9CSrEo_J8Nvy1w+AE z_*9yev-Q}WADxmk^B1%7oLw1qw@IgLx`Q|?w5AD}0qS77Gv$Ok?(*6`W1o+P8dhb( zpS0uD7W30D`UezG&5vC8D9oyB!_r92=&<^Of1hbR53CU@AUInOc4|=N*qPkrx2=U4 z*p0=fQLe@*`0~<+13IbKR*Mf;CnQ?3_t*o758E$jjo(kCBYX+bGHzHG5VAgr6!o|p z5^V;f+_%UT*gem0l0%DrJ`$R8_{X})6FJc^5`(=Ndh7JaKP0TA@wsSR5Bh5mmBz*s zG|4N$JhDhKLkO>C^8CHn-jMqmYzVP6MDe1>ywRgAouVBUxMe*zPZIXqA{X;0J@y#g zx*5%l5&r2-L9;Q)X%cQ+_~$&L(f1TZ(EVUx?lC zVvG9-xHGD0q?6>DkoL$X86DgME|(tPR!IEuYdKw#7XeW#QP9#c-sHJY_oe^67hjsW<601gws|Aj#K#qcq$DGXp)h*O%@g;;{H+HD458lm=IZHzI&Ay_UfErVF=dTcd)XlW(C( zMQE+4j=Z)RtMKU+W@%VjCO+}W!Q1v@znSuazLNOnS${@)k&~P<)Dc;L9OfM1LaIYe&zo`jbgPe5+957(Tw3?ef$` zndVYfh9+1v6=mBIiJ*x|6dR&{(aY!S>oriTz#?ZTy}I0_yEWfW{NP)~Lrlr+SiRQN z%D(b2X${V~cl3PgOK(!zUnBhkl_sXzhV7Ht=Wt*4r3cTPFQOyo*xzO)KHyO52i2$T z45}3ki5%(t*i&o%h?3QwNEdN^%@UCAWpad}-Ib{7&{{U|vA2t2@1Q7^B0rrC7v{(v z|IQ(*YRJkngwYpK2XL~hea|JIKjKiDF>nzZaoma%{JT`3B^9HhC2(x^c(8M}J_CDRT$z&uM*d z^If*Oe?6s=`5V7d%0|CId>Qo)8nZ4<&+NNq_6s6J-PWvL)>4|c`FybQMvRa`3y7%} zPf2bllR!ueLU%VOcEW6 zC8#-kort6UqHF0BhwCW{Dy!TJyQXi9`tRGXFK-J% zD~aGM%j!wqOXzu!T5A!b_^>#X#v8v*2Z@f;lOZ3u<+$NvU#Y^|zaC!8Tnsp?p>PzF zv%>c!)x1zJb=Ce*_erf@l2&N2<04f~ZN&pgUzX@F)#8Z{RQ*j* z9jfkY2aZ!6le4e3NwJ$k!W^GCRA|B>AG)N5doEern=jxv_HRL9tL4v>dE4Cjta-ZA zB)R`v{Rk3YaTXdy?vbjHmx=w>-Yve9M0d#%IW~-jW=e4h*C<3bE7Jv@Rv|ko#mw12 z=`!vX3>q{GH1$t1G@C;>>hdzC(@&*G$KAVJMepq^y~e#GMq7GDRBc(MyCZ`{X+>Y$ z)ge?zcew6yakF!>>l$6wu@HPWg4#Rqy+r#PoSMSI2D^tUCd>UY^8k%EC5A@dtY+tp z+zp@Enpl`yj?%(QL-v2wa1K=DL!aZ+wY-ddv2{to68y4<=4+zny~}oJcSiDbilc5 zMotR`_PU=4Dy1-4%sD8k%Ys9JI`caeUa#)SOFQU_RgIPW%%Rzjo2IajJ_mq53_S*> z9p$*vB(u<#a8fIWe#IRvqXt@{UAae>}*jIy~}M@gYa${M-d@06OE%l(Oe8AvV=225bb zX%B%+*IGvI``RRVgru$zaV^JD>EKP3>bm-f2^)M%=LE^bPg1G#7IfcLL^7=_8nU04 zD{L34pfc-?U=kp`&P&Yrot2+$u5xb-Xz!)hGw!LIS@}Wya8ntBL1|_Bl3C-SQB1KQppZ=$KDrVg`m_sgd4h$*Ix`&+tZzwb9J!<~WZM*I_|OZO zc6lo|))(}dB5x87;w(%@xL~jM6C_`%(a~|HNaz1iX4_AMp7>g=zTEP@J<|SG8mHag zkvd3fTz8%CP?i|W&AVpZ*2KI)`-%0wTGae+OBtS zeCbg`FIp9M=2&LNy4a6Z{P0plfg^Wg<`}hqDx+Y9QOz8VY%+T346=E{xP*{QQtbpg zLU;s@qO<}+y*b5((*yHHX2#}4XBvrB%z*QddD0Be`BV$nixUSRN8_8@z!j#anURFN zoRm6iy(rw3%P@FFxOMfZ@$&Vv4u26%(=;o;aBV_?;mZ;|z=Pi6R-U4^qz7^_X~y6d zaypiGMCI=@AgWvZlq#{FNpK!fVelB~dL@YWb)3w?2!q$s4Hjh!%*SJr$gL(gO?FFC z{dWVRRd0jK^< z{a$UEXt#}afYud;S7x~s`biLJd9zV)vbO2>!D{cQ!4GuK`KsRshiY4#25f3=XOR~g zE)Ci)5;@##9{t^7aeAMH4cmxSDeg%|&?#~DzN_2Pdt7=Pb-o*H2b?Hph(KOpXIOX-|Vg z!N;d`qXqpN5u#~Tt_i~^X6ghJ^F*&Xl=J`-A2E&>HXOM=44qM%uYSDeoSqEhS$ng7 z%K<<{ijg_7iSEsPG2DzP%Scu4Il2u9Q`sNpra@GG&JD4VcXdKY+EXd z(kDyC=fWL4C8b6o(Yd(KWjI3AY87Eb)tD;q_K|&5ViPE>W9IV*Kz3XuW!U^I7wTk4Qm=H8N7St57UQlOgzrjf5(8*oS=6iRIfJnK z@|cdpWq7J^AcTmd<;PrTNWB}PLIEs1i9ECVViC%mQ8*!wHhcB29G2>XSSlJlM|P^| zR=0CyDD>x5=DxnGl~?L{G3CtiW`*H7>%86T2PUJhFsy8!jVsoBoy#4|C6ewV@v^p} z&D(e@GDluBf}DiTmUoTIL)Z@Q{P1+##Y%U^OHuAn*hs;uUi`<@x zYobWcHv&onZeo~wzVw**6Da!Bm;}B0)rG^_Zg(9vjcD|KtX8vY_|lWg*4Lc} z0bR_r$<^il;#!-T@WLdZk{{=tWr87u<+LjXZpgi!YAmCbSiNLccEvneBKNly>#2;C zFrS8io-rBf(7mZ=Z@7`!bfcdBLG_)s?OsW30Z!I8b>W_}mjGoO&FG%aMrScm(VJ)xe zb!boQ`+t3MHbQOKbjLt)r8vE7gIyiAKT?4&O8QE4dsxC9KO}Z^e;qhY%pDyPFhUL2 z6zR>YV+Y_Gr;n}b&-@kicUK0YsTAP$gnBjKn$5Ml*c2HrGy%ZinJ~xA*EuNzYeBM;+`y$i;U}@XFf< z$59A1X0KeAo31U3P`$e?Nf-3qU_x#NK>cIZ2x2zUOybH*X4xbHn$UH?#YmYZ#`n!RVws_tT+8JaJTNBqtm{|)Rmxw*QKBaqc zmpQyEt@K-EbeX#&)=`VKXndzQ_<4r~N)XtOo|Gj7>DQ6vi=S-m6~>zi-@W(x6jh@` zqXS-8J_qPPCahoY{iZcxQ8PQd!4EAv)1bGW1h1gy~3;C$cJuRRC3p^D}w) zVlmYRgwaLrkBv5recnkyHEb`(8pf^UoDA%_f@1k9WnWQI&Q)@+EQJ;W5Ot)(;zOneE<22rIH`=2d*U`6FL>Mfv@ljIdDB*FCs>-mUCp!H zZj_+)_`9w4D+#6$O4I8rs%qET;ojrp-DJCDBr;;HZ+`QW#et%dTg;H=sD)}&(UI+*t}8k2tr4T(`z{icEkn@&hgjZ` zY3)Rl5}38?f#BnM^n;l5?GJ^fqwufrbgy#ZMpKQnDFr?QEsZY4smZ49xlcQAg zc?VsHba=9EAR-qD3w|Jq?ecmqzUkJxJ=}_=3;PU_dwGP1Rp&b`i#?K+hfYRCp8GhM zZ=nsSYI=>i36QZraEkLZw%zqq`xmR(b)TIF94Y~|MWk1{NQPFMke3AMN3iOE{Wf)+ zpNDi9wv$yVurdXE^x`sk@`nZHhcC1c4Or<1+yVC|p1EusehzNW5y3|lMsu#cO;BiL zPzbz)It!GDmVYEUy_ex#>tgK=wdrNFDR%d$krST7b6rNp1YRkw<_42}W_y&AOR5Bj z5>^vXttY`AW5z38=4S~}IX2b=S|ggBt`Q+w6>qn($3-}-_yejyKVBN;O2Y@?kRGrr zYM=5`<0n9DLP+o{iuy=#ih{o9TS%>FZR3=>61S>=TB`GT|4DMi_ZAHza2DAoRXfmt zTjaE-#ehU3^M&#cX}u&+4M8tIGORdbMiGWzquo+vJ4 z7Nm3K{x5oYzoI630WZ2&|L9^VY`U{SNzF~t==zhaseouj-56!p zQ<%6?hK!w9CzH8FLGJ|{d1_jkm4$EI#4&Sku~o|Ax7gJ3VoqUQ?Q%f-Ff>4T2DyC@ z_{iyg4-2hi3!(ev2Tul$>}l8Iwe9(!1J`Dpy?}xolSq=UNnd2eTX~CT)Cb}-5(PEj zxynC%taTmvSXv!lZE{c;&j?VYLyygF^KP zZ%S!zeI#ix6aB2m!DdFlPNK2bl2J-ZO2KY4*W2ZRyVo>z(0Z1w6Kd3>dz@1@ADucR=!`N{TUvTdM(JZ*$iQ6)p=1R87^d*`DpET9?!Wf+p=GU5QQEnxSDu(stwf4n}>sflAF2d#0V$fnW0PhdQP~(EriY zcgM5&hwXM~?X7mHq9|(bS$nHlt5Vdi-P)t}rie{aMPqMT#3uHxSv!bTd&EAE{?0k? z`!^qXJW0OybzkdI$SjytK%avy7t^vqOQVYPUC*(6l_`^@l^W*L#D}BZGis+f@;TX$ zYnBiD%RiW#yMFz0^W1j#0oa5m(%MiZC7<0v^&t4s_qwo=Ghs_Buyo-vfuzOX_hrk6 z*c@YoqxxS@v}1Ub_L5oJ#DHUn_TMqIW}uJ#5@S;uNVNj;ZBiCfKe0QvWEa`t`z73N z8`a#*_Y|UB_C$MCHNY|PazS{utaQL&sdC0x*l$MwuxAZ5FOl3FK?9;-P){%monPAe z*aI1sG;zj$UT$(OJl53W---$|{zIWzP1`aEh3^wK^Lm+)o2nq=0eZNak8Vtjg z&U$BM=HvpIj-S-iVLkoG;OifeN-Qlko@H~IW^+=IDicE16<4#iQ`A<8nASt;m@b?P z=?$BojlHwUELG-)ZvR~y>VPg4ank3n#B0+~tsNGZEmyIF;%luaZEP{89-F6aGKJ8Z ze$4t@e>-h$Ywc!FyFdFwH`vAMr8VB9qo@Bc-603f(5er!kgbTToe0^)J>|sF@x=Gu z?C7<&2K{DI4Hdw^O7l;0Vjv?e-cj#9t< zgMv#HsbU2y>%9q(qvUsXIvG~!_a7CCE|06p2ahqj8yiIy{K=!`l>=fU`qb2V zi>vLoI79q-XwM6~>DPM|=~3__F3&aNZH^E1Ihm`Ul4AIULWhhwd%}`=UzZ8k{!q@2 z19)G7f542SrWT0x;#>)wYjkm&b$I4?o)!|5&-y{c-eddiJ&Al|uL;Suj>$K|5%%b3 zik!r{?1Ob1;z*rY(kyn%_Eb=ijE33NRT0C zv{>zRa;uNz(RW)8^Qf@zFut#p6jB~=j>}KYX132eHuDyni2)0N@h^WXd_GqfdTRv!A8J7~}p(_+UmUG=wq+RVBj>^{X# znifw3wPE)oFQC!l`CMagv#^k$KRGf61w=TU+Kb5qy>i= zUx!lp^3eI*`bk@ofiGP)2QKRYg_wZ;a%b_1u-RptVut%~%gUs+*)Oi$;0yo12>)<# z^^rj@?^wb5IwgjiRCmq0K&aF|<%*Ia^c}Izw_3Bx(bq-apI2WoaAL|vrDD=p*RyF4 zf!62D?Q_Vzes{ESh;y`)qrfs1=9i|X(}V_RMIa$mJY#5{AWv-hg9SM9XWGl`_FOj* z3b4t#k|KMtG#^WWBdR99{sF6Xvu;+`yAx2TwPZ(IIa1QO-Om3!ij=zXL$EXZn)MuB zg{#nk+@+Nn!k+73g%0suun>G3#~VH()_yL>V~z^Q?*fto{#XC4PcgNu%+bY#I@ifRkl+X!-r6_H>$Q9#@e&qeRZB1>h|lkBCp)Sa|bBnSr?f@)2efu$Diz z$4A(?X6A%+8`MPhCOrLEnmt^f<;NljSzNrlHaVNa~6_08; z{Mo&BAZ81(;Ot-+7Mzkd2{{b6pFn)I?^jwi@&U-Z|FoX!-@CbA!Lk8w%tXBq+2A0i zsR2Qs)%qMVZ%>sn+rn%PFAnVQED}J~!EWMZb_ywyY6Ea4jf&Weu2^a!$oO+)istPJ=AzZe*6G|z zhcFmZBYiBHX~+BnVQToL@NTI7OKCnG-?nB_RDD_ZxNob=XZ@uJ9|WyZ-<|&db|R5+#o%t zLz=BwmiStVW!9!7M6y8wR_;4quhKgMw@l=$XnV$cQvM!>X=mJMG!QD|xo5iog9=3) zy-L^UaR{sRsFpV>E1*+3}rSDe3|VLcDiWga-C!@M+O?Vw4XKKcv0iB6igx_IFG%t z(UzvX)4pB?htigLh8o2bI%N~s51`%6Zj9kjuQUg1Q2UQ@51#tJYF2enQD5(+WGpxd zWBI=6Q(u3sc!^I^gmZo@i;YMz@#{_<8+!5Mjm9fZJ5bQSZ5v%WdUw z(gwjo5f85c>tz?tC&;Ly;K*Z9mnc;4civy(W>(In`8_b|l)@ChqI{yrXH#JuQ^LS* z`X2$W7}1`YTf;o$nkddPBmod>aw=mR$5Xm6FbU!fn zZznMnxgZHKhG*gm!Gm=axbD9{isPHUQf(QmPX%>I{PYdHY;hws{259g!cU{xwcBL= zxxTCcrl`w4?gtAN~&XG}HC^gZPCDc}Vk~{-F){V3SkLaaP8`4wsRXPfg9~ zn;@@Bp*AyKuGzNwHb5@tj@$7_`NSX<30%`j$}ulr7PJ38p*@G*A1 z<~4?4Whwc43uwsR@EEU^hmFdyW6xj5`9$2w=P{j2zg9rAGF#w zzOvk=LRD@T2_5u2U0m9@v7T|=5|Puweq5fuu|UmJ%dx2+B>U)^3AtgOIqf|VqnB2s zR}d4IdlbVsEHMb_rh7garkipQ#5>`gU7(8~lo4N4!~*Jg&=4kd3!_27QUu9hJ~MUn zQH>~&f2{n;jrU*yowALd0ipHE8cs!3){^yC&2PES=*~GBQ+M;yX<6QcPT5(aacweP zX3_R(98Q?u{@5P<&Lvzrzu(C-Yee?mRkl18&~j9AG?$);Xd3~=3ZX;>u-yNLVu~Zy zVp!NPNcO?zaQ&S5_;h=Bwnucet|2h8`N`+u5U(`1vIe?*U(=QoinQ%L>%ssGkbJ*& zXDUN8-lkPF;Qmk`5Tsu&i4<~PTPGy-e$vjp5;O&m93O6sakmI`bqIOCl$5bYpO-2S zuDsSo#Rk(X+QP3YH?CfvIk#0E@uvNE zfR~U+M*E;UjNSCbI1lMssY%nh1?#3o?DDdYBiCbApRSYNxnHz5a^-leo$3c|OP;Rl zC^I|`{>Ep1-S=4O4*LJ=gPG*f#)F*#i6U99VFAf1N?q{?#-HTgE-G9awr4sowk@xo ztpt__L~&Z1wDugoc)<>H?kKz!`$-4bpzG+Eb&~}eCuH=x%mF&#pGM_`lzcVqERp)r zQwZyIy*|vu_`s+Z`Dj=4>L95KS~JLco-1d{P?xeEKW;0a)dwt6FeU`0_cd8!j7B1X zYdOYiO1y@6^Ye?|nw$w$Ey#CW9BxEO;TL8XwR)4asoRA38RX>(N`+bJc5)i{*v6t}yf%?AY>Yr7fMZiT7 z>$H24sz*yaz>l)W6+s=RqtOMAl0Jw6tQR(2`ZZ2>qfgYqtA6W>$C_w0a2;NkhQ~6i zp$B%Q-B|`DlRp=Q{c3a+{%bLf&0`(yQmTZ}ig%AgK{)K5Nc_FEcl0-p+#!B+&GZ}~ z93SdMWMD36${$o3~ReZVoji2o|l zYXjZ6@86~+&fCALbG4VZeHnNFr@?=kvVfm&|{;7w{dIJm9KsOB)3h-#qUxl|IL@3^A)N6kb zFtktqySoOlfG$fPFQft|@}G0x_ndu|Kkt z>gByGc3ee{*m|AUwsn6vl;Pbo5x<>UxckvCkCvn*r5|wj;^%x=ZjUr?zoH;s5A6Tq z2C3u5RLUg`uPUY6k$wG;k#8C#aEiHW4oE-S|JO^a#QZ&3Hp?owPM?7q$HFb)`}}TK z2Q`?exGKNXnU{9bC~hwxs{Ho+HnsXyeN=Rrk5qCmr)Qt_4{y;u(d*l#H%C0Xl84H1 zpWSmEB)MxToEWrOJtIXt5q2c=NN_@Q{YT^_k&JolGFsK|8wfpH4I4yHHz^wC@xT?Vc7bY0e`6ZL2O`-#p% zz?}71f6|%%z|E_*W?x<}3?_dDSKy3zcp=-cW*^dtacNBGV*ZWSmG0C%9FL{MD z8&OrTi&y>X&rx(_6g%ZN=JF>s=Bkey>tTZ6P4l?3{n@5C_`TxcwLgtAj37+fOk2~3 zN(T|Ke{VO!du%U2-c~nz4&MZWXcSoZHECBj_z2(ED%i*J)L~IR>1xqhT4w7CtS7IZ z4l&T-yuUBrn{zH0PComQwwPCoozx45;gO6| zi1zCBE8siz;F7K(wl{hakxl`Uclh+6kPM~X6nPi(+w9sqMDI))s>CI1{z~()=H(!d zlv9Q(r9@nb!s1NZp3q1s31qR(8f$;UkAb)_8($G?FnPG`^q6Vmzwzpg{b-nC9{Zw5 z*9)0njzsyN)4S~gfd~5G&wU3AZgU>Te0MQkz+faW9r^ZsVq20JGq?)b$;yh4*!%mVb1!jo6qd zbqhjX7QIr9Weypx)M0u>~mEf?cf&vR@CZ4!V9(@KFher? z!IL+ST7y?dGWjnfg$_2Nl}y2zbvB+fQ`5}+h%L))&`0=ktGoWXKVXoLa9$B|%99g* zD6X$6UFtR_{Nm+X;gc*?&u&b~z9&we+kJx-6(dqT9o0ey`;nPFpJl$OkVUStufFIq z034u$L!dJEb~{9wdSPAii8C4Q5EHnz+njLefZ%VA{K zIuv#LD4B&J%4Z=`$LJcP6f{S_riS|efeZ`K8z+)4UlUDe$Q%8}2Hr&bZmki4loQoD z-tT3<7xCyD**V@kAt?fK3#%3}ZD&s)DAHv1oq!AC8-S7^M}fRJ%YCMXtGrN#zZJUg zrxoqIFRDW3lN){z<1E)wA_DYll}8T*Aq~-lx7D|uM}+>FjleoXu=m)-Ie3(`z!J5!d7uF)}M5F)LZy_dSvq*9fg{ zfm+cTf8<--Vj$A(Bi4>u{$e8%;mOSe2vk4u3ZWUDZVmE71i6aEZ?ahO*&tqc)Gf=)CeGO@h5^cL3cm`Oy8! zp2@wm`APk8!Jqmq{Du>LElY3VYuB+a-c-`IkndBE>aiA{^-Aoa$ytfTcPAwHj`!Fs z10ad|Hu6olPXvcD{l_yt@A{l7H@hHV^_%0+Z+{$lcqMt9ca2>gl=#$zlxMh2ElWsp zgg% zuOxOszc1t6<%zzek6S!gwp*KXHp1@o)qMZMZl@1t z?N8A!zf-Ge{etS3u}nzBOx$^yMM#}i+c!N(F7lU=xZQ+q!ye6jEVnzF!WAAu$fWTY z4K;GT+(0e(gz5&<<_Jyg-18@Rg3`?+A$41(4?1vuS4H}Zkk!sa+Mba?RD+9$(P%>JYESg%}TUa zE!2kT7LuNcin}a2i2I_1xJ4DcB(;`!czAltZ@M+#&}Tj$ycFj-Q-{2RXIo@j+cI?* zpph}5nUw}{b7ii=(fK+;-5<<5X6 zfRfMA*t|(2!^UdK9?qwoG{2lX#KIaM-Cxnj4BxvTKl4Mni94VD<#5N>p^2LD>B#B( z-V@wcOLvim(dBmtW)fn5Qdn!aVb8{&-esd+CLlV+!QXH^hR4jjCGT1QjF^kIe`zj@ zuHHcjdwfVDz=Eh$(;UrJGAD9?c6Afh<(Z4fJb&lqLDy#{a!CDkwKM@go-%DzUyeTX3X$ZfbLtW5GA(t{$uQodzJxY z76L$mX5eTL^RD3}OX@@)*lJ4Z%g%T2L(*=^0e(I9{N}!08-_rD>okHCD`ujm>QPaf zaOw~|{0O#)s7t_|%tAGbH4g?aHYC9IE(ugxr++`r_z|g1vUmiP^D%omJ*`rU@o< zoi2O1C6&S?goemr2l8~Sepo!~O_C(^M-{^l{OFkvi{NILT-6rG+H~31)S5$n(GbTs zxG#u$o_i=ODFoR9*y~g_pz8+lFiYyQ1WK)m7*|}vgFSw5u|4M$8B)}4Bg|*BQhGcI z45)k7@t}@SnuRvQq^Xknw~bKWkiEHMk=^E#;vWCt^i4LRsC-iyvI{iO@~C{_SG@(t zD{Cp3wM<{1HV-#V9M$Bl5nxFljO7e_aoHSx$OPHTsbv^SGV>`%OB#N1BvMFq2H+<7 zKbNwa=j%10BbG+`{%S2TeEiyY)?%ZFdmzPwb5~7QPj5!gzn# z6Z)|n)I()azTAccnFG1#eM`CCVtn}oF4?PRtDa7T)tIM;CP*Ix4$KTfi;^Gf@j7^v zCbmfC2F0wOGx}1{XzPVRk)$aS?}=qmlm_jZG3bKK!|%un60mD)S1U@Ii>%>Om(ozK zWx(_O_RHG+a|=NrILK~8hrq9*;`giFco>uUgoKIz_dTDxW=u9P$EjjQ+p(ppR$*Ua zR>CNW+05`H zX3xN)*I>u2QB}8+3MJ-I1YT$`*#oxMs0{a?no=6J?iS*U7T-<3)1vKp<2mG+0Ku%& zb_fwk&Btg-ZY;4PH*S=*HXd;7B=YML+w`^!nky-Y{a`4=_o1=k5Nh-M&o3a!C_MT{ zwTq@Bwe8I_`J$-G3_x+N9i{R|Bco@0xhWr*e4P3@ zIktn~N5)v-I{fH<+4EYrz3QhiRv>jASTV4hDw9PS<`yT=K%41A;*sHdG#)UttGKsz z2$(*mnvfm$bgx{1-Pg1(-lT`rZE-yi2?Y%Q+NX+ayicPl`78rgyUH>gC+|9@77lTD zGW_}YCio_4UAl!FSHy(;QmpBKTIxmSh(5}P%2`hm@MM;X*P^rn$sQE0W>8|@4}nk< zgqX(O^UaTV0A+mxmZ8rlL!>QhNU*+q<5hGZldJ)eynrbSU9R+m&0Z_E%DaowX0gJgM=jFm*%lsSj4@HM%;zGA_&tLXe`{xq{hqo+qzfK~BRw^dlx_%*|mh#hWa#i4t!UOtoV##orqkghFxRnTeEP@OIbpxGj zC()5Xv-?#P*6|1FEf*HM7n4)M08i7rm$WjvccSbT%Vo)sr~fuHsx-3G7NK3N_!CNE zEyB1)M10P&MrGi07(t=gy8@w!ru{@0TZ#4Xwel`R#QrE?XyuBarElDSkum;rCEzb~ zhTGlA=blf@OS`D;OO~)p2T79)XH$z4;6;A$lVKi{3i!mw8I+E05}DajrP+6lrd78O zW$NV<@3wP{o;-T?rBVg3^4Xk?uek&SAMxUqs`15^Gv(%E75X-mJ|^@Arw&j@K%i#BRc|)__9>C)~W6&xtUN;z!gp?xiF+huzionYKh235)n<`?vHDLNC~N z(TG%$Uwa}A^O67;x_D;8`8lGRR)C=lpbt!e1ufVZ=}@G|TBp-m#S z4-~Ikp1;h!DZ&BQva%OoEWewWQo9OFSih-QdrHRqI;FF#!s_i8z;yNbj?aP5R+6vz zTvplz{N35ltmER^qaV7796F&%%^vUiQ7uEK#|SM=%2kWk7a85y-?%Yc&umIgSuE0F zXJf^rODM0HY_)Nv@};=bXQ2T9ePsfU5lvWfwqC-6Nh1Y&OO5n} z&dRPA(SJqguKPeEo~QmAUh|Dqi|*vw-auHIwH%(plV{r(d^Xnwy6&Z~MD>Oj%HuFI z%fOF~(;v-VgN4Tp>z$-U)o@oXM{LSAZ6-jDeG1NZ< zgTX*V(Ap`Tsb3)5UqwoJ)SFq<%#eF^wgT8OK9O7;sAODZ2yjTrWBpLHM?;2vi)F9S z4+rQxQ!3TP(xzPm8EG^bOXB$!cX&N^SR0|3@8 zSW($g$$>&e^P0F^N#f`4*;XoQS-RbS-xO80 zd>%QnOfih@d2LCujd53<9sKWK5@OpgIPP?c%@#YPzYJdi;VT9c-Z###BzBiiQ@S4r zODjn2{VXS>v2m<(==&z0gxvw2B-evW32u(+izA|BH2BB@;KS%rK{reYGoJ57`nt}d zSB&s0S7=@cey*jsW=`#k`0-_tze`!#DnZg(T;ajl;X(cx9a}%<4&RusEi2NEzn0El zWz44>LKypf%y@YfvAYpA)@;(NIbgzlEoB8w%S=_N@QnvhyC%!sF-mYRx)!r3@vJeI zBJR3-X!$BNUrUOMrim})n-%_aTN%F?B|D#XTtPBp!!=k#ih+J$|I!}@x@LD6cowWu zrkffE0wp{p}_^+?{+hHYu-;KjUugUTva2`9;H z=;50Q(S;5EzNCnJ#)^h^D@?O&l`n@W?vNyjQK5-=koRCpOY`k%?xr&;oAeEEp%RWe zzW^FHctE{Thx58^ys^&2j`1?Sl%<97p-9WztdZ4>jxIaq$E*S^wov<_BXeq5tosOO zUqF5iU4NfeWiXy$?1)+C&Eqy`$`fZ$GJrOAdnIkJo;%)s_T-OH3^!2rGsY5auM8UqHC@ z745qNjF-iNq)vUt=lMNJ#{M}l*7GRS6vmQgSiUPvoIzZe^=gnrc~P{guJ=ys=5C=( z(dR}NtwL(uN~U6S$~#iM({V9e~Q1162_kKH@bKiV1J&H;JVqu zX!FSkd%E_oLO5^{{{LNsDX@fF*3$qTQ}MNn||ez4;|z!Q#s6#U}jeEeHs3pC1p&R7sz>V4HC<&;7{^Y zD4Er;X}?aUfVx{HKf=(NrLTC9_4b1PRP|dyL?o=PGa3d zxxbt9oa&Z59D#BTJhq*z#X57mE6K+)kq4e=aJ7$BQHZcI6f4cXL?vw92nhOFzd2aU zJgGXfY!Wvjfbma$|GaEXU7Avm@}SR5#SssojbTY`+R0M8Vr%ru%+~%uy!RCUZtSK} zvyE@$0}dDYKVM(#f-4Oy*d~HHY6mBVw>fUddVVDA(Tdq^o{=5lT7q5ISOE8E#~t=x zMvF;5`xMiA)M+I7mWti)6*;_~-^km;I_L7p%TXbm4J>+f zVp08ydhhA8g)NX%x-%``j|N5;zqb206q6FhCu=_^`UEs7WC0t}hTcn?SeE&q3G(QC zeyt0>`C&=R#!-t@&^W|N@FAVgYy&MT@SdE-{X0DrgKEDeWo;R3)~k!XfL=C9)vt*$ zB2RD^4l>3AYAad%;|0i9Ro=5mXKX%yejSS9CC`y7uBto+^)+97ueAHQuQqI?-dLza zy6L`r_i!5QyV(;*|5S#|K^QmO>W|{3Hr_IY%MD+IJ-JkgPw1YT$kx3&N5V0pt?qK5K#97Z_H==F| zsMmT+uN+q!Afh>l-hwG<&R2UqM?2}fY&;Rk(Lgf~XXx{0!2mNVtrWq(J1FH|Qfpw* z*q5q_#c*?ia1**x-uB$K_KCiZSLqyoxqrhEc{1P3lF6+3UK Date: Fri, 8 Mar 2024 12:42:05 +0300 Subject: [PATCH 26/97] Remove cheerio --- package.json | 1 - yarn.lock | 113 --------------------------------------------------- 2 files changed, 114 deletions(-) diff --git a/package.json b/package.json index 0249956..4807612 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,6 @@ "dependencies": { "adm-zip": "^0.5.10", "axios": "^1.6.7", - "cheerio": "^1.0.0-rc.12", "uuid": "^8.3.2" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 18c9a5c..988fb2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -513,11 +513,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -boolbase@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -577,31 +572,6 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -cheerio-select@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" - integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== - dependencies: - boolbase "^1.0.0" - css-select "^5.1.0" - css-what "^6.1.0" - domelementtype "^2.3.0" - domhandler "^5.0.3" - domutils "^3.0.1" - -cheerio@^1.0.0-rc.12: - version "1.0.0-rc.12" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" - integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== - dependencies: - cheerio-select "^2.1.0" - dom-serializer "^2.0.0" - domhandler "^5.0.3" - domutils "^3.0.1" - htmlparser2 "^8.0.1" - parse5 "^7.0.0" - parse5-htmlparser2-tree-adapter "^7.0.0" - color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -652,22 +622,6 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -css-select@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" - integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== - dependencies: - boolbase "^1.0.0" - css-what "^6.1.0" - domhandler "^5.0.2" - domutils "^3.0.1" - nth-check "^2.0.1" - -css-what@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" - integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== - debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -699,46 +653,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-serializer@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" - integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.2" - entities "^4.2.0" - -domelementtype@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" - integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== - -domhandler@^5.0.2, domhandler@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" - integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== - dependencies: - domelementtype "^2.3.0" - -domutils@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== - dependencies: - dom-serializer "^2.0.0" - domelementtype "^2.3.0" - domhandler "^5.0.3" - electron-to-chromium@^1.4.668: version "1.4.683" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.683.tgz#b68167ed66dbea01feb86915aca92c09bc1b651a" integrity sha512-FmopjiJjkUzqa5F5Sv+wxd8KimtCxyLFOFgRPwEeMLVmP+vHH/GjNGCuIYrCIchbMSiOe+nG/OPBbR/XoExBNA== -entities@^4.2.0, entities@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== - escalade@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" @@ -1020,16 +939,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -htmlparser2@^8.0.1: - version "8.0.2" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.2.tgz#f002151705b383e62433b5cf466f5b716edaec21" - integrity sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA== - dependencies: - domelementtype "^2.3.0" - domhandler "^5.0.3" - domutils "^3.0.1" - entities "^4.4.0" - ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -1220,13 +1129,6 @@ node-releases@^2.0.14: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== -nth-check@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" - integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== - dependencies: - boolbase "^1.0.0" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1267,21 +1169,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse5-htmlparser2-tree-adapter@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" - integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== - dependencies: - domhandler "^5.0.2" - parse5 "^7.0.0" - -parse5@^7.0.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" - integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== - dependencies: - entities "^4.4.0" - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" From 0831ef58980cc968e8207c08f0923193efd3ee3b Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Fri, 8 Mar 2024 13:26:58 +0300 Subject: [PATCH 27/97] Remove Java check on installation --- src/launcher.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/launcher.ts b/src/launcher.ts index f6be630..0d60f83 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -28,12 +28,6 @@ export const launch = () => { export const install = async () => { log('version', `MCLC version ${mclc}`); - const java = await checkJava(config.javaPath || 'java'); - if (!java || !java.run) { - log('debug', `Couldn't install Minecraft due to: ${java.message}`); - return log('close', 1); - } - if (!existsSync(config.root)) { log('debug', 'Attempting to create root folder'); mkdirSync(config.root); From 65e52b2de0d60cdba6a8da3256fcccfb71425887 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Fri, 8 Mar 2024 15:38:43 +0300 Subject: [PATCH 28/97] Vanilla testing --- .eslintignore | 1 + jest.config.ts | 8 + package.json | 4 + src/authenticator.ts | 2 +- src/index.ts | 2 +- test.js | 21 - tests/auth.ts | 13 + tests/vanilla.ts | 36 + tsconfig.json | 4 +- yarn.lock | 1726 +++++++++++++++++++++++++++++++++++++++++- 10 files changed, 1776 insertions(+), 41 deletions(-) create mode 100644 .eslintignore create mode 100644 jest.config.ts delete mode 100644 test.js create mode 100644 tests/auth.ts create mode 100644 tests/vanilla.ts diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..dcfc405 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +jest.config.ts \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts new file mode 100644 index 0000000..557c7ae --- /dev/null +++ b/jest.config.ts @@ -0,0 +1,8 @@ +import type { JestConfigWithTsJest } from 'ts-jest'; + +const jestConfig: JestConfigWithTsJest = { + preset: 'ts-jest', + testMatch: ['/tests/**/*.ts'], +}; + +export default jestConfig; diff --git a/package.json b/package.json index 4807612..7a94655 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.1.1", "@types/adm-zip": "^0.5.5", + "@types/jest": "^29.5.12", "@types/node": "^14.0.27", "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^7.1.0", @@ -51,7 +52,10 @@ "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", + "jest": "^29.7.0", "prettier": "^3.2.5", + "ts-jest": "^29.1.2", + "ts-node": "^10.9.2", "typescript": "^5.3.3" } } diff --git a/src/authenticator.ts b/src/authenticator.ts index 591cc7a..34eb972 100644 --- a/src/authenticator.ts +++ b/src/authenticator.ts @@ -1,7 +1,7 @@ import { v3 } from 'uuid'; import { User } from './utils/types'; -export const loginOffline = (username: string): User => { +export default (username: string): User => { const uuid = v3(username, v3.DNS); return { access_token: uuid, client_token: uuid, uuid, name: username, user_properties: '{}' }; }; diff --git a/src/index.ts b/src/index.ts index bdb5096..04d9d86 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ export * as Client from './launcher'; -export * as Authenticator from './authenticator'; +export { default as offline } from './authenticator'; export * as Config from './utils/config'; export { onLog } from './utils/log'; diff --git a/test.js b/test.js deleted file mode 100644 index d74c445..0000000 --- a/test.js +++ /dev/null @@ -1,21 +0,0 @@ -const { forge } = require('tomate-loaders'); -const { Config, onLog, Client } = require('./build/cjs/index.js'); -const { join, dirname } = require('node:path'); -const { mkdirSync, writeFileSync } = require('node:fs'); - -Config.setConfig('version', { number: '1.19.4', type: 'release' }); -// Config.setConfig('configPath', '/usr/lib/jvm/java-8-openjdk-amd64/bin/java'); - -(async () => { - const versionPath = join(Config.config.root, 'versions', `forge-1.19.4`, 'forge.jar'); - await forge.downloadForge(versionPath, '1.19.4'); - Config.setConfig('forge', versionPath); - - // console.log(Config.config); - await Client.install(); - await Client.start(); -})(); - -onLog('debug', (e) => console.log(e)); -onLog('data', (e) => console.log(e)); -onLog('progress', (e) => console.log(e)); diff --git a/tests/auth.ts b/tests/auth.ts new file mode 100644 index 0000000..b875005 --- /dev/null +++ b/tests/auth.ts @@ -0,0 +1,13 @@ +import { offline } from '../src'; + +describe('Testing the offline authentication', () => { + test('Using Pierce as THE username', () => { + expect(offline('Pierce')).toStrictEqual({ + access_token: '882661dc-e54f-35ae-b9e7-6c691a8095cb', + client_token: '882661dc-e54f-35ae-b9e7-6c691a8095cb', + uuid: '882661dc-e54f-35ae-b9e7-6c691a8095cb', + name: 'Pierce', + user_properties: '{}', + }); + }); +}); diff --git a/tests/vanilla.ts b/tests/vanilla.ts new file mode 100644 index 0000000..e817fe7 --- /dev/null +++ b/tests/vanilla.ts @@ -0,0 +1,36 @@ +import { ChildProcessWithoutNullStreams } from 'node:child_process'; +import { existsSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { Client, Config } from '../src'; + +Config.setConfig('version', { number: '1.14.4', type: 'release' }); + +describe('Minecraft Vanilla', () => { + test( + 'Installation', + async () => { + await Client.install(); + expect(existsSync(resolve('./minecraft/cache/json/1.14.4.json'))).toBe(true); + expect(existsSync(resolve('./minecraft/natives/1.14.4'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.jar'))).toBe(true); + }, + 3 * 60 * 1000, + ); + + test( + 'Starting', + async () => { + const process = await Client.start(); + expect(process && typeof process.kill === 'function').toBe(true); + await new Promise((resolve) => { + setTimeout(() => { + (process as ChildProcessWithoutNullStreams).kill(); + resolve(); + }, 10 * 1000); + }); + expect(existsSync(resolve('./minecraft/saves'))).toBe(true); + expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); + }, + 3 * 60 * 1000, + ); +}); diff --git a/tsconfig.json b/tsconfig.json index 48cea65..ed87821 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,8 +17,8 @@ "resolveJsonModule": true, "strict": true, "target": "ESNext", - "types": ["node"] + "types": ["node", "jest"] }, "exclude": ["./build/"], - "include": ["./src/"] + "include": ["./src/", "./tests/"] } diff --git a/yarn.lock b/yarn.lock index 988fb2e..5171ac3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,7 +15,7 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.23.5": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== @@ -28,6 +28,27 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b" + integrity sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-module-transforms" "^7.23.3" + "@babel/helpers" "^7.24.0" + "@babel/parser" "^7.24.0" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.0" + "@babel/types" "^7.24.0" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/core@^7.21.8": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" @@ -49,7 +70,7 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.21.5", "@babel/generator@^7.23.6": +"@babel/generator@^7.21.5", "@babel/generator@^7.23.6", "@babel/generator@^7.7.2": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== @@ -108,6 +129,11 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" + integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== + "@babel/helper-simple-access@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" @@ -146,6 +172,15 @@ "@babel/traverse" "^7.23.9" "@babel/types" "^7.23.9" +"@babel/helpers@^7.24.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.0.tgz#a3dd462b41769c95db8091e49cfe019389a9409b" + integrity sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA== + dependencies: + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.0" + "@babel/types" "^7.24.0" + "@babel/highlight@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" @@ -155,11 +190,114 @@ chalk "^2.4.2" js-tokens "^4.0.0" +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.24.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" + integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== + "@babel/parser@^7.21.8", "@babel/parser@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" + integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" + integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== + dependencies: + "@babel/helper-plugin-utils" "^7.14.5" + +"@babel/plugin-syntax-typescript@^7.7.2": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" + integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== + dependencies: + "@babel/helper-plugin-utils" "^7.22.5" + "@babel/template@^7.22.15", "@babel/template@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" @@ -169,6 +307,15 @@ "@babel/parser" "^7.23.9" "@babel/types" "^7.23.9" +"@babel/template@^7.24.0", "@babel/template@^7.3.3": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" + integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.24.0" + "@babel/types" "^7.24.0" + "@babel/traverse@^7.21.5", "@babel/traverse@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" @@ -185,6 +332,31 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.24.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e" + integrity sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.24.0" + "@babel/types" "^7.24.0" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.0", "@babel/types@^7.3.3": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" + integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@babel/types@^7.21.5", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" @@ -194,6 +366,18 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -257,6 +441,214 @@ "@babel/types" "^7.21.5" semver "^7.5.2" +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== + dependencies: + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + ci-info "^3.2.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== + dependencies: + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== + dependencies: + jest-get-type "^29.6.3" + +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== + dependencies: + "@jest/types" "^29.6.3" + "@sinonjs/fake-timers" "^10.0.2" + "@types/node" "*" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/types" "^29.6.3" + jest-mock "^29.7.0" + +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + "@types/node" "*" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^6.0.0" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.1.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" + slash "^3.0.0" + string-length "^4.0.1" + strip-ansi "^6.0.0" + v8-to-istanbul "^9.0.1" + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jest/source-map@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" + integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== + dependencies: + "@jridgewell/trace-mapping" "^0.3.18" + callsites "^3.0.0" + graceful-fs "^4.2.9" + +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== + dependencies: + "@jest/console" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== + dependencies: + "@jest/test-result" "^29.7.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + slash "^3.0.0" + +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== + dependencies: + "@babel/core" "^7.11.6" + "@jest/types" "^29.6.3" + "@jridgewell/trace-mapping" "^0.3.18" + babel-plugin-istanbul "^6.1.1" + chalk "^4.0.0" + convert-source-map "^2.0.0" + fast-json-stable-stringify "^2.1.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + micromatch "^4.0.4" + pirates "^4.0.4" + slash "^3.0.0" + write-file-atomic "^4.0.2" + +"@jest/types@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" + integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== + dependencies: + "@jest/schemas" "^29.6.3" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.4" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz#9b18145d26cf33d08576cf4c7665b28554480ed7" @@ -266,7 +658,7 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== @@ -281,6 +673,22 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.23" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz#afc96847f3f07841477f303eed687707a5aacd80" @@ -315,6 +723,45 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@sinonjs/commons@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" + integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^10.0.2": + version "10.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" + integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== + dependencies: + "@sinonjs/commons" "^3.0.0" + +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + "@types/adm-zip@^0.5.5": version "0.5.5" resolved "https://registry.yarnpkg.com/@types/adm-zip/-/adm-zip-0.5.5.tgz#4588042726aa5f351d7ea88232e4a952f60e7c1a" @@ -322,6 +769,73 @@ dependencies: "@types/node" "*" +"@types/babel__core@^7.1.14": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" + integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== + dependencies: + "@babel/types" "^7.20.7" + +"@types/graceful-fs@^4.1.3": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" + integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== + dependencies: + "@types/node" "*" + +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" + integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== + +"@types/istanbul-lib-report@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" + integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" + integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/jest@^29.5.12": + version "29.5.12" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" + integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== + dependencies: + expect "^29.0.0" + pretty-format "^29.0.0" + "@types/json-schema@^7.0.12": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" @@ -344,11 +858,28 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== +"@types/stack-utils@^2.0.0": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" + integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== + "@types/uuid@^9.0.8": version "9.0.8" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== +"@types/yargs-parser@*": + version "21.0.3" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" + integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== + +"@types/yargs@^17.0.8": + version "17.0.32" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" + integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== + dependencies: + "@types/yargs-parser" "*" + "@typescript-eslint/eslint-plugin@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz#22bb999a8d59893c0ea07923e8a21f9d985ad740" @@ -445,7 +976,12 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.9.0: +acorn-walk@^8.1.1: + version "8.3.2" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" + integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + +acorn@^8.4.1, acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -465,6 +1001,13 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -477,13 +1020,38 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +anymatch@^3.0.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -508,6 +1076,66 @@ axios@^1.6.7: form-data "^4.0.0" proxy-from-env "^1.1.0" +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== + dependencies: + "@jest/transform" "^29.7.0" + "@types/babel__core" "^7.1.14" + babel-plugin-istanbul "^6.1.1" + babel-preset-jest "^29.6.3" + chalk "^4.0.0" + graceful-fs "^4.2.9" + slash "^3.0.0" + +babel-plugin-istanbul@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" + integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^5.0.4" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" + integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.1.14" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" + integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== + dependencies: + babel-plugin-jest-hoist "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -545,11 +1173,40 @@ browserslist@^4.22.2: node-releases "^2.0.14" update-browserslist-db "^1.0.13" +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== + dependencies: + fast-json-stable-stringify "2.x" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + caniuse-lite@^1.0.30001587: version "1.0.30001591" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz#16745e50263edc9f395895a7cd468b9f3767cf33" @@ -572,6 +1229,40 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + +ci-info@^3.2.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" + integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + +cjs-module-lexer@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" + integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== + +collect-v8-coverage@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" + integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -613,7 +1304,25 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -cross-spawn@^7.0.2: +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -622,23 +1331,48 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" +dedent@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" + integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +deepmerge@^4.2.2: + version "4.3.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -658,6 +1392,23 @@ electron-to-chromium@^1.4.668: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.683.tgz#b68167ed66dbea01feb86915aca92c09bc1b651a" integrity sha512-FmopjiJjkUzqa5F5Sv+wxd8KimtCxyLFOFgRPwEeMLVmP+vHH/GjNGCuIYrCIchbMSiOe+nG/OPBbR/XoExBNA== +emittery@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" + integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + escalade@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" @@ -668,6 +1419,11 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -752,6 +1508,11 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esquery@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" @@ -776,6 +1537,37 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +execa@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== + +expect@^29.0.0, expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -797,7 +1589,7 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -814,6 +1606,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +fb-watchman@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== + dependencies: + bser "2.1.1" + file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -828,6 +1627,14 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -869,11 +1676,36 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== +fsevents@^2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -888,7 +1720,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.3: +glob@^7.1.3, glob@^7.1.4: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -924,6 +1756,11 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -939,6 +1776,23 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +hasown@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" + integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== + dependencies: + function-bind "^1.1.2" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -952,6 +1806,14 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" +import-local@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" + integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -970,11 +1832,33 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + +is-core-module@^2.13.0: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -992,16 +1876,440 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-instrument@^5.0.4: + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== + dependencies: + "@babel/core" "^7.12.3" + "@babel/parser" "^7.14.7" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.2.0" + semver "^6.3.0" + +istanbul-lib-instrument@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz#91655936cf7380e4e473383081e38478b69993b1" + integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.3: + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== + dependencies: + execa "^5.0.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + dedent "^1.0.0" + is-generator-fn "^2.0.0" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + p-limit "^3.1.0" + pretty-format "^29.7.0" + pure-rand "^6.0.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== + dependencies: + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + chalk "^4.0.0" + create-jest "^29.7.0" + exit "^0.1.2" + import-local "^3.0.2" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + yargs "^17.3.1" + +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== + dependencies: + "@babel/core" "^7.11.6" + "@jest/test-sequencer" "^29.7.0" + "@jest/types" "^29.6.3" + babel-jest "^29.7.0" + chalk "^4.0.0" + ci-info "^3.2.0" + deepmerge "^4.2.2" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" + jest-get-type "^29.6.3" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + micromatch "^4.0.4" + parse-json "^5.2.0" + pretty-format "^29.7.0" + slash "^3.0.0" + strip-json-comments "^3.1.1" + +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== + dependencies: + detect-newline "^3.0.0" + +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + jest-get-type "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" + +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-mock "^29.7.0" + jest-util "^29.7.0" + +jest-get-type@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" + integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== + +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== + dependencies: + "@jest/types" "^29.6.3" + "@types/graceful-fs" "^4.1.3" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.9" + jest-regex-util "^29.6.3" + jest-util "^29.7.0" + jest-worker "^29.7.0" + micromatch "^4.0.4" + walker "^1.0.8" + optionalDependencies: + fsevents "^2.3.2" + +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== + dependencies: + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + jest-util "^29.7.0" + +jest-pnp-resolver@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== + +jest-regex-util@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" + integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== + +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== + dependencies: + jest-regex-util "^29.6.3" + jest-snapshot "^29.7.0" + +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== + dependencies: + chalk "^4.0.0" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-pnp-resolver "^1.2.2" + jest-util "^29.7.0" + jest-validate "^29.7.0" + resolve "^1.20.0" + resolve.exports "^2.0.0" + slash "^3.0.0" + +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== + dependencies: + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.13.1" + graceful-fs "^4.2.9" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" + p-limit "^3.1.0" + source-map-support "0.5.13" + +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== + dependencies: + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" + "@jest/source-map" "^29.6.3" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + cjs-module-lexer "^1.0.0" + collect-v8-coverage "^1.0.0" + glob "^7.1.3" + graceful-fs "^4.2.9" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-regex-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + slash "^3.0.0" + strip-bom "^4.0.0" + +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== + dependencies: + "@babel/core" "^7.11.6" + "@babel/generator" "^7.7.2" + "@babel/plugin-syntax-jsx" "^7.7.2" + "@babel/plugin-syntax-typescript" "^7.7.2" + "@babel/types" "^7.3.3" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" + "@jest/types" "^29.6.3" + babel-preset-current-node-syntax "^1.0.0" + chalk "^4.0.0" + expect "^29.7.0" + graceful-fs "^4.2.9" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + natural-compare "^1.4.0" + pretty-format "^29.7.0" + semver "^7.5.3" + +jest-util@^29.0.0, jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== + dependencies: + "@jest/types" "^29.6.3" + camelcase "^6.2.0" + chalk "^4.0.0" + jest-get-type "^29.6.3" + leven "^3.1.0" + pretty-format "^29.7.0" + +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== + dependencies: + "@jest/test-result" "^29.7.0" + "@jest/types" "^29.6.3" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + emittery "^0.13.1" + jest-util "^29.7.0" + string-length "^4.0.1" + +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== + dependencies: + "@types/node" "*" + jest-util "^29.7.0" + merge-stream "^2.0.0" + supports-color "^8.0.0" + +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== + dependencies: + "@jest/core" "^29.7.0" + "@jest/types" "^29.6.3" + import-local "^3.0.2" + jest-cli "^29.7.0" + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -1019,6 +2327,11 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -1041,6 +2354,16 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -1049,6 +2372,18 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -1056,6 +2391,11 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" @@ -1075,6 +2415,30 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@1.x, make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +makeerror@1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" + integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== + dependencies: + tmpl "1.0.5" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -1100,6 +2464,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -1107,7 +2476,7 @@ minimatch@9.0.3: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -1124,11 +2493,28 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== + node-releases@^2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1136,6 +2522,13 @@ once@^1.3.0: dependencies: wrappy "1" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -1148,13 +2541,27 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" -p-limit@^3.0.2: +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -1162,6 +2569,11 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -1169,6 +2581,16 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-json@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -1179,11 +2601,16 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^3.1.0: +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -1194,11 +2621,23 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pirates@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" + integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -1216,6 +2655,23 @@ prettier@^3.2.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== +pretty-format@^29.0.0, pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +prompts@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" + integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -1226,16 +2682,57 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +pure-rand@^6.0.0: + version "6.0.4" + resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" + integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve.exports@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" + integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== + +resolve@^1.20.0: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -1255,12 +2752,12 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -semver@^6.3.1: +semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.2, semver@^7.5.4: +semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== @@ -1279,18 +2776,80 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -strip-ansi@^6.0.1: +source-map-support@0.5.13: + version "0.5.13" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" + integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0, source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stack-utils@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== + dependencies: + escape-string-regexp "^2.0.0" + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -1310,6 +2869,18 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + synckit@^0.8.6: version "0.8.8" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" @@ -1318,11 +2889,25 @@ synckit@^0.8.6: "@pkgr/core" "^0.1.0" tslib "^2.6.2" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +tmpl@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -1340,6 +2925,39 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA== +ts-jest@^29.1.2: + version "29.1.2" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" + integrity sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g== + dependencies: + bs-logger "0.x" + fast-json-stable-stringify "2.x" + jest-util "^29.0.0" + json5 "^2.2.3" + lodash.memoize "4.x" + make-error "1.x" + semver "^7.5.3" + yargs-parser "^21.0.1" + +ts-node@^10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" @@ -1352,11 +2970,21 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + typescript@^5.3.3: version "5.3.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" @@ -1387,6 +3015,27 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +v8-to-istanbul@^9.0.1: + version "9.2.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +walker@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" + integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== + dependencies: + makeerror "1.0.12" + which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -1394,11 +3043,33 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== +write-file-atomic@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" + integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== + dependencies: + imurmurhash "^0.1.4" + signal-exit "^3.0.7" + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -1409,6 +3080,29 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== +yargs-parser@^21.0.1, yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.3.1: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" From 6dffaab65c07364121d809d2cc1399a609dd756f Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Fri, 8 Mar 2024 15:41:29 +0300 Subject: [PATCH 29/97] Whoops --- tests/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auth.ts b/tests/auth.ts index b875005..b297a38 100644 --- a/tests/auth.ts +++ b/tests/auth.ts @@ -1,7 +1,7 @@ import { offline } from '../src'; describe('Testing the offline authentication', () => { - test('Using Pierce as THE username', () => { + test('Using Pierce as the username', () => { expect(offline('Pierce')).toStrictEqual({ access_token: '882661dc-e54f-35ae-b9e7-6c691a8095cb', client_token: '882661dc-e54f-35ae-b9e7-6c691a8095cb', From 7d1ba38ef8b461616464ef8fc014ccbe200920b3 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 9 Mar 2024 19:46:34 +0300 Subject: [PATCH 30/97] Legacy and modern versions testing --- tests/vanilla.ts | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/tests/vanilla.ts b/tests/vanilla.ts index e817fe7..a30f170 100644 --- a/tests/vanilla.ts +++ b/tests/vanilla.ts @@ -3,9 +3,41 @@ import { existsSync } from 'node:fs'; import { resolve } from 'node:path'; import { Client, Config } from '../src'; -Config.setConfig('version', { number: '1.14.4', type: 'release' }); +describe('Minecraft Vanilla Legacy (1.8.9)', () => { + Config.setConfig('version', { number: '1.8.9', type: 'release' }); + + test( + 'Installation', + async () => { + await Client.install(); + expect(existsSync(resolve('./minecraft/cache/json/1.8.9.json'))).toBe(true); + expect(existsSync(resolve('./minecraft/natives/1.8.9'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.jar'))).toBe(true); + }, + 3 * 60 * 1000, + ); + + test( + 'Starting', + async () => { + const process = await Client.start(); + expect(process && typeof process.kill === 'function').toBe(true); + await new Promise((resolve) => { + setTimeout(() => { + (process as ChildProcessWithoutNullStreams).kill(); + resolve(); + }, 10 * 1000); + }); + expect(existsSync(resolve('./minecraft/saves'))).toBe(true); + expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); + }, + 3 * 60 * 1000, + ); +}); + +describe('Minecraft Vanilla Modern (1.14.4)', () => { + Config.setConfig('version', { number: '1.14.4', type: 'release' }); -describe('Minecraft Vanilla', () => { test( 'Installation', async () => { From 5bf5608f2e0f9b62adf1a731c7695f7255f8df71 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 9 Mar 2024 19:49:44 +0300 Subject: [PATCH 31/97] Change imports of config --- src/index.ts | 2 +- tests/vanilla.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index 04d9d86..88a5fd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ export * as Client from './launcher'; export { default as offline } from './authenticator'; -export * as Config from './utils/config'; +export * from './utils/config'; export { onLog } from './utils/log'; diff --git a/tests/vanilla.ts b/tests/vanilla.ts index a30f170..c802260 100644 --- a/tests/vanilla.ts +++ b/tests/vanilla.ts @@ -1,10 +1,10 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process'; import { existsSync } from 'node:fs'; import { resolve } from 'node:path'; -import { Client, Config } from '../src'; +import { Client, setConfig } from '../src'; describe('Minecraft Vanilla Legacy (1.8.9)', () => { - Config.setConfig('version', { number: '1.8.9', type: 'release' }); + setConfig('version', { number: '1.8.9', type: 'release' }); test( 'Installation', @@ -36,7 +36,7 @@ describe('Minecraft Vanilla Legacy (1.8.9)', () => { }); describe('Minecraft Vanilla Modern (1.14.4)', () => { - Config.setConfig('version', { number: '1.14.4', type: 'release' }); + setConfig('version', { number: '1.14.4', type: 'release' }); test( 'Installation', From 66b92eca4d6a0ea6ed212038780374b6f8b678c0 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 9 Mar 2024 19:53:24 +0300 Subject: [PATCH 32/97] Remove tests from tsconfig --- src/handler.ts | 1 - tsconfig.json | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 43e49f6..5a03961 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -534,7 +534,6 @@ const downloadToDirectory = async ( return libs; }; -// TODO: figure out the right type const getClasses = async (classJson: { id: string; mainClass: string; diff --git a/tsconfig.json b/tsconfig.json index ed87821..a64ece2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,5 +20,5 @@ "types": ["node", "jest"] }, "exclude": ["./build/"], - "include": ["./src/", "./tests/"] + "include": ["./src/"] } From 27929b7fc76a5f04fdb67d0adb29020dfad122bd Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 9 Mar 2024 22:42:40 +0300 Subject: [PATCH 33/97] [WIP] Fix types (not working) --- src/handler.ts | 50 +++++++++++----------------------------------- src/utils/types.ts | 21 +++++++++++++------ 2 files changed, 27 insertions(+), 44 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 5a03961..22f67ca 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -17,7 +17,7 @@ import axios from 'axios'; import { checkSum, cleanUp, getOS, isLegacy, popString } from './utils'; import { config, setConfig } from './utils/config'; import { log } from './utils/log'; -import { artifactType, customArtifactType, Fields, libType, Version } from './utils/types'; +import { artifactType, customArtifactType, customLibType, Fields, libType, Version } from './utils/types'; let counter = 0; let parsedVersion: Version; @@ -420,6 +420,7 @@ const getForgedWrapped = async () => { // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. await Promise.all( json.libraries.map(async (library: any) => { + console.log(library); const lib = library.name.split(':'); if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; if (!library.url && !(library.serverreq || library.clientreq)) return; @@ -534,23 +535,8 @@ const downloadToDirectory = async ( return libs; }; -const getClasses = async (classJson: { - id: string; - mainClass: string; - arguments: { - game: string[]; - jvm: string[]; - }; - mavenFiles?: any; - libraries: { - name: string; - url: string; - sha1?: string; - size?: number; - }[]; -}) => { +const getClasses = async (classJson: customLibType) => { let libs: string[] = []; - const libraryDirectory = resolve(config.libraryRoot || join(config.root, 'libraries')); if (classJson) { @@ -595,21 +581,14 @@ const formatQuickPlay = () => { return returnArgs; }; -// TODO: figure out the right type -const getLaunchOptions = async (modification: any) => { +const getLaunchOptions = async (modification: customLibType) => { const type = Object.assign({}, parsedVersion, modification); - - let args = type.minecraftArguments ? type.minecraftArguments.split(' ') : type.arguments.game; + let args = type.arguments.game; const assetRoot = join(resolve(config.assetRoot || join(config.root, 'assets'))); const assetPath = isLegacy(parsedVersion) ? join(config.root, 'resources') : join(assetRoot); const minArgs = config.minArgs || isLegacy(parsedVersion) ? 5 : 11; - if (args.length < minArgs) - args = args.concat( - parsedVersion.minecraftArguments - ? parsedVersion.minecraftArguments.split(' ') - : parsedVersion.arguments.game, - ); + if (args.length < minArgs) args = args.concat(parsedVersion.arguments.game); if (config.customLaunchArgs) args = args.concat(config.customLaunchArgs); config.authorization = await Promise.resolve(config.authorization); @@ -637,7 +616,7 @@ const getLaunchOptions = async (modification: any) => { args.push('--demo'); const replaceArg = (obj: { value: string | string[] }, index: number) => { - if (!Array.isArray(obj.value)) { + if (Array.isArray(obj.value)) { for (const arg of obj.value) args.push(arg); } else { args.push(obj.value); @@ -650,15 +629,11 @@ const getLaunchOptions = async (modification: any) => { if (args[index].rules) { if (!config.features) continue; const featureFlags = []; - for (const rule of args[index].rules) { - featureFlags.push(...Object.keys(rule.features)); - } + for (const rule of args[index].rules) featureFlags.push(...Object.keys(rule.features)); + let hasAllRules = true; - for (const feature of config.features) { - if (!featureFlags.includes(feature)) { - hasAllRules = false; - } - } + for (const feature of config.features) if (!featureFlags.includes(feature)) hasAllRules = false; + if (hasAllRules) replaceArg(args[index], index); } else { replaceArg(args[index], index); @@ -677,7 +652,7 @@ const getLaunchOptions = async (modification: any) => { } } if (config.quickPlay) args = args.concat(formatQuickPlay()); - if (config.proxy) { + if (config.proxy) args.push( '--proxyHost', config.proxy.host, @@ -688,7 +663,6 @@ const getLaunchOptions = async (modification: any) => { '--proxyPass', config.proxy.password, ); - } args = args.filter((value: string | number) => typeof value === 'string' || typeof value === 'number'); log('debug', 'Set launch options'); return args; diff --git a/src/utils/types.ts b/src/utils/types.ts index f49c366..f41b586 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -173,7 +173,6 @@ export interface Options { resource?: string; }; logj4ConfigurationFile?: string; - authorization: Promise | User; /** * Path of json cache. @@ -199,6 +198,11 @@ export interface User { }; } +type Rule = { + action: string; + features: Record; +}; + export type artifactType = { path: string; sha1: string; @@ -238,10 +242,13 @@ export type customLibType = { id: string; mainClass: string; arguments: { - game: string[]; - jvm: string[]; + game: string | Rule | string[]; + jvm: string | Rule | string[]; }; - mavenFiles?: any; + mavenFiles?: { + name: string; + url: string; + }[]; libraries: customArtifactType[]; }; @@ -264,8 +271,10 @@ export interface Version { }; id: string; libraries: libType[]; - minecraftArguments?: any; - arguments?: any; + arguments: { + game: string | Rule | string[]; + jvm: string | Rule | string[]; + }; type: string; mainClass: string; } From 2645cf56d3f704d08d0ce1ef030885ef3c027c12 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 11 Mar 2024 13:36:57 +0300 Subject: [PATCH 34/97] Save for later to rework on --- src/handler.ts | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 22f67ca..b6a1051 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -582,8 +582,8 @@ const formatQuickPlay = () => { }; const getLaunchOptions = async (modification: customLibType) => { - const type = Object.assign({}, parsedVersion, modification); - let args = type.arguments.game; + const initialArgs = Object.assign({}, parsedVersion, modification).arguments.game; + let args = ''; const assetRoot = join(resolve(config.assetRoot || join(config.root, 'assets'))); const assetPath = isLegacy(parsedVersion) ? join(config.root, 'resources') : join(assetRoot); @@ -615,34 +615,6 @@ const getLaunchOptions = async (modification: customLibType) => { if (config.authorization.meta.demo && (config.features ? !config.features.includes('is_demo_user') : true)) args.push('--demo'); - const replaceArg = (obj: { value: string | string[] }, index: number) => { - if (Array.isArray(obj.value)) { - for (const arg of obj.value) args.push(arg); - } else { - args.push(obj.value); - } - delete args[index]; - }; - - for (let index = 0; index < args.length; index++) { - if (typeof args[index] === 'object') { - if (args[index].rules) { - if (!config.features) continue; - const featureFlags = []; - for (const rule of args[index].rules) featureFlags.push(...Object.keys(rule.features)); - - let hasAllRules = true; - for (const feature of config.features) if (!featureFlags.includes(feature)) hasAllRules = false; - - if (hasAllRules) replaceArg(args[index], index); - } else { - replaceArg(args[index], index); - } - } else { - if (Object.keys(fields).includes(args[index] as keyof Fields)) - args[index] = fields[args[index] as keyof Fields]; - } - } if (config.window) { if (config.window.fullscreen) { args.push('--fullscreen'); @@ -651,6 +623,7 @@ const getLaunchOptions = async (modification: customLibType) => { if (config.window.height) args.push('--height', config.window.height); } } + if (config.quickPlay) args = args.concat(formatQuickPlay()); if (config.proxy) args.push( @@ -663,7 +636,8 @@ const getLaunchOptions = async (modification: customLibType) => { '--proxyPass', config.proxy.password, ); - args = args.filter((value: string | number) => typeof value === 'string' || typeof value === 'number'); + + args = args.filter((value: any) => typeof value === 'string' || typeof value === 'number'); log('debug', 'Set launch options'); return args; }; From ca0d10d4fcf7705033e64b9951114f506efd3cfc Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 11 Mar 2024 22:27:11 +0300 Subject: [PATCH 35/97] Finish the rewrite --- src/handler.ts | 202 +++++++++++++++++++++++---------------------- src/launcher.ts | 22 +++-- src/utils/types.ts | 7 +- 3 files changed, 116 insertions(+), 115 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index b6a1051..1b0b9d3 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -17,7 +17,7 @@ import axios from 'axios'; import { checkSum, cleanUp, getOS, isLegacy, popString } from './utils'; import { config, setConfig } from './utils/config'; import { log } from './utils/log'; -import { artifactType, customArtifactType, customLibType, Fields, libType, Version } from './utils/types'; +import { artifactType, customArtifactType, customLibType, Fields, libType, Rule, Version } from './utils/types'; let counter = 0; let parsedVersion: Version; @@ -75,10 +75,7 @@ const downloadAsync = async (url: string, directory: string, name: string, retry await new Promise((resolve) => { file.on('finish', resolve); file.on('error', async (e) => { - log( - 'debug', - `Failed to download asset to ${join(directory, name)} due to\n${e}.` + ` Retrying... ${retry}`, - ); + log('debug', `Failed to download asset to ${join(directory, name)} due to\n${e}. Retrying... ${retry}`); if (existsSync(join(directory, name))) unlinkSync(join(directory, name)); if (retry) await downloadAsync(url, directory, name, false, type); return resolve(e); @@ -324,6 +321,12 @@ const fwAddArgs = () => { return; }; +// I don't see a better way of putting anything else (for now) +const isModern = (json: any): boolean => + json.inheritsFrom && + json.inheritsFrom.split('.')[1] >= 12 && + !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847'); + const getForgedWrapped = async () => { let json = null; let installerJson = null; @@ -333,20 +336,12 @@ const getForgedWrapped = async () => { if (existsSync(versionPath)) { try { json = JSON.parse(readFileSync(versionPath).toString()); - if (!json.forgeWrapperVersion || !(json.forgeWrapperVersion === '1.6.0')) { - log('debug', 'Old ForgeWrapper has generated this version JSON, re-generating'); - } else { - // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. - if ( - json.inheritsFrom && - json.inheritsFrom.split('.')[1] >= 12 && - !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') - ) { - fwAddArgs(); - setConfig('forge', undefined); - } - return json; + // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. + if (isModern(json)) { + fwAddArgs(); + setConfig('forge', undefined); } + return json; } catch (e) { console.warn(e); log('debug', 'Failed to parse Forge version JSON, re-generating'); @@ -356,8 +351,8 @@ const getForgedWrapped = async () => { log('debug', 'Generating Forge version json, this might take a bit'); const zipFile = new Zip(config.forge); json = zipFile.readAsText('version.json'); - if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); + if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); try { json = JSON.parse(json); if (installerJson) installerJson = JSON.parse(installerJson); @@ -366,20 +361,15 @@ const getForgedWrapped = async () => { return null; } // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. - if (installerJson) { + if (installerJson) json.mavenFiles ? (json.mavenFiles = json.mavenFiles.concat(installerJson.libraries)) : (json.mavenFiles = installerJson.libraries); - } // Holder for the specifc jar ending which depends on the specifc forge version. let jarEnding = 'universal'; // We need to handle modern forge differently than legacy. - if ( - json.inheritsFrom && - json.inheritsFrom.split('.')[1] >= 12 && - !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') - ) { + if (isModern(json)) { // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. if (json.inheritsFrom !== '1.12.2') { fwAddArgs(); @@ -401,8 +391,7 @@ const getForgedWrapped = async () => { for (const library of json.mavenFiles) { const lib = library.name.split(':'); if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - library.downloads.artifact.url = - 'https://files.minecraftforge.net/maven/' + library.downloads.artifact.path; + library.downloads.artifact.url = `https://files.minecraftforge.net/maven/${library.downloads.artifact.path}`; break; } } @@ -419,30 +408,31 @@ const getForgedWrapped = async () => { } else { // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. await Promise.all( - json.libraries.map(async (library: any) => { - console.log(library); - const lib = library.name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; - if (!library.url && !(library.serverreq || library.clientreq)) return; - - library.url = library.url - ? 'https://files.minecraftforge.net/maven/' - : 'https://libraries.minecraft.net/'; - const downloadLink = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${lib[1]}-${lib[2]}.jar`; - // Checking if the file still exists on Forge's server, if not, replace it with the fallback. - // Not checking for sucess, only if it 404s. - await axios - .get(downloadLink, { - timeout: config.timeout || 50000, - httpAgent: new http({ maxSockets: config.maxSockets || 2 }), - httpsAgent: new https({ maxSockets: config.maxSockets || 2 }), - }) - .then( - ({ status }) => - status === 404 && (library.url = 'https://search.maven.org/remotecontent?filepath='), - ) - .catch(() => log('debug', `Failed checking request for ${downloadLink}`)); - }), + json.libraries.map( + async (library: { name: string; url?: string; serverreq: boolean; clientreq?: boolean }) => { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; + if (!library.url && !(library.serverreq || library.clientreq)) return; + + library.url = library.url + ? 'https://files.minecraftforge.net/maven/' + : 'https://libraries.minecraft.net/'; + const downloadLink = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${lib[1]}-${lib[2]}.jar`; + // Checking if the file still exists on Forge's server, if not, replace it with the fallback. + // Not checking for sucess, only if it 404s. + await axios + .get(downloadLink, { + timeout: config.timeout || 50000, + httpAgent: new http({ maxSockets: config.maxSockets || 2 }), + httpsAgent: new https({ maxSockets: config.maxSockets || 2 }), + }) + .then( + ({ status }) => + status === 404 && (library.url = 'https://search.maven.org/remotecontent?filepath='), + ) + .catch(() => log('debug', `Failed checking request for ${downloadLink}`)); + }, + ), ); } // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. @@ -450,13 +440,12 @@ const getForgedWrapped = async () => { if (json.libraries[0].downloads) { const name = json.libraries[0].name; if (name.includes('minecraftforge:forge') && !name.includes('universal')) { - json.libraries[0].name = name + `:${jarEnding}`; + json.libraries[0].name = `${name}:${jarEnding}`; json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.replace( '.jar', `-${jarEnding}.jar`, ); - json.libraries[0].downloads.artifact.url = - 'https://files.minecraftforge.net/maven/' + json.libraries[0].downloads.artifact.path; + json.libraries[0].downloads.artifact.url = `https://files.minecraftforge.net/maven/${json.libraries[0].downloads.artifact.path}`; } } else { delete json.libraries[0]; @@ -503,7 +492,7 @@ const downloadToDirectory = async ( library.downloads.artifact.path.split('/')[library.downloads.artifact.path.split('/').length - 1]; jarPath = join(directory, popString(library.downloads.artifact.path)); } else { - name = `${lib[1]}-${lib[2]}${lib[3] ? '-' + lib[3] : ''}.jar`; + name = `${lib[1]}-${lib[2]}${lib[3] ? `-${lib[3]}` : ''}.jar`; jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); } @@ -558,38 +547,29 @@ const getClasses = async (classJson: customLibType) => { return libs; }; -const formatQuickPlay = () => { - if (!config.quickPlay) return; +const processArguments = (...args: (string | Rule | string[])[]): string[] => { + const result: string[] = []; + args.forEach((arg) => { + if (Array.isArray(arg)) { + result.push(...arg); + } else if (typeof arg === 'string') { + result.push(arg); + } + }); - const types = { - singleplayer: '--quickPlaySingleplayer', - multiplayer: '--quickPlayMultiplayer', - realms: '--quickPlayRealms', - legacy: null, - }; - const { type, identifier, path } = config.quickPlay; - const keys = Object.keys(types); - if (!keys.includes(type)) { - log('debug', `quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); - return null; - } - const returnArgs = - type === 'legacy' - ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] - : [types[type], identifier]; - if (path) returnArgs.push('--quickPlayPath', path); - return returnArgs; + return result; }; -const getLaunchOptions = async (modification: customLibType) => { - const initialArgs = Object.assign({}, parsedVersion, modification).arguments.game; - let args = ''; - const assetRoot = join(resolve(config.assetRoot || join(config.root, 'assets'))); - const assetPath = isLegacy(parsedVersion) ? join(config.root, 'resources') : join(assetRoot); +const getLaunchOptions = async (modification: customLibType | null): Promise => { + const type = Object.assign({}, parsedVersion, modification); + const args = type.minecraftArguments ? type.minecraftArguments.split(' ') : processArguments(type.arguments.game); + const assetPath = resolve( + isLegacy(parsedVersion) + ? join(config.root, 'resources') + : join(config.assetRoot || join(config.root, 'assets')), + ); - const minArgs = config.minArgs || isLegacy(parsedVersion) ? 5 : 11; - if (args.length < minArgs) args = args.concat(parsedVersion.arguments.game); - if (config.customLaunchArgs) args = args.concat(config.customLaunchArgs); + if (config.customLaunchArgs) args.concat(config.customLaunchArgs); config.authorization = await Promise.resolve(config.authorization); config.authorization.meta = config.authorization.meta ?? { demo: false, type: 'mojang' }; @@ -619,27 +599,49 @@ const getLaunchOptions = async (modification: customLibType) => { if (config.window.fullscreen) { args.push('--fullscreen'); } else { - if (config.window.width) args.push('--width', config.window.width); - if (config.window.height) args.push('--height', config.window.height); + if (config.window.width) args.push('--width', config.window.width.toString()); + if (config.window.height) args.push('--height', config.window.height.toString()); } } - if (config.quickPlay) args = args.concat(formatQuickPlay()); - if (config.proxy) - args.push( - '--proxyHost', - config.proxy.host, - '--proxyPort', - config.proxy.port || '8080', - '--proxyUser', - config.proxy.username, - '--proxyPass', - config.proxy.password, - ); + if (config.quickPlay) { + const types = { + singleplayer: '--quickPlaySingleplayer', + multiplayer: '--quickPlayMultiplayer', + realms: '--quickPlayRealms', + legacy: null, + }; + + const { type, identifier, path } = config.quickPlay; + const keys = Object.keys(types); + if (!keys.includes(type)) { + log('debug', `quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); + } else { + const returnArgs = + type === 'legacy' + ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] + : [types[type], identifier]; + + if (path) returnArgs.push('--quickPlayPath', path); + args.concat(returnArgs); + } + } + + if (config.proxy) { + args.push('--proxyHost', config.proxy.host, '--proxyPort', config.proxy.port || '8080'); + + if (config.proxy.username) args.push('--proxyUser', config.proxy.username); + if (config.proxy.password) args.push('--proxyPass', config.proxy.password); + } - args = args.filter((value: any) => typeof value === 'string' || typeof value === 'number'); log('debug', 'Set launch options'); - return args; + return args.map((arg) => + Object.entries(fields).reduce( + (acc, [placeholder, replacement]) => + acc.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), replacement), + arg, + ), + ); }; const getJVM = async () => diff --git a/src/launcher.ts b/src/launcher.ts index 0d60f83..8517da4 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -107,11 +107,11 @@ export const start = async () => { ); } else if (config.forge) { setConfig('forge', resolve(config.forge)); - log('debug', '[MCLC]: Detected Forge in options, getting dependencies'); + log('debug', 'Detected Forge in options, getting dependencies'); modifyJson = await getForgedWrapped(); } - let jvm = [ + const jvm = [ '-XX:-UseAdaptiveSizePolicy', '-XX:-OmitStackTraceInFastThrow', '-Dfml.ignorePatchDiscrepancies=true', @@ -124,10 +124,8 @@ export const start = async () => { if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await getJVM()); } else jvm.push(await getJVM()); - if (config.customArgs) jvm = jvm.concat(config.customArgs); - if (config.logj4ConfigurationFile) { - jvm.push(`-Dlog4j.configurationFile=${resolve(config.logj4ConfigurationFile)}`); - } + if (config.customArgs) jvm.concat(config.customArgs); + if (config.logj4ConfigurationFile) jvm.push(`-Dlog4j.configurationFile=${resolve(config.logj4ConfigurationFile)}`); // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); @@ -144,7 +142,7 @@ export const start = async () => { true, 'log4j', ); - jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml'); + jvm.push(`-Dlog4j.configurationFile=${resolve(join(configPath, 'log4j2_112-116.xml'))}`); } else if (intVersion >= 7) { await downloadAsync( 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', @@ -153,7 +151,7 @@ export const start = async () => { true, 'log4j', ); - jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml'); + jvm.push(`-Dlog4j.configurationFile=${resolve(join(configPath, 'log4j2_17-111.xml'))}`); } } } @@ -166,9 +164,9 @@ export const start = async () => { const file = modifyJson || versionFile; // So mods like fabric work. const jar = existsSync(mcPath) - ? `${separator}${mcPath}` - : `${separator}${join(directory, `${config.version.number}.jar`)}`; - classPaths.push(`${config.forge ? config.forge + separator : ''}${classes.join(separator)}${jar}`); + ? `${separator}${resolve(mcPath)}` + : `${separator}${resolve(join(directory, `${config.version.number}.jar`))}`; + classPaths.push(`${config.forge ? `${config.forge}${separator}` : ''}${classes.join(separator)}${jar}`); classPaths.push(file.mainClass); const launchconfig = await getLaunchOptions(modifyJson); @@ -176,7 +174,7 @@ export const start = async () => { log('arguments', launchArguments); log('debug', `Launching with arguments ${launchArguments.join(' ')}`); - const minecraft = spawn(config.javaPath ? config.javaPath : 'java', launchArguments, { + const minecraft = spawn(config.javaPath ?? 'java', launchArguments, { detached: config.detached, }); minecraft.stdout.on('data', (data) => log('data', data.toString('utf-8'))); diff --git a/src/utils/types.ts b/src/utils/types.ts index f41b586..d333007 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -198,7 +198,7 @@ export interface User { }; } -type Rule = { +export type Rule = { action: string; features: Record; }; @@ -271,10 +271,11 @@ export interface Version { }; id: string; libraries: libType[]; - arguments: { + arguments?: { game: string | Rule | string[]; - jvm: string | Rule | string[]; + jvm?: string | Rule | string[]; }; + minecraftArguments?: string; type: string; mainClass: string; } From c30b022cceb59724db997d0ad155d2fe78a1c62d Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 11 Mar 2024 22:57:13 +0300 Subject: [PATCH 36/97] v3.19.0 --- src/mclc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mclc.ts b/src/mclc.ts index 6e19b9f..81e1dd6 100644 --- a/src/mclc.ts +++ b/src/mclc.ts @@ -1,2 +1,2 @@ // Should be changed each update -export default '3.18.0'; +export default '3.19.0'; From ded6c3e6f8c3d2855cc9bf65447c9bb7edbc9532 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 11 Mar 2024 22:57:30 +0300 Subject: [PATCH 37/97] Formatting --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e7d616..b8ad6c7 100644 --- a/package.json +++ b/package.json @@ -58,4 +58,4 @@ "ts-node": "^10.9.2", "typescript": "^5.3.3" } -} \ No newline at end of file +} From 4561da623700aed9a6bef41ce56c1b3a5773997f Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 11:59:55 +0300 Subject: [PATCH 38/97] Remove JSX from ESLint (accidentally added) --- .eslintrc.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 0e60326..f75825f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -3,9 +3,6 @@ module.exports = { parser: '@typescript-eslint/parser', parserOptions: { ecmaVersion: 'latest', - ecmaFeatures: { - jsx: true, - }, project: './tsconfig.json', tsconfigRootDir: './', }, From 08dd92bc8eae296eea3449db297d65645ffa0a61 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 12:05:26 +0300 Subject: [PATCH 39/97] Use .cjs instead of .js for ESLint https://eslint.org/docs/latest/use/configure/configuration-files#configuration-file-formats --- .eslintignore | 4 +++- .eslintrc.js => .eslintrc.cjs | 0 2 files changed, 3 insertions(+), 1 deletion(-) rename .eslintrc.js => .eslintrc.cjs (100%) diff --git a/.eslintignore b/.eslintignore index dcfc405..b0993f6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1,3 @@ -jest.config.ts \ No newline at end of file +jest.config.ts +tests/ +build/ \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.cjs similarity index 100% rename from .eslintrc.js rename to .eslintrc.cjs From aa399167956e61fd70cc9b17fd4ee8a389c75e11 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 14:33:29 +0300 Subject: [PATCH 40/97] [WIP] Rework on the config system --- src/handler.ts | 26 ++++++++++++++++---------- src/launcher.ts | 10 +++++----- src/utils/config.ts | 24 +++++++++++------------- src/utils/types.ts | 2 +- 4 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 1b0b9d3..a1524be 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -15,7 +15,7 @@ import { join, resolve, sep } from 'node:path'; import Zip from 'adm-zip'; import axios from 'axios'; import { checkSum, cleanUp, getOS, isLegacy, popString } from './utils'; -import { config, setConfig } from './utils/config'; +import { config } from './utils/config'; import { log } from './utils/log'; import { artifactType, customArtifactType, customLibType, Fields, libType, Rule, Version } from './utils/types'; @@ -101,7 +101,7 @@ const getVersion = async () => { return parsedVersion; } - const manifest = `${config.url?.meta}/mc/game/version_manifest.json`; + const manifest = `${config.url.meta}/mc/game/version_manifest.json`; const cache = config.cache ? `${config.cache}/json` : `${config.root}/cache/json`; const { data } = await axios.get(manifest); @@ -168,7 +168,7 @@ const getAssets = async () => { const subAsset = join(assetDirectory, 'objects', subhash); if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) - await downloadAsync(`${config.url?.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets'); + await downloadAsync(`${config.url.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets'); counter++; log('progress', { type: 'assets', @@ -315,8 +315,8 @@ const fwAddArgs = () => { `-Dforgewrapper.minecraft=${resolve(join(config.directory!, `${config.version.number}.jar`))}`, ]; config.customArgs - ? setConfig('customArgs', config.customArgs.concat(forgeWrapperAgrs)) - : setConfig('customArgs', forgeWrapperAgrs); + ? (config.customArgs = config.customArgs.concat(forgeWrapperAgrs)) + : (config.customArgs = forgeWrapperAgrs); return; }; @@ -339,7 +339,7 @@ const getForgedWrapped = async () => { // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. if (isModern(json)) { fwAddArgs(); - setConfig('forge', undefined); + config.forge = undefined; } return json; } catch (e) { @@ -467,7 +467,7 @@ const getForgedWrapped = async () => { json.inheritsFrom.split('.')[1] >= 12 && !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') ) - setConfig('forge', undefined); + config.forge = undefined; return json; }; @@ -551,7 +551,7 @@ const processArguments = (...args: (string | Rule | string[])[]): string[] => { const result: string[] = []; args.forEach((arg) => { if (Array.isArray(arg)) { - result.push(...arg); + result.push(...arg.filter((item) => typeof item !== 'object')); } else if (typeof arg === 'string') { result.push(arg); } @@ -655,7 +655,10 @@ const getMemory = () => { if (typeof config.memory.min === 'number' && typeof config.memory.max === 'number') { if (config.memory.max < config.memory.min) { log('debug', 'MIN memory is higher then MAX! Resetting!'); - setConfig('memory', { min: Math.pow(2, 9), max: Math.pow(2, 10) }); + config.memory = { + min: Math.pow(2, 9), + max: Math.pow(2, 10), + }; } return [`${config.memory.max}M`, `${config.memory.min}M`]; } else if (typeof config.memory.min === 'string' && typeof config.memory.max === 'string') { @@ -665,7 +668,10 @@ const getMemory = () => { 'debug', `MIN memory is a ${typeof config.memory.min} while MAX is ${typeof config.memory.max}! Resetting!`, ); - setConfig('memory', { min: Math.pow(2, 9), max: Math.pow(2, 10) }); + config.memory = { + min: Math.pow(2, 9), + max: Math.pow(2, 10), + }; return [`${config.memory.max}M`, `${config.memory.min}M`]; } }; diff --git a/src/launcher.ts b/src/launcher.ts index 8517da4..6cb19d0 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -16,7 +16,7 @@ import { } from './handler'; import mclc from './mclc'; import { cleanUp, getOS } from './utils'; -import { config, setConfig } from './utils/config'; +import { config, defineOptions } from './utils/config'; import { log } from './utils/log'; export const launch = () => { @@ -34,12 +34,12 @@ export const install = async () => { } if (config.gameDirectory) { - setConfig('gameDirectory', resolve(config.gameDirectory)); + defineOptions({ gameDirectory: resolve(config.gameDirectory) }); if (!existsSync(config.gameDirectory)) mkdirSync(config.gameDirectory, { recursive: true }); } const directory = config.directory || join(config.root, 'versions', config.version.custom ?? config.version.number); - setConfig('directory', directory); + defineOptions({ directory: directory }); await getVersion(); const mcPath = @@ -85,7 +85,7 @@ export const start = async () => { const directory = config.directory || join(config.root, 'versions', config.version.custom ? config.version.custom : config.version.number); - setConfig('directory', directory); + defineOptions({ directory: directory }); const versionFile = await getVersion(); const mcPath = @@ -106,7 +106,7 @@ export const start = async () => { }), ); } else if (config.forge) { - setConfig('forge', resolve(config.forge)); + defineOptions({ forge: resolve(config.forge) }); log('debug', 'Detected Forge in options, getting dependencies'); modifyJson = await getForgedWrapped(); } diff --git a/src/utils/config.ts b/src/utils/config.ts index b7ffc59..0abed59 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,17 +1,12 @@ +import { offline } from 'src'; import { Options } from './types'; -const config: Options = { +let config: Options = { root: './minecraft', - authorization: { - access_token: 'e9df5bd1-28bb-31c6-8eb0-4ad41f47d874', - client_token: 'e9df5bd1-28bb-31c6-8eb0-4ad41f47d874', - uuid: 'e9df5bd1-28bb-31c6-8eb0-4ad41f47d874', - name: 'Steve', - user_properties: '{}', - }, + authorization: offline('Steve'), detached: true, version: { - number: '1.7.10', + number: '1.14.4', type: 'release', }, url: { @@ -19,12 +14,15 @@ const config: Options = { resource: 'https://resources.download.minecraft.net', }, memory: { - min: '2G', - max: '4G', + min: Math.pow(2, 9), + max: Math.pow(2, 10), }, maxSockets: Infinity, }; -const setConfig = (key: K, value: Options[K]) => (config[key] = value); +const defineOptions = (newConfig: Partial): void => { + config = { ...config, ...newConfig }; + return; +}; -export { config, setConfig }; +export { config, defineOptions }; diff --git a/src/utils/types.ts b/src/utils/types.ts index d333007..93f3764 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -162,7 +162,7 @@ export interface Options { * This is for launcher developers located in countries that have the Minecraft resource servers * blocked for what ever reason. They obviously need to mirror the formatting of the original JSONs / file structures. */ - url?: { + url: { /** * List of versions. */ From df8bb421dfa1cb0de313ec61d13be644f1130187 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 14:33:41 +0300 Subject: [PATCH 41/97] [WIP] Use vitest instead of Jest --- .eslintignore | 2 +- jest.config.ts | 8 - package.json | 8 +- tests/auth.ts | 1 + tests/vanilla.ts | 33 +- tsconfig.json | 2 +- vitest.config.ts | 5 + yarn.lock | 2091 +++++++++++++--------------------------------- 8 files changed, 600 insertions(+), 1550 deletions(-) delete mode 100644 jest.config.ts create mode 100644 vitest.config.ts diff --git a/.eslintignore b/.eslintignore index b0993f6..ff17779 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,3 @@ -jest.config.ts +vitest.config.ts tests/ build/ \ No newline at end of file diff --git a/jest.config.ts b/jest.config.ts deleted file mode 100644 index 557c7ae..0000000 --- a/jest.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { JestConfigWithTsJest } from 'ts-jest'; - -const jestConfig: JestConfigWithTsJest = { - preset: 'ts-jest', - testMatch: ['/tests/**/*.ts'], -}; - -export default jestConfig; diff --git a/package.json b/package.json index b8ad6c7..96af3b2 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "type": "module", "scripts": { "clean": "rm -rf ./lib/", + "test": "vitest", "build": "yarn clean && yarn build:esm && yarn tsc", "build:esm": "tsc --module esnext --declaration --outDir ./build/esm", "lint": "eslint --color .", @@ -44,7 +45,6 @@ "devDependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.1.1", "@types/adm-zip": "^0.5.5", - "@types/jest": "^29.5.12", "@types/node": "^14.0.27", "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^7.1.0", @@ -52,10 +52,10 @@ "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.1.3", - "jest": "^29.7.0", "prettier": "^3.2.5", - "ts-jest": "^29.1.2", "ts-node": "^10.9.2", - "typescript": "^5.3.3" + "typescript": "^5.3.3", + "vite": "^5.1.6", + "vitest": "^1.3.1" } } diff --git a/tests/auth.ts b/tests/auth.ts index b297a38..0b96b74 100644 --- a/tests/auth.ts +++ b/tests/auth.ts @@ -1,3 +1,4 @@ +import { describe, expect, test } from 'vitest'; import { offline } from '../src'; describe('Testing the offline authentication', () => { diff --git a/tests/vanilla.ts b/tests/vanilla.ts index c802260..31aeab8 100644 --- a/tests/vanilla.ts +++ b/tests/vanilla.ts @@ -1,10 +1,16 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process'; -import { existsSync } from 'node:fs'; +import { existsSync, rmdirSync } from 'node:fs'; import { resolve } from 'node:path'; -import { Client, setConfig } from '../src'; +import { afterAll, beforeAll, describe, expect, test } from 'vitest'; +import { Client, defineOptions } from '../src'; describe('Minecraft Vanilla Legacy (1.8.9)', () => { - setConfig('version', { number: '1.8.9', type: 'release' }); + defineOptions({ + version: { + number: '1.8.9', + type: 'release', + }, + }); test( 'Installation', @@ -33,10 +39,21 @@ describe('Minecraft Vanilla Legacy (1.8.9)', () => { }, 3 * 60 * 1000, ); + + // Cleanup for other tests + afterAll(() => { + rmdirSync(resolve('./minecraft/saves')); + rmdirSync(resolve('./minecraft/resourcepacks')); + }); }); describe('Minecraft Vanilla Modern (1.14.4)', () => { - setConfig('version', { number: '1.14.4', type: 'release' }); + defineOptions({ + version: { + number: '1.14.4', + type: 'release', + }, + }); test( 'Installation', @@ -58,11 +75,17 @@ describe('Minecraft Vanilla Modern (1.14.4)', () => { setTimeout(() => { (process as ChildProcessWithoutNullStreams).kill(); resolve(); - }, 10 * 1000); + }, 20 * 1000); }); expect(existsSync(resolve('./minecraft/saves'))).toBe(true); expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); }, 3 * 60 * 1000, ); + + // Cleanup for other tests + afterAll(() => { + rmdirSync(resolve('./minecraft/saves')); + rmdirSync(resolve('./minecraft/resourcepacks')); + }); }); diff --git a/tsconfig.json b/tsconfig.json index a64ece2..48cea65 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,7 @@ "resolveJsonModule": true, "strict": true, "target": "ESNext", - "types": ["node", "jest"] + "types": ["node"] }, "exclude": ["./build/"], "include": ["./src/"] diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..7a934af --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,5 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { include: ['./tests/*'] }, +}); diff --git a/yarn.lock b/yarn.lock index 5171ac3..914bd78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,7 +15,7 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.23.5": +"@babel/code-frame@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== @@ -28,27 +28,6 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.23.9": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b" - integrity sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.24.0" - "@babel/parser" "^7.24.0" - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.0" - "@babel/types" "^7.24.0" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - "@babel/core@^7.21.8": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" @@ -70,7 +49,7 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.21.5", "@babel/generator@^7.23.6", "@babel/generator@^7.7.2": +"@babel/generator@^7.21.5", "@babel/generator@^7.23.6": version "7.23.6" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== @@ -129,11 +108,6 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" - integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== - "@babel/helper-simple-access@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de" @@ -172,15 +146,6 @@ "@babel/traverse" "^7.23.9" "@babel/types" "^7.23.9" -"@babel/helpers@^7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.0.tgz#a3dd462b41769c95db8091e49cfe019389a9409b" - integrity sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA== - dependencies: - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.0" - "@babel/types" "^7.24.0" - "@babel/highlight@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" @@ -190,114 +155,11 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" - integrity sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg== - "@babel/parser@^7.21.8", "@babel/parser@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-bigint@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" - integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.8.3": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-import-meta@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - -"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" - integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-numeric-separator@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" - integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-chaining@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" - integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-top-level-await@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.7.2": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== - dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/template@^7.22.15", "@babel/template@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" @@ -307,15 +169,6 @@ "@babel/parser" "^7.23.9" "@babel/types" "^7.23.9" -"@babel/template@^7.24.0", "@babel/template@^7.3.3": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" - integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.24.0" - "@babel/types" "^7.24.0" - "@babel/traverse@^7.21.5", "@babel/traverse@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" @@ -332,31 +185,6 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/traverse@^7.24.0": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e" - integrity sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.24.0" - "@babel/types" "^7.24.0" - debug "^4.3.1" - globals "^11.1.0" - -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.0", "@babel/types@^7.3.3": - version "7.24.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" - integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== - dependencies: - "@babel/helper-string-parser" "^7.23.4" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - "@babel/types@^7.21.5", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9": version "7.23.9" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" @@ -366,11 +194,6 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== - "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -378,6 +201,121 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@esbuild/aix-ppc64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" + integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA== + +"@esbuild/android-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" + integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA== + +"@esbuild/android-arm@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" + integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w== + +"@esbuild/android-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" + integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew== + +"@esbuild/darwin-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" + integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== + +"@esbuild/darwin-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" + integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A== + +"@esbuild/freebsd-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" + integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA== + +"@esbuild/freebsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" + integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg== + +"@esbuild/linux-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" + integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA== + +"@esbuild/linux-arm@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" + integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w== + +"@esbuild/linux-ia32@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" + integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA== + +"@esbuild/linux-loong64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" + integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA== + +"@esbuild/linux-mips64el@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" + integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w== + +"@esbuild/linux-ppc64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" + integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg== + +"@esbuild/linux-riscv64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" + integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg== + +"@esbuild/linux-s390x@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" + integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg== + +"@esbuild/linux-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78" + integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== + +"@esbuild/netbsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" + integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA== + +"@esbuild/openbsd-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" + integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw== + +"@esbuild/sunos-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" + integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA== + +"@esbuild/win32-arm64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" + integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A== + +"@esbuild/win32-ia32@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" + integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ== + +"@esbuild/win32-x64@0.19.12": + version "0.19.12" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" + integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -441,145 +379,6 @@ "@babel/types" "^7.21.5" semver "^7.5.2" -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": - version "0.1.3" - resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jest/console@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" - integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - -"@jest/core@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" - integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== - dependencies: - "@jest/console" "^29.7.0" - "@jest/reporters" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - ci-info "^3.2.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-changed-files "^29.7.0" - jest-config "^29.7.0" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-resolve-dependencies "^29.7.0" - jest-runner "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - jest-watcher "^29.7.0" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-ansi "^6.0.0" - -"@jest/environment@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" - integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== - dependencies: - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - -"@jest/expect-utils@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== - dependencies: - jest-get-type "^29.6.3" - -"@jest/expect@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" - integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== - dependencies: - expect "^29.7.0" - jest-snapshot "^29.7.0" - -"@jest/fake-timers@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" - integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== - dependencies: - "@jest/types" "^29.6.3" - "@sinonjs/fake-timers" "^10.0.2" - "@types/node" "*" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -"@jest/globals@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" - integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/types" "^29.6.3" - jest-mock "^29.7.0" - -"@jest/reporters@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" - integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== - dependencies: - "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - "@types/node" "*" - chalk "^4.0.0" - collect-v8-coverage "^1.0.0" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-instrument "^6.0.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.1.3" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - jest-worker "^29.7.0" - slash "^3.0.0" - string-length "^4.0.1" - strip-ansi "^6.0.0" - v8-to-istanbul "^9.0.1" - "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -587,68 +386,6 @@ dependencies: "@sinclair/typebox" "^0.27.8" -"@jest/source-map@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-29.6.3.tgz#d90ba772095cf37a34a5eb9413f1b562a08554c4" - integrity sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw== - dependencies: - "@jridgewell/trace-mapping" "^0.3.18" - callsites "^3.0.0" - graceful-fs "^4.2.9" - -"@jest/test-result@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" - integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== - dependencies: - "@jest/console" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - collect-v8-coverage "^1.0.0" - -"@jest/test-sequencer@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" - integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== - dependencies: - "@jest/test-result" "^29.7.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - slash "^3.0.0" - -"@jest/transform@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" - integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== - dependencies: - "@babel/core" "^7.11.6" - "@jest/types" "^29.6.3" - "@jridgewell/trace-mapping" "^0.3.18" - babel-plugin-istanbul "^6.1.1" - chalk "^4.0.0" - convert-source-map "^2.0.0" - fast-json-stable-stringify "^2.1.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - micromatch "^4.0.4" - pirates "^4.0.4" - slash "^3.0.0" - write-file-atomic "^4.0.2" - -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - "@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": version "0.3.4" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.4.tgz#9b18145d26cf33d08576cf4c7665b28554480ed7" @@ -668,7 +405,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15": version "1.4.15" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== @@ -681,14 +418,6 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.18": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== - dependencies: - "@jridgewell/resolve-uri" "^3.1.0" - "@jridgewell/sourcemap-codec" "^1.4.14" - "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": version "0.3.23" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.23.tgz#afc96847f3f07841477f303eed687707a5aacd80" @@ -723,25 +452,76 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@rollup/rollup-android-arm-eabi@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz#b98786c1304b4ff8db3a873180b778649b5dff2b" + integrity sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg== + +"@rollup/rollup-android-arm64@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz#8833679af11172b1bf1ab7cb3bad84df4caf0c9e" + integrity sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q== + +"@rollup/rollup-darwin-arm64@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz#ef02d73e0a95d406e0eb4fd61a53d5d17775659b" + integrity sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g== + +"@rollup/rollup-darwin-x64@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz#3ce5b9bcf92b3341a5c1c58a3e6bcce0ea9e7455" + integrity sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg== + +"@rollup/rollup-linux-arm-gnueabihf@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz#3d3d2c018bdd8e037c6bfedd52acfff1c97e4be4" + integrity sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ== + +"@rollup/rollup-linux-arm64-gnu@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz#5fc8cc978ff396eaa136d7bfe05b5b9138064143" + integrity sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w== + +"@rollup/rollup-linux-arm64-musl@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz#f2ae7d7bed416ffa26d6b948ac5772b520700eef" + integrity sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw== + +"@rollup/rollup-linux-riscv64-gnu@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz#303d57a328ee9a50c85385936f31cf62306d30b6" + integrity sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA== + +"@rollup/rollup-linux-x64-gnu@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz#f672f6508f090fc73f08ba40ff76c20b57424778" + integrity sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA== + +"@rollup/rollup-linux-x64-musl@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz#d2f34b1b157f3e7f13925bca3288192a66755a89" + integrity sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw== + +"@rollup/rollup-win32-arm64-msvc@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz#8ffecc980ae4d9899eb2f9c4ae471a8d58d2da6b" + integrity sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA== + +"@rollup/rollup-win32-ia32-msvc@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz#a7505884f415662e088365b9218b2b03a88fc6f2" + integrity sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw== + +"@rollup/rollup-win32-x64-msvc@4.13.0": + version "4.13.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz#6abd79db7ff8d01a58865ba20a63cfd23d9e2a10" + integrity sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw== + "@sinclair/typebox@^0.27.8": version "0.27.8" resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== -"@sinonjs/commons@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^10.0.2": - version "10.3.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz#55fdff1ecab9f354019129daf4df0dd4d923ea66" - integrity sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA== - dependencies: - "@sinonjs/commons" "^3.0.0" - "@tsconfig/node10@^1.0.7": version "1.0.9" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" @@ -769,72 +549,10 @@ dependencies: "@types/node" "*" -"@types/babel__core@^7.1.14": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.5.tgz#7b7502be0aa80cc4ef22978846b983edaafcd4dd" - integrity sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ== - dependencies: - "@babel/types" "^7.20.7" - -"@types/graceful-fs@^4.1.3": - version "4.1.9" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.9.tgz#2a06bc0f68a20ab37b3e36aa238be6abdf49e8b4" - integrity sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@^29.5.12": - version "29.5.12" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" - integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" +"@types/estree@1.0.5", "@types/estree@^1.0.0": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/json-schema@^7.0.12": version "7.0.15" @@ -858,28 +576,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== -"@types/stack-utils@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - "@types/uuid@^9.0.8": version "9.0.8" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== - dependencies: - "@types/yargs-parser" "*" - "@typescript-eslint/eslint-plugin@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.0.tgz#22bb999a8d59893c0ea07923e8a21f9d985ad740" @@ -971,17 +672,61 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@vitest/expect@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.3.1.tgz#d4c14b89c43a25fd400a6b941f51ba27fe0cb918" + integrity sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw== + dependencies: + "@vitest/spy" "1.3.1" + "@vitest/utils" "1.3.1" + chai "^4.3.10" + +"@vitest/runner@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.3.1.tgz#e7f96cdf74842934782bfd310eef4b8695bbfa30" + integrity sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg== + dependencies: + "@vitest/utils" "1.3.1" + p-limit "^5.0.0" + pathe "^1.1.1" + +"@vitest/snapshot@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.3.1.tgz#193a5d7febf6ec5d22b3f8c5a093f9e4322e7a88" + integrity sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ== + dependencies: + magic-string "^0.30.5" + pathe "^1.1.1" + pretty-format "^29.7.0" + +"@vitest/spy@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.3.1.tgz#814245d46d011b99edd1c7528f5725c64e85a88b" + integrity sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig== + dependencies: + tinyspy "^2.2.0" + +"@vitest/utils@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.3.1.tgz#7b05838654557544f694a372de767fcc9594d61a" + integrity sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ== + dependencies: + diff-sequences "^29.6.3" + estree-walker "^3.0.3" + loupe "^2.3.7" + pretty-format "^29.7.0" + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-walk@^8.1.1: +acorn-walk@^8.1.1, acorn-walk@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^8.4.1, acorn@^8.9.0: +acorn@^8.11.3, acorn@^8.4.1, acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -1001,13 +746,6 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-escapes@^4.2.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" - integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== - dependencies: - type-fest "^0.21.3" - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -1020,7 +758,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0, ansi-styles@^4.1.0: +ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -1032,26 +770,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -anymatch@^3.0.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" - integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - argparse@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" @@ -1062,6 +785,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1076,66 +804,6 @@ axios@^1.6.7: form-data "^4.0.0" proxy-from-env "^1.1.0" -babel-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" - integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== - dependencies: - "@jest/transform" "^29.7.0" - "@types/babel__core" "^7.1.14" - babel-plugin-istanbul "^6.1.1" - babel-preset-jest "^29.6.3" - chalk "^4.0.0" - graceful-fs "^4.2.9" - slash "^3.0.0" - -babel-plugin-istanbul@^6.1.1: - version "6.1.1" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" - integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-instrument "^5.0.4" - test-exclude "^6.0.0" - -babel-plugin-jest-hoist@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz#aadbe943464182a8922c3c927c3067ff40d24626" - integrity sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg== - dependencies: - "@babel/template" "^7.3.3" - "@babel/types" "^7.3.3" - "@types/babel__core" "^7.1.14" - "@types/babel__traverse" "^7.0.6" - -babel-preset-current-node-syntax@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" - integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== - dependencies: - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-bigint" "^7.8.3" - "@babel/plugin-syntax-class-properties" "^7.8.3" - "@babel/plugin-syntax-import-meta" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.8.3" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-top-level-await" "^7.8.3" - -babel-preset-jest@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz#fa05fa510e7d493896d7b0dd2033601c840f171c" - integrity sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA== - dependencies: - babel-plugin-jest-hoist "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -1173,45 +841,34 @@ browserslist@^4.22.2: node-releases "^2.0.14" update-browserslist-db "^1.0.13" -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.2.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - caniuse-lite@^1.0.30001587: version "1.0.30001591" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz#16745e50263edc9f395895a7cd468b9f3767cf33" integrity sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ== +chai@^4.3.10: + version "4.4.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" + integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.0.8" + chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1229,39 +886,12 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -char-regex@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" - integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== - -ci-info@^3.2.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== - -cjs-module-lexer@^1.0.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== - -cliui@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" - integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== +check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.1" - wrap-ansi "^7.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== - -collect-v8-coverage@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9" - integrity sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q== + get-func-name "^2.0.2" color-convert@^1.9.0: version "1.9.3" @@ -1304,19 +934,6 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -create-jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" - integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - exit "^0.1.2" - graceful-fs "^4.2.9" - jest-config "^29.7.0" - jest-util "^29.7.0" - prompts "^2.0.1" - create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -1331,38 +948,30 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -dedent@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/dedent/-/dedent-1.5.1.tgz#4f3fc94c8b711e9bb2800d185cd6ad20f2a90aff" - integrity sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg== +deep-eql@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -deepmerge@^4.2.2: - version "4.3.1" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" - integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== -detect-newline@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" - integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== - diff-sequences@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" @@ -1392,22 +1001,34 @@ electron-to-chromium@^1.4.668: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.683.tgz#b68167ed66dbea01feb86915aca92c09bc1b651a" integrity sha512-FmopjiJjkUzqa5F5Sv+wxd8KimtCxyLFOFgRPwEeMLVmP+vHH/GjNGCuIYrCIchbMSiOe+nG/OPBbR/XoExBNA== -emittery@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" - integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" +esbuild@^0.19.3: + version "0.19.12" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" + integrity sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.19.12" + "@esbuild/android-arm" "0.19.12" + "@esbuild/android-arm64" "0.19.12" + "@esbuild/android-x64" "0.19.12" + "@esbuild/darwin-arm64" "0.19.12" + "@esbuild/darwin-x64" "0.19.12" + "@esbuild/freebsd-arm64" "0.19.12" + "@esbuild/freebsd-x64" "0.19.12" + "@esbuild/linux-arm" "0.19.12" + "@esbuild/linux-arm64" "0.19.12" + "@esbuild/linux-ia32" "0.19.12" + "@esbuild/linux-loong64" "0.19.12" + "@esbuild/linux-mips64el" "0.19.12" + "@esbuild/linux-ppc64" "0.19.12" + "@esbuild/linux-riscv64" "0.19.12" + "@esbuild/linux-s390x" "0.19.12" + "@esbuild/linux-x64" "0.19.12" + "@esbuild/netbsd-x64" "0.19.12" + "@esbuild/openbsd-x64" "0.19.12" + "@esbuild/sunos-x64" "0.19.12" + "@esbuild/win32-arm64" "0.19.12" + "@esbuild/win32-ia32" "0.19.12" + "@esbuild/win32-x64" "0.19.12" escalade@^3.1.1: version "3.1.2" @@ -1419,11 +1040,6 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -1508,11 +1124,6 @@ espree@^9.6.0, espree@^9.6.1: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.4.1" -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - esquery@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" @@ -1532,41 +1143,32 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -execa@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" - integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== +execa@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== dependencies: cross-spawn "^7.0.3" - get-stream "^6.0.0" - human-signals "^2.1.0" - is-stream "^2.0.0" + get-stream "^8.0.1" + human-signals "^5.0.0" + is-stream "^3.0.0" merge-stream "^2.0.0" - npm-run-path "^4.0.1" - onetime "^5.1.2" - signal-exit "^3.0.3" - strip-final-newline "^2.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== - -expect@^29.0.0, expect@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== - dependencies: - "@jest/expect-utils" "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" + npm-run-path "^5.1.0" + onetime "^6.0.0" + signal-exit "^4.1.0" + strip-final-newline "^3.0.0" fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" @@ -1589,7 +1191,7 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: +fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -1606,13 +1208,6 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fb-watchman@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" - integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== - dependencies: - bser "2.1.1" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -1627,14 +1222,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-up@^4.0.0, find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -1676,35 +1263,25 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2: +fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" - integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== - gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -get-stream@^6.0.0: - version "6.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" - integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== glob-parent@^5.1.2: version "5.1.2" @@ -1720,7 +1297,7 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" -glob@^7.1.3, glob@^7.1.4: +glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -1756,11 +1333,6 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -1776,22 +1348,10 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -hasown@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" - integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== - dependencies: - function-bind "^1.1.2" - -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -human-signals@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" - integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== ignore@^5.2.0, ignore@^5.2.4: version "5.3.1" @@ -1806,14 +1366,6 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -1832,33 +1384,11 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== - -is-core-module@^2.13.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -1876,439 +1406,25 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" - integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== - -istanbul-lib-instrument@^5.0.4: - version "5.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" - integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== - dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.2.0" - semver "^6.3.0" - -istanbul-lib-instrument@^6.0.0: - version "6.0.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz#91655936cf7380e4e473383081e38478b69993b1" - integrity sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw== - dependencies: - "@babel/core" "^7.23.9" - "@babel/parser" "^7.23.9" - "@istanbuljs/schema" "^0.1.3" - istanbul-lib-coverage "^3.2.0" - semver "^7.5.4" - -istanbul-lib-report@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.1.3: - version "3.1.7" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" - integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -jest-changed-files@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" - integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== - dependencies: - execa "^5.0.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - -jest-circus@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" - integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/expect" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - co "^4.6.0" - dedent "^1.0.0" - is-generator-fn "^2.0.0" - jest-each "^29.7.0" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-runtime "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - p-limit "^3.1.0" - pretty-format "^29.7.0" - pure-rand "^6.0.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-cli@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" - integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== - dependencies: - "@jest/core" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - chalk "^4.0.0" - create-jest "^29.7.0" - exit "^0.1.2" - import-local "^3.0.2" - jest-config "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - yargs "^17.3.1" - -jest-config@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" - integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== - dependencies: - "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.7.0" - "@jest/types" "^29.6.3" - babel-jest "^29.7.0" - chalk "^4.0.0" - ci-info "^3.2.0" - deepmerge "^4.2.2" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-circus "^29.7.0" - jest-environment-node "^29.7.0" - jest-get-type "^29.6.3" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-runner "^29.7.0" - jest-util "^29.7.0" - jest-validate "^29.7.0" - micromatch "^4.0.4" - parse-json "^5.2.0" - pretty-format "^29.7.0" - slash "^3.0.0" - strip-json-comments "^3.1.1" - -jest-diff@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" - integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== - dependencies: - chalk "^4.0.0" - diff-sequences "^29.6.3" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-docblock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" - integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== - dependencies: - detect-newline "^3.0.0" - -jest-each@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" - integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== - dependencies: - "@jest/types" "^29.6.3" - chalk "^4.0.0" - jest-get-type "^29.6.3" - jest-util "^29.7.0" - pretty-format "^29.7.0" - -jest-environment-node@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" - integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-mock "^29.7.0" - jest-util "^29.7.0" - -jest-get-type@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" - integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== - -jest-haste-map@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" - integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== - dependencies: - "@jest/types" "^29.6.3" - "@types/graceful-fs" "^4.1.3" - "@types/node" "*" - anymatch "^3.0.3" - fb-watchman "^2.0.0" - graceful-fs "^4.2.9" - jest-regex-util "^29.6.3" - jest-util "^29.7.0" - jest-worker "^29.7.0" - micromatch "^4.0.4" - walker "^1.0.8" - optionalDependencies: - fsevents "^2.3.2" - -jest-leak-detector@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" - integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== - dependencies: - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-matcher-utils@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== - dependencies: - chalk "^4.0.0" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-mock@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" - integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - jest-util "^29.7.0" - -jest-pnp-resolver@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" - integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== - -jest-regex-util@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" - integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== - -jest-resolve-dependencies@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" - integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== - dependencies: - jest-regex-util "^29.6.3" - jest-snapshot "^29.7.0" - -jest-resolve@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" - integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== - dependencies: - chalk "^4.0.0" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-pnp-resolver "^1.2.2" - jest-util "^29.7.0" - jest-validate "^29.7.0" - resolve "^1.20.0" - resolve.exports "^2.0.0" - slash "^3.0.0" - -jest-runner@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" - integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== - dependencies: - "@jest/console" "^29.7.0" - "@jest/environment" "^29.7.0" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - emittery "^0.13.1" - graceful-fs "^4.2.9" - jest-docblock "^29.7.0" - jest-environment-node "^29.7.0" - jest-haste-map "^29.7.0" - jest-leak-detector "^29.7.0" - jest-message-util "^29.7.0" - jest-resolve "^29.7.0" - jest-runtime "^29.7.0" - jest-util "^29.7.0" - jest-watcher "^29.7.0" - jest-worker "^29.7.0" - p-limit "^3.1.0" - source-map-support "0.5.13" - -jest-runtime@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" - integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== - dependencies: - "@jest/environment" "^29.7.0" - "@jest/fake-timers" "^29.7.0" - "@jest/globals" "^29.7.0" - "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - cjs-module-lexer "^1.0.0" - collect-v8-coverage "^1.0.0" - glob "^7.1.3" - graceful-fs "^4.2.9" - jest-haste-map "^29.7.0" - jest-message-util "^29.7.0" - jest-mock "^29.7.0" - jest-regex-util "^29.6.3" - jest-resolve "^29.7.0" - jest-snapshot "^29.7.0" - jest-util "^29.7.0" - slash "^3.0.0" - strip-bom "^4.0.0" - -jest-snapshot@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" - integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== - dependencies: - "@babel/core" "^7.11.6" - "@babel/generator" "^7.7.2" - "@babel/plugin-syntax-jsx" "^7.7.2" - "@babel/plugin-syntax-typescript" "^7.7.2" - "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.7.0" - "@jest/transform" "^29.7.0" - "@jest/types" "^29.6.3" - babel-preset-current-node-syntax "^1.0.0" - chalk "^4.0.0" - expect "^29.7.0" - graceful-fs "^4.2.9" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" - natural-compare "^1.4.0" - pretty-format "^29.7.0" - semver "^7.5.3" - -jest-util@^29.0.0, jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - -jest-validate@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" - integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== - dependencies: - "@jest/types" "^29.6.3" - camelcase "^6.2.0" - chalk "^4.0.0" - jest-get-type "^29.6.3" - leven "^3.1.0" - pretty-format "^29.7.0" - -jest-watcher@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" - integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== - dependencies: - "@jest/test-result" "^29.7.0" - "@jest/types" "^29.6.3" - "@types/node" "*" - ansi-escapes "^4.2.1" - chalk "^4.0.0" - emittery "^0.13.1" - jest-util "^29.7.0" - string-length "^4.0.1" - -jest-worker@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" - integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== - dependencies: - "@types/node" "*" - jest-util "^29.7.0" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -jest@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" - integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== - dependencies: - "@jest/core" "^29.7.0" - "@jest/types" "^29.6.3" - import-local "^3.0.2" - jest-cli "^29.7.0" - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" +js-tokens@^8.0.2: + version "8.0.3" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-8.0.3.tgz#1c407ec905643603b38b6be6977300406ec48775" + integrity sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw== js-yaml@^4.1.0: version "4.1.0" @@ -2327,11 +1443,6 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -2347,6 +1458,11 @@ json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonc-parser@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.1.tgz#031904571ccf929d7670ee8c547545081cb37f1a" + integrity sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA== + keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -2354,16 +1470,6 @@ keyv@^4.5.3: dependencies: json-buffer "3.0.1" -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -2372,17 +1478,13 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lines-and-columns@^1.1.6: - version "1.2.4" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" - integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== +local-pkg@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c" + integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg== dependencies: - p-locate "^4.1.0" + mlly "^1.4.2" + pkg-types "^1.0.3" locate-path@^6.0.0: version "6.0.0" @@ -2391,16 +1493,18 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== - lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +loupe@^2.3.6, loupe@^2.3.7: + version "2.3.7" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== + dependencies: + get-func-name "^2.0.1" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -2415,25 +1519,18 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== +magic-string@^0.30.5: + version "0.30.8" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.8.tgz#14e8624246d2bedba70d5462aa99ac9681844613" + integrity sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ== dependencies: - semver "^7.5.3" + "@jridgewell/sourcemap-codec" "^1.4.15" -make-error@1.x, make-error@^1.1.1: +make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -makeerror@1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" - integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg== - dependencies: - tmpl "1.0.5" - merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -2464,10 +1561,10 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== minimatch@9.0.3: version "9.0.3" @@ -2476,44 +1573,49 @@ minimatch@9.0.3: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" +mlly@^1.2.0, mlly@^1.4.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.6.1.tgz#0983067dc3366d6314fc5e12712884e6978d028f" + integrity sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA== + dependencies: + acorn "^8.11.3" + pathe "^1.1.2" + pkg-types "^1.0.3" + ufo "^1.3.2" + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== - node-releases@^2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== -normalize-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -npm-run-path@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" - integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== +npm-run-path@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" + integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== dependencies: - path-key "^3.0.0" + path-key "^4.0.0" once@^1.3.0: version "1.4.0" @@ -2522,12 +1624,12 @@ once@^1.3.0: dependencies: wrappy "1" -onetime@^5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== dependencies: - mimic-fn "^2.1.0" + mimic-fn "^4.0.0" optionator@^0.9.3: version "0.9.3" @@ -2541,26 +1643,19 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== +p-limit@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-5.0.0.tgz#6946d5b7140b649b7a33a027d89b4c625b3a5985" + integrity sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ== dependencies: - p-limit "^2.2.0" + yocto-queue "^1.0.0" p-locate@^5.0.0: version "5.0.0" @@ -2569,11 +1664,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2581,16 +1671,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-json@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" - integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -2601,42 +1681,58 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^3.0.0, path-key@^3.1.0: +path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathe@^1.1.0, pathe@^1.1.1, pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pirates@^4.0.4: - version "4.0.6" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" - integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg== +pkg-types@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.3.tgz#988b42ab19254c01614d13f4f65a2cfc7880f868" + integrity sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A== + dependencies: + jsonc-parser "^3.2.0" + mlly "^1.2.0" + pathe "^1.1.0" -pkg-dir@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== +postcss@^8.4.35: + version "8.4.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.35.tgz#60997775689ce09011edf083a549cea44aabe2f7" + integrity sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA== dependencies: - find-up "^4.0.0" + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.0.2" prelude-ls@^1.2.1: version "1.2.1" @@ -2655,7 +1751,7 @@ prettier@^3.2.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== -pretty-format@^29.0.0, pretty-format@^29.7.0: +pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== @@ -2664,14 +1760,6 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" -prompts@^2.0.1: - version "2.4.2" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" - integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.5" - proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" @@ -2682,11 +1770,6 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== -pure-rand@^6.0.0: - version "6.0.4" - resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.4.tgz#50b737f6a925468679bff00ad20eade53f37d5c7" - integrity sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -2697,42 +1780,11 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve.exports@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" - integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== - -resolve@^1.20.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -2745,6 +1797,28 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup@^4.2.0: + version "4.13.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.13.0.tgz#dd2ae144b4cdc2ea25420477f68d4937a721237a" + integrity sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg== + dependencies: + "@types/estree" "1.0.5" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.13.0" + "@rollup/rollup-android-arm64" "4.13.0" + "@rollup/rollup-darwin-arm64" "4.13.0" + "@rollup/rollup-darwin-x64" "4.13.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.13.0" + "@rollup/rollup-linux-arm64-gnu" "4.13.0" + "@rollup/rollup-linux-arm64-musl" "4.13.0" + "@rollup/rollup-linux-riscv64-gnu" "4.13.0" + "@rollup/rollup-linux-x64-gnu" "4.13.0" + "@rollup/rollup-linux-x64-musl" "4.13.0" + "@rollup/rollup-win32-arm64-msvc" "4.13.0" + "@rollup/rollup-win32-ia32-msvc" "4.13.0" + "@rollup/rollup-win32-x64-msvc" "4.13.0" + fsevents "~2.3.2" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -2752,12 +1826,12 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -semver@^6.3.0, semver@^6.3.1: +semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.2, semver@^7.5.3, semver@^7.5.4: +semver@^7.5.2, semver@^7.5.4: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== @@ -2776,85 +1850,60 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -signal-exit@^3.0.3, signal-exit@^3.0.7: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== -sisteransi@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" - integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-support@0.5.13: - version "0.5.13" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" - integrity sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0, source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== -string-length@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" - integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== - dependencies: - char-regex "^1.0.2" - strip-ansi "^6.0.0" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" +std-env@^3.5.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" + integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== -strip-ansi@^6.0.0, strip-ansi@^6.0.1: +strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - -strip-final-newline@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" - integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-literal@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.0.0.tgz#5d063580933e4e03ebb669b12db64d2200687527" + integrity sha512-f9vHgsCWBq2ugHAkGMiiYY+AYG0D/cbloKKg0nhaaaSNsujdGIpVXCNsrJpCKr5M0f4aI31mr13UjY6GAuXCKA== + dependencies: + js-tokens "^8.0.2" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -2869,18 +1918,6 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -supports-preserve-symlinks-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" - integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== - synckit@^0.8.6: version "0.8.8" resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.8.8.tgz#fe7fe446518e3d3d49f5e429f443cf08b6edfcd7" @@ -2889,24 +1926,25 @@ synckit@^0.8.6: "@pkgr/core" "^0.1.0" tslib "^2.6.2" -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -tmpl@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" - integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== +tinybench@^2.5.1: + version "2.6.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.6.0.tgz#1423284ee22de07c91b3752c048d2764714b341b" + integrity sha512-N8hW3PG/3aOoZAN5V/NSAEDz0ZixDSSt5b/a05iqtpgfLWMSVuCo7w0k2vVvEjdrIoeGqZzweX2WlyioNIHchA== + +tinypool@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.2.tgz#84013b03dc69dacb322563a475d4c0a9be00f82a" + integrity sha512-SUszKYe5wgsxnNOVlBYO6IC+8VGWdVGZWAqUxp3UErNBtptZvWbwyUOyzNL59zigz2rCA92QiL3wvG+JDSdJdQ== + +tinyspy@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.1.tgz#117b2342f1f38a0dbdcc73a50a454883adf861d1" + integrity sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A== to-fast-properties@^2.0.0: version "2.0.0" @@ -2925,20 +1963,6 @@ ts-api-utils@^1.0.1: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b" integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA== -ts-jest@^29.1.2: - version "29.1.2" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-29.1.2.tgz#7613d8c81c43c8cb312c6904027257e814c40e09" - integrity sha512-br6GJoH/WUX4pu7FbZXuWGKGNDuU7b8Uj77g/Sp7puZV6EXzuByl6JrECvm0MzVzSTkSHWTihsXt+5XYER5b+g== - dependencies: - bs-logger "0.x" - fast-json-stable-stringify "2.x" - jest-util "^29.0.0" - json5 "^2.2.3" - lodash.memoize "4.x" - make-error "1.x" - semver "^7.5.3" - yargs-parser "^21.0.1" - ts-node@^10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" @@ -2970,7 +1994,7 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-detect@4.0.8: +type-detect@^4.0.0, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== @@ -2980,16 +2004,16 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^0.21.3: - version "0.21.3" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" - integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== - typescript@^5.3.3: version "5.3.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +ufo@^1.3.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.4.0.tgz#39845b31be81b4f319ab1d99fd20c56cac528d32" + integrity sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ== + undici-types@~5.26.4: version "5.26.5" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" @@ -3020,21 +2044,53 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -v8-to-istanbul@^9.0.1: - version "9.2.0" - resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" - integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== +vite-node@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.3.1.tgz#a93f7372212f5d5df38e945046b945ac3f4855d2" + integrity sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng== dependencies: - "@jridgewell/trace-mapping" "^0.3.12" - "@types/istanbul-lib-coverage" "^2.0.1" - convert-source-map "^2.0.0" + cac "^6.7.14" + debug "^4.3.4" + pathe "^1.1.1" + picocolors "^1.0.0" + vite "^5.0.0" -walker@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f" - integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ== +vite@^5.0.0, vite@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.1.6.tgz#706dae5fab9e97f57578469eef1405fc483943e4" + integrity sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA== dependencies: - makeerror "1.0.12" + esbuild "^0.19.3" + postcss "^8.4.35" + rollup "^4.2.0" + optionalDependencies: + fsevents "~2.3.3" + +vitest@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.3.1.tgz#2d7e9861f030d88a4669392a4aecb40569d90937" + integrity sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ== + dependencies: + "@vitest/expect" "1.3.1" + "@vitest/runner" "1.3.1" + "@vitest/snapshot" "1.3.1" + "@vitest/spy" "1.3.1" + "@vitest/utils" "1.3.1" + acorn-walk "^8.3.2" + chai "^4.3.10" + debug "^4.3.4" + execa "^8.0.1" + local-pkg "^0.5.0" + magic-string "^0.30.5" + pathe "^1.1.1" + picocolors "^1.0.0" + std-env "^3.5.0" + strip-literal "^2.0.0" + tinybench "^2.5.1" + tinypool "^0.8.2" + vite "^5.0.0" + vite-node "1.3.1" + why-is-node-running "^2.2.2" which@^2.0.1: version "2.0.2" @@ -3043,33 +2099,19 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== +why-is-node-running@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.2.2.tgz#4185b2b4699117819e7154594271e7e344c9973e" + integrity sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA== dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + siginfo "^2.0.0" + stackback "0.0.2" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd" - integrity sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg== - dependencies: - imurmurhash "^0.1.4" - signal-exit "^3.0.7" - -y18n@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" - integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== - yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" @@ -3080,24 +2122,6 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@^21.0.1, yargs-parser@^21.1.1: - version "21.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" - integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== - -yargs@^17.3.1: - version "17.7.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" - integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== - dependencies: - cliui "^8.0.1" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.3" - y18n "^5.0.5" - yargs-parser "^21.1.1" - yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" @@ -3107,3 +2131,8 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yocto-queue@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" + integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== From aaad53d53b637cde2cb11a8f94e99aa30cc2ed2b Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 14:46:49 +0300 Subject: [PATCH 42/97] Clean build folder via an another way --- .eslintignore | 5 +++-- clean.js | 5 +++++ package.json | 4 ++-- 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 clean.js diff --git a/.eslintignore b/.eslintignore index ff17779..85b6a63 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,3 +1,4 @@ -vitest.config.ts tests/ -build/ \ No newline at end of file +build/ +clean.js +vitest.config.ts \ No newline at end of file diff --git a/clean.js b/clean.js new file mode 100644 index 0000000..d319178 --- /dev/null +++ b/clean.js @@ -0,0 +1,5 @@ +import { existsSync, rm } from 'fs'; + +// A simple way to delete the `build` folder +// instead of `rm -rf` which is limited per OS +if (existsSync('build')) rm('build', { recursive: true, force: true }, () => void 0); diff --git a/package.json b/package.json index 96af3b2..61d3785 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ ], "type": "module", "scripts": { - "clean": "rm -rf ./lib/", + "clean": "node clean.js", "test": "vitest", "build": "yarn clean && yarn build:esm && yarn tsc", "build:esm": "tsc --module esnext --declaration --outDir ./build/esm", @@ -58,4 +58,4 @@ "vite": "^5.1.6", "vitest": "^1.3.1" } -} +} \ No newline at end of file From b03e7291dce26287f32a5f94613a7e0406ee6a51 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 14:49:14 +0300 Subject: [PATCH 43/97] PascalCase --- src/handler.ts | 26 +++++++++++++------------- src/utils/types.ts | 26 +++++++++++++------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index a1524be..b04079e 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -17,7 +17,7 @@ import axios from 'axios'; import { checkSum, cleanUp, getOS, isLegacy, popString } from './utils'; import { config } from './utils/config'; import { log } from './utils/log'; -import { artifactType, customArtifactType, customLibType, Fields, libType, Rule, Version } from './utils/types'; +import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, Version } from './utils/types'; let counter = 0; let parsedVersion: Version; @@ -229,7 +229,7 @@ const getAssets = async () => { log('debug', 'Downloaded assets'); }; -const parseRule = (lib: libType) => { +const parseRule = (lib: LibType) => { if (!lib.rules) return false; if (lib.rules.length <= 1 && lib.rules[0].action === 'allow' && lib.rules[0].os) return lib.rules[0].os.name !== getOS(); @@ -248,18 +248,18 @@ const getNatives = async () => { mkdirSync(nativeDirectory, { recursive: true }); const natives = async () => { - const natives: artifactType[] = []; + const natives: ArtifactType[] = []; await Promise.all( - parsedVersion.libraries.map(async (lib: libType) => { + parsedVersion.libraries.map(async (lib: LibType) => { if (!lib.downloads || !lib.downloads.classifiers) return; if (parseRule(lib)) return; const native = getOS() === 'osx' ? lib.downloads.classifiers['natives-osx'] - ? (lib.downloads.classifiers['natives-osx'] as artifactType) - : (lib.downloads.classifiers['natives-macos'] as artifactType) - : (lib.downloads.classifiers[`natives-${getOS()}`] as artifactType); + ? (lib.downloads.classifiers['natives-osx'] as ArtifactType) + : (lib.downloads.classifiers['natives-macos'] as ArtifactType) + : (lib.downloads.classifiers[`natives-${getOS()}`] as ArtifactType); natives.push(native); }), @@ -474,7 +474,7 @@ const getForgedWrapped = async () => { const downloadToDirectory = async ( directory: string, - libraries: libType[] | customArtifactType[], + libraries: LibType[] | CustomArtifactType[], eventName: string, ) => { const libs: string[] = []; @@ -496,7 +496,7 @@ const downloadToDirectory = async ( jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); } - const downloadLibrary = async (library: libType | customArtifactType) => { + const downloadLibrary = async (library: LibType | CustomArtifactType) => { if ('url' in library) { const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; await downloadAsync(url, jarPath, name, true, eventName); @@ -524,7 +524,7 @@ const downloadToDirectory = async ( return libs; }; -const getClasses = async (classJson: customLibType) => { +const getClasses = async (classJson: CustomLibType) => { let libs: string[] = []; const libraryDirectory = resolve(config.libraryRoot || join(config.root, 'libraries')); @@ -534,11 +534,11 @@ const getClasses = async (classJson: customLibType) => { libs = await downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom'); } - const parsed = parsedVersion.libraries.filter(Boolean).map((lib: libType) => { + const parsed = parsedVersion.libraries.filter(Boolean).map((lib: LibType) => { if (lib.downloads && lib.downloads.artifact && !parseRule(lib)) return lib; }); - libs = libs.concat(await downloadToDirectory(libraryDirectory, parsed as libType[], 'classes')); + libs = libs.concat(await downloadToDirectory(libraryDirectory, parsed as LibType[], 'classes')); counter = 0; if (classJson) libs.sort(); @@ -560,7 +560,7 @@ const processArguments = (...args: (string | Rule | string[])[]): string[] => { return result; }; -const getLaunchOptions = async (modification: customLibType | null): Promise => { +const getLaunchOptions = async (modification: CustomLibType | null): Promise => { const type = Object.assign({}, parsedVersion, modification); const args = type.minecraftArguments ? type.minecraftArguments.split(' ') : processArguments(type.arguments.game); const assetPath = resolve( diff --git a/src/utils/types.ts b/src/utils/types.ts index 93f3764..a2f475d 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -203,23 +203,23 @@ export type Rule = { features: Record; }; -export type artifactType = { +export type ArtifactType = { path: string; sha1: string; size: number; url: string; }; -export type libType = { +export type LibType = { downloads: { - artifact: artifactType; + artifact: ArtifactType; classifiers?: { - 'natives-linux'?: artifactType; - 'natives-osx'?: artifactType; - 'natives-macos'?: artifactType; - 'natives-windows'?: artifactType; - 'natives-windows-64'?: artifactType; - 'natives-windows-32'?: artifactType; + 'natives-linux'?: ArtifactType; + 'natives-osx'?: ArtifactType; + 'natives-macos'?: ArtifactType; + 'natives-windows'?: ArtifactType; + 'natives-windows-64'?: ArtifactType; + 'natives-windows-32'?: ArtifactType; }; }; name: string; @@ -231,14 +231,14 @@ export type libType = { }[]; }; -export type customArtifactType = { +export type CustomArtifactType = { name: string; url: string; sha1?: string; size?: number; }; -export type customLibType = { +export type CustomLibType = { id: string; mainClass: string; arguments: { @@ -249,7 +249,7 @@ export type customLibType = { name: string; url: string; }[]; - libraries: customArtifactType[]; + libraries: CustomArtifactType[]; }; export interface Version { @@ -270,7 +270,7 @@ export interface Version { }; }; id: string; - libraries: libType[]; + libraries: LibType[]; arguments?: { game: string | Rule | string[]; jvm?: string | Rule | string[]; From cb2d0d9801c1993ed7ebed3249128f694189ce20 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 15:13:46 +0300 Subject: [PATCH 44/97] No usage of ! and use Infinity by default for maxSockets --- clean.js | 2 +- src/handler.ts | 21 ++++++----- src/launcher.ts | 14 ++----- src/utils/config.ts | 4 +- src/utils/types.ts | 2 +- tests/vanilla.ts | 90 +++++++++++++++++++++++---------------------- 6 files changed, 66 insertions(+), 67 deletions(-) diff --git a/clean.js b/clean.js index d319178..5cb1cc0 100644 --- a/clean.js +++ b/clean.js @@ -1,4 +1,4 @@ -import { existsSync, rm } from 'fs'; +import { existsSync, rm } from 'node:fs'; // A simple way to delete the `build` folder // instead of `rm -rf` which is limited per OS diff --git a/src/handler.ts b/src/handler.ts index b04079e..4a4cf2f 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -51,8 +51,8 @@ const downloadAsync = async (url: string, directory: string, name: string, retry const response = await axios.get(url, { responseType: 'stream', timeout: config.timeout || 50000, - httpAgent: new http({ maxSockets: config.maxSockets || 2 }), - httpsAgent: new https({ maxSockets: config.maxSockets || 2 }), + httpAgent: new http({ maxSockets: config.maxSockets || Infinity }), + httpsAgent: new https({ maxSockets: config.maxSockets || Infinity }), }); const totalBytes = parseInt(response.headers['content-length']); @@ -95,7 +95,7 @@ const downloadAsync = async (url: string, directory: string, name: string, retry }; const getVersion = async () => { - const versionJsonPath = config.versionJson || join(config.directory!, `${config.version.number}.json`); + const versionJsonPath = config.versionJson || join(config.directory, `${config.version.number}.json`); if (existsSync(versionJsonPath)) { parsedVersion = JSON.parse(readFileSync(versionJsonPath).toString()); return parsedVersion; @@ -130,12 +130,12 @@ const getVersion = async () => { const getJar = async () => { await downloadAsync( parsedVersion.downloads.client.url, - config.directory!, + config.directory, `${config.version.custom ?? config.version.number}.jar`, true, 'version-jar', ); - writeFileSync(join(config.directory!, `${config.version.number}.json`), JSON.stringify(parsedVersion, null, 4)); + writeFileSync(join(config.directory, `${config.version.number}.json`), JSON.stringify(parsedVersion, null, 4)); return log('debug', 'Downloaded version jar and wrote version json'); }; @@ -277,7 +277,10 @@ const getNatives = async () => { await Promise.all( stat.map(async (native) => { if (!native) return; - const name = native.path.split('/').pop()!; + const name = native.path.split('/').pop(); + + // Shouldn't even be happening + if (!name) return; await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); const downloaded = await checkSum(native.sha1, join(nativeDirectory, name)); if (!existsSync(join(nativeDirectory, name)) || !downloaded) @@ -312,7 +315,7 @@ const fwAddArgs = () => { const forgeWrapperAgrs = [ `-Dforgewrapper.librariesDir=${resolve(config.libraryRoot || join(config.root, 'libraries'))}`, `-Dforgewrapper.installer=${config.forge}`, - `-Dforgewrapper.minecraft=${resolve(join(config.directory!, `${config.version.number}.jar`))}`, + `-Dforgewrapper.minecraft=${resolve(join(config.directory, `${config.version.number}.jar`))}`, ]; config.customArgs ? (config.customArgs = config.customArgs.concat(forgeWrapperAgrs)) @@ -423,8 +426,8 @@ const getForgedWrapped = async () => { await axios .get(downloadLink, { timeout: config.timeout || 50000, - httpAgent: new http({ maxSockets: config.maxSockets || 2 }), - httpsAgent: new https({ maxSockets: config.maxSockets || 2 }), + httpAgent: new http({ maxSockets: config.maxSockets || Infinity }), + httpsAgent: new https({ maxSockets: config.maxSockets || Infinity }), }) .then( ({ status }) => diff --git a/src/launcher.ts b/src/launcher.ts index 6cb19d0..b771b82 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -38,15 +38,12 @@ export const install = async () => { if (!existsSync(config.gameDirectory)) mkdirSync(config.gameDirectory, { recursive: true }); } - const directory = config.directory || join(config.root, 'versions', config.version.custom ?? config.version.number); - defineOptions({ directory: directory }); - await getVersion(); const mcPath = config.minecraftJar || (config.version.custom ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) - : join(directory, `${config.version.number}.jar`)); + : join(config.directory, `${config.version.number}.jar`)); await getNatives(); if (!existsSync(mcPath)) { @@ -82,17 +79,12 @@ export const start = async () => { return log('close', 1); } - const directory = - config.directory || - join(config.root, 'versions', config.version.custom ? config.version.custom : config.version.number); - defineOptions({ directory: directory }); - const versionFile = await getVersion(); const mcPath = config.minecraftJar || (config.version.custom ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) - : join(directory, `${config.version.number}.jar`)); + : join(config.directory, `${config.version.number}.jar`)); const nativePath = await getNatives(); const args: string[] = []; @@ -165,7 +157,7 @@ export const start = async () => { // So mods like fabric work. const jar = existsSync(mcPath) ? `${separator}${resolve(mcPath)}` - : `${separator}${resolve(join(directory, `${config.version.number}.jar`))}`; + : `${separator}${resolve(join(config.directory, `${config.version.number}.jar`))}`; classPaths.push(`${config.forge ? `${config.forge}${separator}` : ''}${classes.join(separator)}${jar}`); classPaths.push(file.mainClass); diff --git a/src/utils/config.ts b/src/utils/config.ts index 0abed59..1622c11 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,8 +1,10 @@ +import { join } from 'node:path'; import { offline } from 'src'; import { Options } from './types'; let config: Options = { root: './minecraft', + directory: '', authorization: offline('Steve'), detached: true, version: { @@ -17,11 +19,11 @@ let config: Options = { min: Math.pow(2, 9), max: Math.pow(2, 10), }, - maxSockets: Infinity, }; const defineOptions = (newConfig: Partial): void => { config = { ...config, ...newConfig }; + config.directory = join(config.root, 'versions', config.version.custom || config.version.number); return; }; diff --git a/src/utils/types.ts b/src/utils/types.ts index a2f475d..461d289 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -138,7 +138,7 @@ export interface Options { /** * Folder, where the Minecraft jar and version json are located. */ - directory?: string; + directory: string; natives?: string; assetRoot?: string; assetIndex?: string; diff --git a/tests/vanilla.ts b/tests/vanilla.ts index 31aeab8..c811dbc 100644 --- a/tests/vanilla.ts +++ b/tests/vanilla.ts @@ -5,11 +5,13 @@ import { afterAll, beforeAll, describe, expect, test } from 'vitest'; import { Client, defineOptions } from '../src'; describe('Minecraft Vanilla Legacy (1.8.9)', () => { - defineOptions({ - version: { - number: '1.8.9', - type: 'release', - }, + beforeAll(() => { + defineOptions({ + version: { + number: '1.8.9', + type: 'release', + }, + }); }); test( @@ -47,45 +49,45 @@ describe('Minecraft Vanilla Legacy (1.8.9)', () => { }); }); -describe('Minecraft Vanilla Modern (1.14.4)', () => { - defineOptions({ - version: { - number: '1.14.4', - type: 'release', - }, - }); +// describe('Minecraft Vanilla Modern (1.14.4)', () => { +// defineOptions({ +// version: { +// number: '1.14.4', +// type: 'release', +// }, +// }); - test( - 'Installation', - async () => { - await Client.install(); - expect(existsSync(resolve('./minecraft/cache/json/1.14.4.json'))).toBe(true); - expect(existsSync(resolve('./minecraft/natives/1.14.4'))).toBe(true); - expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.jar'))).toBe(true); - }, - 3 * 60 * 1000, - ); +// test( +// 'Installation', +// async () => { +// await Client.install(); +// expect(existsSync(resolve('./minecraft/cache/json/1.14.4.json'))).toBe(true); +// expect(existsSync(resolve('./minecraft/natives/1.14.4'))).toBe(true); +// expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.jar'))).toBe(true); +// }, +// 3 * 60 * 1000, +// ); - test( - 'Starting', - async () => { - const process = await Client.start(); - expect(process && typeof process.kill === 'function').toBe(true); - await new Promise((resolve) => { - setTimeout(() => { - (process as ChildProcessWithoutNullStreams).kill(); - resolve(); - }, 20 * 1000); - }); - expect(existsSync(resolve('./minecraft/saves'))).toBe(true); - expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); - }, - 3 * 60 * 1000, - ); +// test( +// 'Starting', +// async () => { +// const process = await Client.start(); +// expect(process && typeof process.kill === 'function').toBe(true); +// await new Promise((resolve) => { +// setTimeout(() => { +// (process as ChildProcessWithoutNullStreams).kill(); +// resolve(); +// }, 20 * 1000); +// }); +// expect(existsSync(resolve('./minecraft/saves'))).toBe(true); +// expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); +// }, +// 3 * 60 * 1000, +// ); - // Cleanup for other tests - afterAll(() => { - rmdirSync(resolve('./minecraft/saves')); - rmdirSync(resolve('./minecraft/resourcepacks')); - }); -}); +// // Cleanup for other tests +// afterAll(() => { +// rmdirSync(resolve('./minecraft/saves')); +// rmdirSync(resolve('./minecraft/resourcepacks')); +// }); +// }); From 300d5c2d66c7ed2a7891d6da49e4bc226bafdd36 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 15:18:33 +0300 Subject: [PATCH 45/97] Remake the exporting of `offline` --- src/authenticator.ts | 2 +- src/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/authenticator.ts b/src/authenticator.ts index 34eb972..4bedc75 100644 --- a/src/authenticator.ts +++ b/src/authenticator.ts @@ -1,7 +1,7 @@ import { v3 } from 'uuid'; import { User } from './utils/types'; -export default (username: string): User => { +export const offline = (username: string): User => { const uuid = v3(username, v3.DNS); return { access_token: uuid, client_token: uuid, uuid, name: username, user_properties: '{}' }; }; diff --git a/src/index.ts b/src/index.ts index 88a5fd4..7c1f7c7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ export * as Client from './launcher'; -export { default as offline } from './authenticator'; +export { offline } from './authenticator'; export * from './utils/config'; export { onLog } from './utils/log'; From b0c34765dc8b4639b908b3585fa87984e2ff15b5 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 15:19:34 +0300 Subject: [PATCH 46/97] Use `${number}M/G` as a type for memory --- src/utils/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/types.ts b/src/utils/types.ts index 461d289..42a372f 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -52,11 +52,11 @@ export interface Options { /** * Max amount of memory being used by Minecraft. */ - min: string | number; + min: `${number}M` | `${number}G` | number; /** * Min amount of memory being used by Minecraft. */ - max: string | number; + max: `${number}M` | `${number}G` | number; }; /** * Path to the JRE executable file, will default to java if not entered. From a57480c13e3998f1840ce4a0f4274591add23759 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 15:22:31 +0300 Subject: [PATCH 47/97] Enforce OS type --- src/utils/index.ts | 4 ++-- src/utils/types.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index 31e83f5..ad29d2e 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,12 +3,12 @@ import { createReadStream, stat } from 'node:fs'; import { resolve as _resolve } from 'node:path'; import { config } from './config'; import { log } from './log'; -import { Version } from './types'; +import { OS, Version } from './types'; const popString = (path: string) => path.split('/').slice(0, -1).join('/'); const cleanUp = (array: string[]) => [...new Set(Object.values(array).filter((value) => value !== null))]; -const getOS = () => { +const getOS = (): OS => { if (config.os) { return config.os; } else { diff --git a/src/utils/types.ts b/src/utils/types.ts index 42a372f..c035023 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -13,7 +13,7 @@ export interface Options { * * @default will autodetect */ - os?: 'windows' | 'osx' | 'linux'; + os?: OS; /** * Array of custom Minecraft arguments. */ @@ -198,6 +198,7 @@ export interface User { }; } +export type OS = 'windows' | 'osx' | 'linux'; export type Rule = { action: string; features: Record; From 659f680f888e8792b26926c3386f1ae1676666c4 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 15:36:56 +0300 Subject: [PATCH 48/97] Remove user_properties --- src/authenticator.ts | 2 +- src/handler.ts | 2 +- src/utils/types.ts | 3 +-- tests/auth.ts | 1 - 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/authenticator.ts b/src/authenticator.ts index 4bedc75..1ff4cea 100644 --- a/src/authenticator.ts +++ b/src/authenticator.ts @@ -3,5 +3,5 @@ import { User } from './utils/types'; export const offline = (username: string): User => { const uuid = v3(username, v3.DNS); - return { access_token: uuid, client_token: uuid, uuid, name: username, user_properties: '{}' }; + return { access_token: uuid, client_token: uuid, uuid, name: username }; }; diff --git a/src/handler.ts b/src/handler.ts index 4a4cf2f..132d859 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -582,7 +582,7 @@ const getLaunchOptions = async (modification: CustomLibType | null): Promise | string; meta?: { type: 'mojang' | 'msa'; demo?: boolean; @@ -287,7 +286,7 @@ export interface Fields { '${auth_player_name}': string; '${auth_uuid}': string; '${auth_xuid}': string; - '${user_properties}': string | Partial; + '${user_properties}': '{}'; '${user_type}': string; '${version_name}'?: string; '${assets_index_name}': string; diff --git a/tests/auth.ts b/tests/auth.ts index 0b96b74..0f0eca3 100644 --- a/tests/auth.ts +++ b/tests/auth.ts @@ -8,7 +8,6 @@ describe('Testing the offline authentication', () => { client_token: '882661dc-e54f-35ae-b9e7-6c691a8095cb', uuid: '882661dc-e54f-35ae-b9e7-6c691a8095cb', name: 'Pierce', - user_properties: '{}', }); }); }); From c83c8981322b111aaa2201c2e9be6cb066b4e728 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 15:42:55 +0300 Subject: [PATCH 49/97] Unbundle types --- src/authenticator.ts | 2 +- src/handler.ts | 5 +- src/types/Custom.ts | 22 +++++ src/types/Fields.ts | 18 ++++ src/{utils/types.ts => types/Options.ts} | 118 +---------------------- src/types/User.ts | 10 ++ src/types/Version.ts | 29 ++++++ src/types/index.ts | 34 +++++++ src/utils/config.ts | 2 +- src/utils/index.ts | 3 +- 10 files changed, 125 insertions(+), 118 deletions(-) create mode 100644 src/types/Custom.ts create mode 100644 src/types/Fields.ts rename src/{utils/types.ts => types/Options.ts} (66%) create mode 100644 src/types/User.ts create mode 100644 src/types/Version.ts create mode 100644 src/types/index.ts diff --git a/src/authenticator.ts b/src/authenticator.ts index 1ff4cea..ae1938d 100644 --- a/src/authenticator.ts +++ b/src/authenticator.ts @@ -1,5 +1,5 @@ import { v3 } from 'uuid'; -import { User } from './utils/types'; +import User from './types/User'; export const offline = (username: string): User => { const uuid = v3(username, v3.DNS); diff --git a/src/handler.ts b/src/handler.ts index 132d859..d784320 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -14,10 +14,13 @@ import { Agent as https } from 'node:https'; import { join, resolve, sep } from 'node:path'; import Zip from 'adm-zip'; import axios from 'axios'; +import { ArtifactType, LibType, Rule } from './types'; +import { CustomArtifactType, CustomLibType } from './types/Custom'; +import Fields from './types/Fields'; +import Version from './types/Version'; import { checkSum, cleanUp, getOS, isLegacy, popString } from './utils'; import { config } from './utils/config'; import { log } from './utils/log'; -import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, Version } from './utils/types'; let counter = 0; let parsedVersion: Version; diff --git a/src/types/Custom.ts b/src/types/Custom.ts new file mode 100644 index 0000000..c7b686f --- /dev/null +++ b/src/types/Custom.ts @@ -0,0 +1,22 @@ +import { Rule } from '.'; + +export type CustomArtifactType = { + name: string; + url: string; + sha1?: string; + size?: number; +}; + +export type CustomLibType = { + id: string; + mainClass: string; + arguments: { + game: string | Rule | string[]; + jvm: string | Rule | string[]; + }; + mavenFiles?: { + name: string; + url: string; + }[]; + libraries: CustomArtifactType[]; +}; diff --git a/src/types/Fields.ts b/src/types/Fields.ts new file mode 100644 index 0000000..4225554 --- /dev/null +++ b/src/types/Fields.ts @@ -0,0 +1,18 @@ +export default interface Fields { + '${auth_access_token}': string; + '${auth_session}': string; + '${auth_player_name}': string; + '${auth_uuid}': string; + '${auth_xuid}': string; + '${user_properties}': '{}'; + '${user_type}': string; + '${version_name}'?: string; + '${assets_index_name}': string; + '${game_directory}': string; + '${assets_root}': string; + '${game_assets}': string; + '${version_type}': string; + '${clientid}': string; + '${resolution_width}'?: number; + '${resolution_height}'?: number; +} diff --git a/src/utils/types.ts b/src/types/Options.ts similarity index 66% rename from src/utils/types.ts rename to src/types/Options.ts index b22124f..a0f0142 100644 --- a/src/utils/types.ts +++ b/src/types/Options.ts @@ -1,4 +1,7 @@ -export interface Options { +import { OS } from '.'; +import User from './User'; + +export default interface Options { /** * if true MCLC will remove the client package zip file after its finished extracting. */ @@ -185,116 +188,3 @@ export interface Options { */ forge?: string; } - -export interface User { - access_token: string; - client_token: string; - uuid: string; - name: string; - meta?: { - type: 'mojang' | 'msa'; - demo?: boolean; - }; -} - -export type OS = 'windows' | 'osx' | 'linux'; -export type Rule = { - action: string; - features: Record; -}; - -export type ArtifactType = { - path: string; - sha1: string; - size: number; - url: string; -}; - -export type LibType = { - downloads: { - artifact: ArtifactType; - classifiers?: { - 'natives-linux'?: ArtifactType; - 'natives-osx'?: ArtifactType; - 'natives-macos'?: ArtifactType; - 'natives-windows'?: ArtifactType; - 'natives-windows-64'?: ArtifactType; - 'natives-windows-32'?: ArtifactType; - }; - }; - name: string; - rules?: { - action: 'allow' | 'disallow'; - os: { - name?: string; - }; - }[]; -}; - -export type CustomArtifactType = { - name: string; - url: string; - sha1?: string; - size?: number; -}; - -export type CustomLibType = { - id: string; - mainClass: string; - arguments: { - game: string | Rule | string[]; - jvm: string | Rule | string[]; - }; - mavenFiles?: { - name: string; - url: string; - }[]; - libraries: CustomArtifactType[]; -}; - -export interface Version { - assetIndex: { - id: string; - sha1: string; - size: number; - totalSize: number; - url: string; - }; - assets: string; - complianceLevel: number; - downloads: { - client: { - sha1: string; - size: number; - url: string; - }; - }; - id: string; - libraries: LibType[]; - arguments?: { - game: string | Rule | string[]; - jvm?: string | Rule | string[]; - }; - minecraftArguments?: string; - type: string; - mainClass: string; -} - -export interface Fields { - '${auth_access_token}': string; - '${auth_session}': string; - '${auth_player_name}': string; - '${auth_uuid}': string; - '${auth_xuid}': string; - '${user_properties}': '{}'; - '${user_type}': string; - '${version_name}'?: string; - '${assets_index_name}': string; - '${game_directory}': string; - '${assets_root}': string; - '${game_assets}': string; - '${version_type}': string; - '${clientid}': string; - '${resolution_width}'?: number; - '${resolution_height}'?: number; -} diff --git a/src/types/User.ts b/src/types/User.ts new file mode 100644 index 0000000..486ca31 --- /dev/null +++ b/src/types/User.ts @@ -0,0 +1,10 @@ +export default interface User { + access_token: string; + client_token: string; + uuid: string; + name: string; + meta?: { + type: 'mojang' | 'msa'; + demo?: boolean; + }; +} diff --git a/src/types/Version.ts b/src/types/Version.ts new file mode 100644 index 0000000..bed5089 --- /dev/null +++ b/src/types/Version.ts @@ -0,0 +1,29 @@ +import { LibType, Rule } from '.'; + +export default interface Version { + assetIndex: { + id: string; + sha1: string; + size: number; + totalSize: number; + url: string; + }; + assets: string; + complianceLevel: number; + downloads: { + client: { + sha1: string; + size: number; + url: string; + }; + }; + id: string; + libraries: LibType[]; + arguments?: { + game: string | Rule | string[]; + jvm?: string | Rule | string[]; + }; + minecraftArguments?: string; + type: string; + mainClass: string; +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..b96a21c --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,34 @@ +export type OS = 'windows' | 'osx' | 'linux'; + +export type Rule = { + action: string; + features: Record; +}; + +export type ArtifactType = { + path: string; + sha1: string; + size: number; + url: string; +}; + +export type LibType = { + downloads: { + artifact: ArtifactType; + classifiers?: { + 'natives-linux'?: ArtifactType; + 'natives-osx'?: ArtifactType; + 'natives-macos'?: ArtifactType; + 'natives-windows'?: ArtifactType; + 'natives-windows-64'?: ArtifactType; + 'natives-windows-32'?: ArtifactType; + }; + }; + name: string; + rules?: { + action: 'allow' | 'disallow'; + os: { + name?: string; + }; + }[]; +}; diff --git a/src/utils/config.ts b/src/utils/config.ts index 1622c11..560095d 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,6 +1,6 @@ import { join } from 'node:path'; import { offline } from 'src'; -import { Options } from './types'; +import Options from 'src/types/Options'; let config: Options = { root: './minecraft', diff --git a/src/utils/index.ts b/src/utils/index.ts index ad29d2e..ffddc8a 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,9 +1,10 @@ import { createHash } from 'node:crypto'; import { createReadStream, stat } from 'node:fs'; import { resolve as _resolve } from 'node:path'; +import { OS } from 'src/types'; +import Version from 'src/types/Version'; import { config } from './config'; import { log } from './log'; -import { OS, Version } from './types'; const popString = (path: string) => path.split('/').slice(0, -1).join('/'); const cleanUp = (array: string[]) => [...new Set(Object.values(array).filter((value) => value !== null))]; From d5c44c453a24591b990731a948ec037d239c8e7d Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 16:32:38 +0300 Subject: [PATCH 50/97] Formatting --- src/utils/index.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index ffddc8a..ee98c78 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -10,17 +10,15 @@ const popString = (path: string) => path.split('/').slice(0, -1).join('/'); const cleanUp = (array: string[]) => [...new Set(Object.values(array).filter((value) => value !== null))]; const getOS = (): OS => { - if (config.os) { - return config.os; - } else { - switch (process.platform) { - case 'win32': - return 'windows'; - case 'darwin': - return 'osx'; - default: - return 'linux'; - } + if (config.os) return config.os; + + switch (process.platform) { + case 'win32': + return 'windows'; + case 'darwin': + return 'osx'; + default: + return 'linux'; } }; From f32590dddc6a0cfe93606c00123f16dfc0a8cde6 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 17:27:47 +0300 Subject: [PATCH 51/97] Usage of custom paths --- package.json | 7 ++- src/authenticator.ts | 2 +- src/handler.ts | 15 +++--- src/index.ts | 8 ++-- src/launcher.ts | 14 +++--- src/types/Custom.ts | 2 +- src/types/Options.ts | 3 +- src/types/Version.ts | 2 +- src/types/index.ts | 9 ++++ src/utils/config.ts | 8 ++-- src/utils/index.ts | 7 ++- src/utils/log.ts | 2 +- tests/vanilla.ts | 4 +- tsconfig.json | 9 +++- vitest.config.ts | 2 + yarn.lock | 112 ++++++++++++++++++++++++++++++++++++++++--- 16 files changed, 161 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index 61d3785..ae77ffb 100644 --- a/package.json +++ b/package.json @@ -30,8 +30,9 @@ "scripts": { "clean": "node clean.js", "test": "vitest", - "build": "yarn clean && yarn build:esm && yarn tsc", + "build": "yarn clean && yarn build:esm && tsc", "build:esm": "tsc --module esnext --declaration --outDir ./build/esm", + "postbuild": "tsc-alias && tsc-alias --outDir ./build/esm", "lint": "eslint --color .", "prettier": "prettier --check .", "prettier:write": "prettier --write .", @@ -54,8 +55,10 @@ "eslint-plugin-prettier": "^5.1.3", "prettier": "^3.2.5", "ts-node": "^10.9.2", + "tsc-alias": "^1.8.8", "typescript": "^5.3.3", "vite": "^5.1.6", + "vite-tsconfig-paths": "^4.3.1", "vitest": "^1.3.1" } -} \ No newline at end of file +} diff --git a/src/authenticator.ts b/src/authenticator.ts index ae1938d..5c06d59 100644 --- a/src/authenticator.ts +++ b/src/authenticator.ts @@ -1,5 +1,5 @@ +import { User } from '@types'; import { v3 } from 'uuid'; -import User from './types/User'; export const offline = (username: string): User => { const uuid = v3(username, v3.DNS); diff --git a/src/handler.ts b/src/handler.ts index d784320..baff1fb 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -1,3 +1,4 @@ +import { exec, ExecException } from 'node:child_process'; import { copyFileSync, createWriteStream, @@ -7,20 +8,16 @@ import { readFileSync, unlinkSync, writeFileSync, -} from 'fs'; -import { exec, ExecException } from 'node:child_process'; +} from 'node:fs'; import { Agent as http } from 'node:http'; import { Agent as https } from 'node:https'; import { join, resolve, sep } from 'node:path'; +import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, Version } from '@types'; +import { checkSum, cleanUp, getOS, isLegacy, popString } from '@utils'; +import { config } from '@utils/config'; +import { log } from '@utils/log'; import Zip from 'adm-zip'; import axios from 'axios'; -import { ArtifactType, LibType, Rule } from './types'; -import { CustomArtifactType, CustomLibType } from './types/Custom'; -import Fields from './types/Fields'; -import Version from './types/Version'; -import { checkSum, cleanUp, getOS, isLegacy, popString } from './utils'; -import { config } from './utils/config'; -import { log } from './utils/log'; let counter = 0; let parsedVersion: Version; diff --git a/src/index.ts b/src/index.ts index 7c1f7c7..04bf7a2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -export * as Client from './launcher'; -export { offline } from './authenticator'; -export * from './utils/config'; -export { onLog } from './utils/log'; +export * as Client from '@/launcher'; +export { offline } from '@/authenticator'; +export { config, defineConfig } from '@utils/config'; +export { onLog } from '@utils/log'; diff --git a/src/launcher.ts b/src/launcher.ts index b771b82..a6b1d69 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -13,11 +13,11 @@ import { getMemory, getNatives, getVersion, -} from './handler'; -import mclc from './mclc'; -import { cleanUp, getOS } from './utils'; -import { config, defineOptions } from './utils/config'; -import { log } from './utils/log'; +} from '@/handler'; +import mclc from '@/mclc'; +import { cleanUp, getOS } from '@utils'; +import { config, defineConfig } from '@utils/config'; +import { log } from '@utils/log'; export const launch = () => { throw Error( @@ -34,7 +34,7 @@ export const install = async () => { } if (config.gameDirectory) { - defineOptions({ gameDirectory: resolve(config.gameDirectory) }); + defineConfig({ gameDirectory: resolve(config.gameDirectory) }); if (!existsSync(config.gameDirectory)) mkdirSync(config.gameDirectory, { recursive: true }); } @@ -98,7 +98,7 @@ export const start = async () => { }), ); } else if (config.forge) { - defineOptions({ forge: resolve(config.forge) }); + defineConfig({ forge: resolve(config.forge) }); log('debug', 'Detected Forge in options, getting dependencies'); modifyJson = await getForgedWrapped(); } diff --git a/src/types/Custom.ts b/src/types/Custom.ts index c7b686f..c57ff00 100644 --- a/src/types/Custom.ts +++ b/src/types/Custom.ts @@ -1,4 +1,4 @@ -import { Rule } from '.'; +import { Rule } from '@types'; export type CustomArtifactType = { name: string; diff --git a/src/types/Options.ts b/src/types/Options.ts index a0f0142..6ca0f8d 100644 --- a/src/types/Options.ts +++ b/src/types/Options.ts @@ -1,5 +1,4 @@ -import { OS } from '.'; -import User from './User'; +import { OS, User } from '@types'; export default interface Options { /** diff --git a/src/types/Version.ts b/src/types/Version.ts index bed5089..873e68f 100644 --- a/src/types/Version.ts +++ b/src/types/Version.ts @@ -1,4 +1,4 @@ -import { LibType, Rule } from '.'; +import { LibType, Rule } from '@types'; export default interface Version { assetIndex: { diff --git a/src/types/index.ts b/src/types/index.ts index b96a21c..bd6a018 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,3 +1,10 @@ +// There's no other way to make it work +import { CustomArtifactType, CustomLibType } from './Custom'; +import Fields from './Fields'; +import Options from './Options'; +import User from './User'; +import Version from './Version'; + export type OS = 'windows' | 'osx' | 'linux'; export type Rule = { @@ -32,3 +39,5 @@ export type LibType = { }; }[]; }; + +export type { Version, User, CustomArtifactType, CustomLibType, Fields, Options }; diff --git a/src/utils/config.ts b/src/utils/config.ts index 560095d..1decfe9 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,6 +1,6 @@ import { join } from 'node:path'; -import { offline } from 'src'; -import Options from 'src/types/Options'; +import { offline } from '@/authenticator'; +import { Options } from '@types'; let config: Options = { root: './minecraft', @@ -21,10 +21,10 @@ let config: Options = { }, }; -const defineOptions = (newConfig: Partial): void => { +const defineConfig = (newConfig: Partial): void => { config = { ...config, ...newConfig }; config.directory = join(config.root, 'versions', config.version.custom || config.version.number); return; }; -export { config, defineOptions }; +export { config, defineConfig }; diff --git a/src/utils/index.ts b/src/utils/index.ts index ee98c78..828062d 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,10 +1,9 @@ import { createHash } from 'node:crypto'; import { createReadStream, stat } from 'node:fs'; import { resolve as _resolve } from 'node:path'; -import { OS } from 'src/types'; -import Version from 'src/types/Version'; -import { config } from './config'; -import { log } from './log'; +import { OS, Version } from '@types'; +import { config } from '@utils/config'; +import { log } from '@utils/log'; const popString = (path: string) => path.split('/').slice(0, -1).join('/'); const cleanUp = (array: string[]) => [...new Set(Object.values(array).filter((value) => value !== null))]; diff --git a/src/utils/log.ts b/src/utils/log.ts index dc9e16c..b3ed2e2 100644 --- a/src/utils/log.ts +++ b/src/utils/log.ts @@ -1,4 +1,4 @@ -import EventEmitter from 'events'; +import EventEmitter from 'node:events'; const eventEmitter = new EventEmitter(); diff --git a/tests/vanilla.ts b/tests/vanilla.ts index c811dbc..7613d36 100644 --- a/tests/vanilla.ts +++ b/tests/vanilla.ts @@ -2,11 +2,11 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process'; import { existsSync, rmdirSync } from 'node:fs'; import { resolve } from 'node:path'; import { afterAll, beforeAll, describe, expect, test } from 'vitest'; -import { Client, defineOptions } from '../src'; +import { Client, defineConfig } from '../src'; describe('Minecraft Vanilla Legacy (1.8.9)', () => { beforeAll(() => { - defineOptions({ + defineConfig({ version: { number: '1.8.9', type: 'release', diff --git a/tsconfig.json b/tsconfig.json index 48cea65..f302a89 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,7 +17,14 @@ "resolveJsonModule": true, "strict": true, "target": "ESNext", - "types": ["node"] + "types": ["node"], + "paths": { + "@types": ["src/types/"], + "@utils": ["src/utils/"], + "@utils/*": ["src/utils/*"], + "@": ["src/"], + "@/*": ["src/*"] + } }, "exclude": ["./build/"], "include": ["./src/"] diff --git a/vitest.config.ts b/vitest.config.ts index 7a934af..ab1f54a 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,5 +1,7 @@ +import tsconfigPaths from 'vite-tsconfig-paths'; import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { include: ['./tests/*'] }, + plugins: [tsconfigPaths()], }); diff --git a/yarn.lock b/yarn.lock index 914bd78..c95b296 100644 --- a/yarn.lock +++ b/yarn.lock @@ -770,6 +770,14 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -809,6 +817,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -824,7 +837,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@^3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -893,6 +906,21 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" +chokidar@^3.5.3: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -924,6 +952,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +commander@^9.0.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -948,7 +981,7 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -1283,7 +1316,7 @@ get-stream@^8.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -1321,7 +1354,7 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globby@^11.1.0: +globby@^11.0.4, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -1333,6 +1366,11 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" +globrex@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" + integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg== + graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -1384,12 +1422,19 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -1595,6 +1640,11 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mylas@^2.1.9: + version "2.1.13" + resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.13.tgz#1e23b37d58fdcc76e15d8a5ed23f9ae9fc0cbdf4" + integrity sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg== + nanoid@^3.3.7: version "3.3.7" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" @@ -1610,6 +1660,11 @@ node-releases@^2.0.14: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + npm-run-path@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" @@ -1711,7 +1766,7 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -1725,6 +1780,13 @@ pkg-types@^1.0.3: mlly "^1.2.0" pathe "^1.1.0" +plimit-lit@^1.2.6: + version "1.6.1" + resolved "https://registry.yarnpkg.com/plimit-lit/-/plimit-lit-1.6.1.tgz#a34594671b31ee8e93c72d505dfb6852eb72374a" + integrity sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA== + dependencies: + queue-lit "^1.5.1" + postcss@^8.4.35: version "8.4.35" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.35.tgz#60997775689ce09011edf083a549cea44aabe2f7" @@ -1770,6 +1832,11 @@ punycode@^2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== +queue-lit@^1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/queue-lit/-/queue-lit-1.5.2.tgz#83c24d4f4764802377b05a6e5c73017caf3f8747" + integrity sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -1780,6 +1847,13 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -1982,6 +2056,23 @@ ts-node@^10.9.2: v8-compile-cache-lib "^3.0.1" yn "3.1.1" +tsc-alias@^1.8.8: + version "1.8.8" + resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.8.8.tgz#48696af442b7656dd7905e37ae0bc332d80be3fe" + integrity sha512-OYUOd2wl0H858NvABWr/BoSKNERw3N9GTi3rHPK8Iv4O1UyUXIrTTOAZNHsjlVpXFOhpJBVARI1s+rzwLivN3Q== + dependencies: + chokidar "^3.5.3" + commander "^9.0.0" + globby "^11.0.4" + mylas "^2.1.9" + normalize-path "^3.0.0" + plimit-lit "^1.2.6" + +tsconfck@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-3.0.3.tgz#d9bda0e87d05b1c360e996c9050473c7e6f8084f" + integrity sha512-4t0noZX9t6GcPTfBAbIbbIU4pfpCwh0ueq3S4O/5qXI1VwK1outmxhe9dOiEWqMz3MW2LKgDTpqWV+37IWuVbA== + tslib@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" @@ -2055,6 +2146,15 @@ vite-node@1.3.1: picocolors "^1.0.0" vite "^5.0.0" +vite-tsconfig-paths@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.1.tgz#28762938151e7c80aec9d70c57e65ddce43a576f" + integrity sha512-cfgJwcGOsIxXOLU/nELPny2/LUD/lcf1IbfyeKTv2bsupVbTH/xpFtdQlBmIP1GEK2CjjLxYhFfB+QODFAx5aw== + dependencies: + debug "^4.1.1" + globrex "^0.1.2" + tsconfck "^3.0.1" + vite@^5.0.0, vite@^5.1.6: version "5.1.6" resolved "https://registry.yarnpkg.com/vite/-/vite-5.1.6.tgz#706dae5fab9e97f57578469eef1405fc483943e4" From 6abbb99954ce9315da2cb52951c62438b63b4b32 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 17:45:20 +0300 Subject: [PATCH 52/97] Formatting --- src/handler.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index baff1fb..9d113ac 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -22,12 +22,7 @@ import axios from 'axios'; let counter = 0; let parsedVersion: Version; -const checkJava = ( - java: string, -): Promise<{ - run: boolean; - message?: ExecException; -}> => +const checkJava = (java: string): Promise<{ run: boolean; message?: ExecException }> => new Promise((resolve) => { exec(`"${java}" -version`, (error, _, stderr) => { if (error) From 12ad5d7fd5e64fc62a4048563e37fb81d63daedf Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 17:48:40 +0300 Subject: [PATCH 53/97] Remove useless counter --- src/handler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/handler.ts b/src/handler.ts index 9d113ac..2698f7e 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -537,7 +537,6 @@ const getClasses = async (classJson: CustomLibType) => { }); libs = libs.concat(await downloadToDirectory(libraryDirectory, parsed as LibType[], 'classes')); - counter = 0; if (classJson) libs.sort(); From ffc0effc77cc5625c74f8622fa277dcf50a79c6e Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 17:48:56 +0300 Subject: [PATCH 54/97] Undo: Remove useless counter --- src/handler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/handler.ts b/src/handler.ts index 2698f7e..9d113ac 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -537,6 +537,7 @@ const getClasses = async (classJson: CustomLibType) => { }); libs = libs.concat(await downloadToDirectory(libraryDirectory, parsed as LibType[], 'classes')); + counter = 0; if (classJson) libs.sort(); From 11e9f3983ff036f76f5a2f09c71541ccf0b4ef54 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 18:01:02 +0300 Subject: [PATCH 55/97] Use a class for the Counter --- src/handler.ts | 29 +++++++++++++++-------------- src/utils/Counter.ts | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 src/utils/Counter.ts diff --git a/src/handler.ts b/src/handler.ts index 9d113ac..9b9b7e4 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -15,11 +15,12 @@ import { join, resolve, sep } from 'node:path'; import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, Version } from '@types'; import { checkSum, cleanUp, getOS, isLegacy, popString } from '@utils'; import { config } from '@utils/config'; +import Counter from '@utils/Counter'; import { log } from '@utils/log'; import Zip from 'adm-zip'; import axios from 'axios'; -let counter = 0; +const counter = new Counter(); let parsedVersion: Version; const checkJava = (java: string): Promise<{ run: boolean; message?: ExecException }> => @@ -164,15 +165,15 @@ const getAssets = async () => { if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) await downloadAsync(`${config.url.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets'); - counter++; + counter.increment(); log('progress', { type: 'assets', - task: counter, + task: counter.getValue(), total: Object.keys(index.objects).length, }); }), ); - counter = 0; + counter.reset(); // Copy assets to legacy if it's an older Minecraft version. if (isLegacy(parsedVersion)) { @@ -210,16 +211,16 @@ const getAssets = async () => { if (!existsSync(join(legacyDirectory, asset))) { copyFileSync(join(subAsset, hash), join(legacyDirectory, asset)); } - counter++; + counter.increment(); log('progress', { type: 'assets-copy', - task: counter, + task: counter.getValue(), total: Object.keys(index.objects).length, }); }), ); } - counter = 0; + counter.reset(); log('debug', 'Downloaded assets'); }; @@ -289,10 +290,10 @@ const getNatives = async () => { console.warn(e); } unlinkSync(join(nativeDirectory, name)); - counter++; + counter.increment(); log('progress', { type: 'natives', - task: counter, + task: counter.getValue(), total: stat.length, }); }), @@ -300,7 +301,7 @@ const getNatives = async () => { log('debug', 'Downloaded and extracted natives'); } - counter = 0; + counter.reset(); log('debug', `Set native path to ${nativeDirectory}`); return nativeDirectory; @@ -508,16 +509,16 @@ const downloadToDirectory = async ( if ('downloads' in library && library.downloads.artifact) if (!checkSum(library.downloads.artifact.sha1, join(jarPath, name))) await downloadLibrary(library); - counter++; + counter.increment(); log('progress', { type: eventName, - task: counter, + task: counter.getValue(), total: libraries.length, }); libs.push(`${jarPath}${sep}${name}`); }), ); - counter = 0; + counter.reset(); return libs; }; @@ -537,7 +538,7 @@ const getClasses = async (classJson: CustomLibType) => { }); libs = libs.concat(await downloadToDirectory(libraryDirectory, parsed as LibType[], 'classes')); - counter = 0; + counter.reset(); if (classJson) libs.sort(); diff --git a/src/utils/Counter.ts b/src/utils/Counter.ts new file mode 100644 index 0000000..519d766 --- /dev/null +++ b/src/utils/Counter.ts @@ -0,0 +1,21 @@ +class Counter { + value: number; + + constructor() { + this.value = 0; + } + + increment() { + this.value++; + } + + reset() { + this.value = 0; + } + + getValue() { + return this.value; + } +} + +export default Counter; From bce319c720dd2e4b1c12bef14350e34044f25b42 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 20:32:03 +0300 Subject: [PATCH 56/97] Remove the need to cache the version As it is unused --- src/handler.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 9b9b7e4..0c0240e 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -112,8 +112,6 @@ const getVersion = async () => { const desiredVersion = data.versions.find((version: { id: string }) => version.id === config.version.number); if (desiredVersion) { const { data } = await axios.get(desiredVersion.url); - writeFileSync(join(`${cache}/${config.version.number}.json`), JSON.stringify(data)); - log('debug', `Cached ${config.version.number}.json`); log('debug', 'Parsed version from version manifest'); parsedVersion = data; From 92a700ed19d8c50aa05c8d13a9fc6d8a30ca015f Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 21:01:36 +0300 Subject: [PATCH 57/97] [WIP] FileDownloader --- src/utils/FileDownloader.ts | 81 +++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 src/utils/FileDownloader.ts diff --git a/src/utils/FileDownloader.ts b/src/utils/FileDownloader.ts new file mode 100644 index 0000000..e50445d --- /dev/null +++ b/src/utils/FileDownloader.ts @@ -0,0 +1,81 @@ +import { createWriteStream, existsSync, mkdirSync, unlinkSync } from 'node:fs'; +import { Agent as http } from 'node:http'; +import { Agent as https } from 'node:https'; +import { join } from 'node:path'; +import { checkSum } from '@utils'; +import { config } from '@utils/config'; +import { log } from '@utils/log'; +import axios, { AxiosInstance } from 'axios'; + +class FileDownloader { + axios: AxiosInstance; + + constructor() { + this.axios = axios.create({ + responseType: 'stream', + timeout: config.timeout || 50000, + httpAgent: new http({ maxSockets: config.maxSockets || Infinity }), + httpsAgent: new https({ maxSockets: config.maxSockets || Infinity }), + }); + } + + async download( + url: string, + directory: string, + name: string, + type: string, + sha1: string | null, + retry: boolean = true, + ): Promise { + if (!retry) return true; + const fileToCheck = join(directory, name); + + try { + mkdirSync(directory, { recursive: true }); + + const response = await this.axios.get(url); + const totalBytes = parseInt(response.headers['content-length']); + let receivedBytes = 0; + + response.data.on('data', (data: Buffer | string) => { + typeof data === 'string' ? (receivedBytes += Buffer.byteLength(data)) : (receivedBytes += data.length); + + log('download-status', { + name: name, + type: type, + current: receivedBytes, + total: totalBytes, + }); + }); + + const file = createWriteStream(fileToCheck); + await response.data.pipe(file); + + file.on('finish', async () => { + if (sha1) { + const sum = await checkSum(sha1, fileToCheck); + if (!sum) { + await this.download(url, directory, name, type, sha1, false); + return false; + } + } + }); + + file.on('error', async (e) => { + log('debug', `Failed to download asset to ${fileToCheck} due to\n${e}. Retrying...`); + if (existsSync(fileToCheck)) unlinkSync(fileToCheck); + await this.download(url, directory, name, type, sha1, false); + return false; + }); + + log('download', name); + return true; + } catch (error) { + log('debug', `Failed to download asset to ${fileToCheck} due\n${error}. Retrying...`); + await this.download(url, directory, name, type, sha1, false); + return false; + } + } +} + +export default FileDownloader; From 5686051e854cda7695960ff9dac69eb55aa8b620 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 21:13:18 +0300 Subject: [PATCH 58/97] Fix retry and return a promise --- src/utils/FileDownloader.ts | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/utils/FileDownloader.ts b/src/utils/FileDownloader.ts index e50445d..2d34b61 100644 --- a/src/utils/FileDownloader.ts +++ b/src/utils/FileDownloader.ts @@ -27,7 +27,6 @@ class FileDownloader { sha1: string | null, retry: boolean = true, ): Promise { - if (!retry) return true; const fileToCheck = join(directory, name); try { @@ -48,31 +47,31 @@ class FileDownloader { }); }); - const file = createWriteStream(fileToCheck); - await response.data.pipe(file); + await response.data.pipe(createWriteStream(fileToCheck)); - file.on('finish', async () => { - if (sha1) { - const sum = await checkSum(sha1, fileToCheck); - if (!sum) { - await this.download(url, directory, name, type, sha1, false); - return false; + return new Promise((resolve, reject) => { + response.data.on('finish', async () => { + if (sha1) { + const sum = await checkSum(sha1, fileToCheck); + if (!sum) { + if (retry) await this.download(url, directory, name, type, sha1, false); + reject(false); + } } - } - }); - file.on('error', async (e) => { - log('debug', `Failed to download asset to ${fileToCheck} due to\n${e}. Retrying...`); - if (existsSync(fileToCheck)) unlinkSync(fileToCheck); - await this.download(url, directory, name, type, sha1, false); - return false; - }); + resolve(true); + }); - log('download', name); - return true; + response.data.on('error', async (e: Error) => { + log('debug', `Failed to download asset to ${fileToCheck} due to\n${e}. Retrying...`); + if (existsSync(fileToCheck)) unlinkSync(fileToCheck); + if (retry) await this.download(url, directory, name, type, sha1, false); + reject(false); + }); + }); } catch (error) { log('debug', `Failed to download asset to ${fileToCheck} due\n${error}. Retrying...`); - await this.download(url, directory, name, type, sha1, false); + if (retry) await this.download(url, directory, name, type, sha1, false); return false; } } From c8796445be6d20b014d0cba9c216eb819e54f812 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 12 Mar 2024 21:33:29 +0300 Subject: [PATCH 59/97] Move first forge library into a constant --- src/handler.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 0c0240e..615ee68 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -434,16 +434,15 @@ const getForgedWrapped = async () => { } // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. // If it doesn't, we simply remove it since we're already providing the universal jar. - if (json.libraries[0].downloads) { - const name = json.libraries[0].name; - if (name.includes('minecraftforge:forge') && !name.includes('universal')) { - json.libraries[0].name = `${name}:${jarEnding}`; - json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.replace( - '.jar', - `-${jarEnding}.jar`, - ); - json.libraries[0].downloads.artifact.url = `https://files.minecraftforge.net/maven/${json.libraries[0].downloads.artifact.path}`; + const firstLibrary = json.libraries[0]; + if (firstLibrary.downloads) { + if (firstLibrary.name.includes('minecraftforge:forge') && !firstLibrary.name.includes('universal')) { + firstLibrary.name = `${firstLibrary.name}:${jarEnding}`; + firstLibrary.downloads.artifact.path = firstLibrary.downloads.artifact.replace('.jar', `-${jarEnding}.jar`); + firstLibrary.downloads.artifact.url = `https://files.minecraftforge.net/maven/${firstLibrary.downloads.artifact.path}`; } + + json.libraries[0] = firstLibrary; } else { delete json.libraries[0]; } @@ -453,9 +452,8 @@ const getForgedWrapped = async () => { if (json.mavenFiles) json.mavenFiles = cleanUp(json.mavenFiles); // Saving file for next run! - if (!existsSync(join(config.root, 'forge', parsedVersion.id))) { + if (!existsSync(join(config.root, 'forge', parsedVersion.id))) mkdirSync(join(config.root, 'forge', parsedVersion.id), { recursive: true }); - } writeFileSync(versionPath, JSON.stringify(json, null, 4)); // Make MCLC treat modern forge as a custom version json rather then legacy forge. From 38b04bb86d27f6e9cd7f5ce38e6aa8964f3dbdb7 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 16 Mar 2024 14:12:16 +0300 Subject: [PATCH 60/97] Fix importing the library --- clean.js | 2 +- package.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/clean.js b/clean.js index 5cb1cc0..7347871 100644 --- a/clean.js +++ b/clean.js @@ -1,4 +1,4 @@ -import { existsSync, rm } from 'node:fs'; +const { existsSync, rm } = require('node:fs'); // A simple way to delete the `build` folder // instead of `rm -rf` which is limited per OS diff --git a/package.json b/package.json index ae77ffb..7ef391b 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "files": [ "./build/" ], - "type": "module", "scripts": { "clean": "node clean.js", "test": "vitest", From 72c4fa3ed1f3ecd968c71f84419d45d3f156c5b0 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Thu, 21 Mar 2024 23:36:16 +0300 Subject: [PATCH 61/97] [WIP] Fix (sort of) the FileDownloader --- src/handler.ts | 67 +++++++++----------- src/utils/FileDownloader.ts | 121 +++++++++++++++++++++++++++--------- 2 files changed, 124 insertions(+), 64 deletions(-) diff --git a/src/handler.ts b/src/handler.ts index 615ee68..be7a3ae 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -16,10 +16,12 @@ import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, import { checkSum, cleanUp, getOS, isLegacy, popString } from '@utils'; import { config } from '@utils/config'; import Counter from '@utils/Counter'; +import FileDownloader from '@utils/FileDownloader'; import { log } from '@utils/log'; import Zip from 'adm-zip'; import axios from 'axios'; +const fd = new FileDownloader(); const counter = new Counter(); let parsedVersion: Version; @@ -122,13 +124,14 @@ const getVersion = async () => { }; const getJar = async () => { - await downloadAsync( - parsedVersion.downloads.client.url, - config.directory, - `${config.version.custom ?? config.version.number}.jar`, - true, - 'version-jar', - ); + fd.add({ + url: parsedVersion.downloads.client.url, + directory: config.directory, + name: `${config.version.custom ?? config.version.number}.jar`, + type: 'version-jar', + hash: parsedVersion.downloads.client.sha1, + }); + await fd.start(); writeFileSync(join(config.directory, `${config.version.number}.json`), JSON.stringify(parsedVersion, null, 4)); return log('debug', 'Downloaded version jar and wrote version json'); }; @@ -138,40 +141,32 @@ const getAssets = async () => { const assetId = config.version.custom || config.version.number; if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) { - await downloadAsync( - parsedVersion.assetIndex.url, - join(assetDirectory, 'indexes'), - `${assetId}.json`, - true, - 'asset-json', - ); + fd.add({ + url: parsedVersion.assetIndex.url, + directory: join(assetDirectory, 'indexes'), + name: `${assetId}.json`, + type: 'asset-json', + hash: parsedVersion.assetIndex.sha1, + }); + await fd.start(); } const index = JSON.parse(readFileSync(join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' })); - - log('progress', { - type: 'assets', - task: 0, - total: Object.keys(index.objects).length, - }); - - await Promise.all( - Object.keys(index.objects).map(async (asset) => { - const hash = index.objects[asset].hash; - const subhash = hash.substring(0, 2); - const subAsset = join(assetDirectory, 'objects', subhash); - - if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) - await downloadAsync(`${config.url.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets'); - counter.increment(); - log('progress', { + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = join(assetDirectory, 'objects', subhash); + + if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) + fd.add({ + url: `${config.url.resource}/${subhash}/${hash}`, + directory: subAsset, + name: hash, type: 'assets', - task: counter.getValue(), - total: Object.keys(index.objects).length, }); - }), - ); - counter.reset(); + }); + + await fd.start(); // Copy assets to legacy if it's an older Minecraft version. if (isLegacy(parsedVersion)) { diff --git a/src/utils/FileDownloader.ts b/src/utils/FileDownloader.ts index 2d34b61..e026566 100644 --- a/src/utils/FileDownloader.ts +++ b/src/utils/FileDownloader.ts @@ -7,32 +7,84 @@ import { config } from '@utils/config'; import { log } from '@utils/log'; import axios, { AxiosInstance } from 'axios'; +interface DownloadableFile { + url: string; + directory: string; + name: string; + type: string; + hash?: string; + retriedCount?: number; +} + class FileDownloader { axios: AxiosInstance; + maxParallel: number; + maxRetries: number; + queue: DownloadableFile[] = []; + private _counter: number = 0; + private _total: number = 0; - constructor() { + constructor(maxParallel?: number, maxRetries?: number) { this.axios = axios.create({ responseType: 'stream', timeout: config.timeout || 50000, httpAgent: new http({ maxSockets: config.maxSockets || Infinity }), httpsAgent: new https({ maxSockets: config.maxSockets || Infinity }), }); + this.maxParallel = maxParallel || 5; + this.maxRetries = maxRetries || 5; + } + + public add(file: DownloadableFile) { + this.queue.push(file); + this._total++; + } + + public reset() { + this.queue = []; + this._counter = 0; + this._total = 0; } - async download( - url: string, - directory: string, - name: string, - type: string, - sha1: string | null, - retry: boolean = true, - ): Promise { - const fileToCheck = join(directory, name); + public get counter() { + return this._counter; + } + + public get total() { + return this._total; + } + + public async start() { + const promises: Promise[] = []; + + while (this.queue.length > 0 && this.counter < this.maxParallel) { + const file = this.queue.shift(); + if (file) { + this._counter++; + promises.push(this.download(file)); + } + } try { - mkdirSync(directory, { recursive: true }); + await Promise.all(promises); + } catch (err) { + console.error(err); + } + } + + private onDownloadFinished() { + this._counter++; + const nextFile = this.queue.shift(); + if (nextFile) this.download(nextFile); + } + + public async download(file: DownloadableFile): Promise { + const fileToCheck = join(file.directory, file.name); - const response = await this.axios.get(url); + try { + mkdirSync(file.directory, { recursive: true }); + + const response = await this.axios.get(file.url); const totalBytes = parseInt(response.headers['content-length']); let receivedBytes = 0; @@ -40,41 +92,54 @@ class FileDownloader { typeof data === 'string' ? (receivedBytes += Buffer.byteLength(data)) : (receivedBytes += data.length); log('download-status', { - name: name, - type: type, + name: file.name, + type: file.type, current: receivedBytes, total: totalBytes, }); }); - await response.data.pipe(createWriteStream(fileToCheck)); + const fileStream = createWriteStream(fileToCheck); + response.data.pipe(fileStream); - return new Promise((resolve, reject) => { - response.data.on('finish', async () => { - if (sha1) { - const sum = await checkSum(sha1, fileToCheck); - if (!sum) { - if (retry) await this.download(url, directory, name, type, sha1, false); - reject(false); - } + return await new Promise((resolve, reject) => { + fileStream.on('finish', async () => { + if (file.hash) { + const sum = await checkSum(file.hash, fileToCheck); + if (!sum) this.onFileDownloadFailed(file); } + this.onDownloadFinished(); resolve(true); }); - response.data.on('error', async (e: Error) => { - log('debug', `Failed to download asset to ${fileToCheck} due to\n${e}. Retrying...`); + fileStream.on('error', (error: Error) => { + log('debug', `Failed to download asset to ${fileToCheck} due\n${error}. Retrying...`); if (existsSync(fileToCheck)) unlinkSync(fileToCheck); - if (retry) await this.download(url, directory, name, type, sha1, false); - reject(false); + + this.onFileDownloadFailed(file); + reject(); }); }); } catch (error) { log('debug', `Failed to download asset to ${fileToCheck} due\n${error}. Retrying...`); - if (retry) await this.download(url, directory, name, type, sha1, false); + this.onFileDownloadFailed(file); return false; } } + + private onFileDownloadFailed(file: DownloadableFile) { + file.retriedCount = file.retriedCount ? file.retriedCount + 1 : 1; + if (file.retriedCount >= this.maxRetries) + throw new Error( + `Failed to download asset too many times. ${file.name} has been retried ${this.maxRetries} times and still failed.`, + ); + + this._counter--; + this._total--; + this.add(file); + return; + } } export default FileDownloader; From 8c665918fbaf8fe97f8dad59eb9220a58a2778d1 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 6 Apr 2024 22:30:23 +0300 Subject: [PATCH 62/97] Remove FileDownloader --- src/handler.ts | 70 +++++++++-------- src/utils/FileDownloader.ts | 145 ------------------------------------ 2 files changed, 37 insertions(+), 178 deletions(-) delete mode 100644 src/utils/FileDownloader.ts diff --git a/src/handler.ts b/src/handler.ts index be7a3ae..e7e0f8e 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -16,12 +16,10 @@ import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, import { checkSum, cleanUp, getOS, isLegacy, popString } from '@utils'; import { config } from '@utils/config'; import Counter from '@utils/Counter'; -import FileDownloader from '@utils/FileDownloader'; import { log } from '@utils/log'; import Zip from 'adm-zip'; import axios from 'axios'; -const fd = new FileDownloader(); const counter = new Counter(); let parsedVersion: Version; @@ -124,14 +122,13 @@ const getVersion = async () => { }; const getJar = async () => { - fd.add({ - url: parsedVersion.downloads.client.url, - directory: config.directory, - name: `${config.version.custom ?? config.version.number}.jar`, - type: 'version-jar', - hash: parsedVersion.downloads.client.sha1, - }); - await fd.start(); + await downloadAsync( + parsedVersion.downloads.client.url, + config.directory, + `${config.version.custom ?? config.version.number}.jar`, + true, + 'version-jar', + ); writeFileSync(join(config.directory, `${config.version.number}.json`), JSON.stringify(parsedVersion, null, 4)); return log('debug', 'Downloaded version jar and wrote version json'); }; @@ -140,33 +137,40 @@ const getAssets = async () => { const assetDirectory = resolve(config.assetRoot || join(config.root, 'assets')); const assetId = config.version.custom || config.version.number; - if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) { - fd.add({ - url: parsedVersion.assetIndex.url, - directory: join(assetDirectory, 'indexes'), - name: `${assetId}.json`, - type: 'asset-json', - hash: parsedVersion.assetIndex.sha1, - }); - await fd.start(); - } + if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) + await downloadAsync( + parsedVersion.assetIndex.url, + join(assetDirectory, 'indexes'), + `${assetId}.json`, + true, + 'asset-json', + ); const index = JSON.parse(readFileSync(join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' })); - Object.keys(index.objects).map(async (asset) => { - const hash = index.objects[asset].hash; - const subhash = hash.substring(0, 2); - const subAsset = join(assetDirectory, 'objects', subhash); - - if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) - fd.add({ - url: `${config.url.resource}/${subhash}/${hash}`, - directory: subAsset, - name: hash, - type: 'assets', - }); + + log('progress', { + type: 'assets', + task: 0, + total: Object.keys(index.objects).length, }); - await fd.start(); + await Promise.all( + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = join(assetDirectory, 'objects', subhash); + + if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) + await downloadAsync(`${config.url.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets'); + counter.increment(); + log('progress', { + type: 'assets', + task: counter.getValue(), + total: Object.keys(index.objects).length, + }); + }), + ); + counter.reset(); // Copy assets to legacy if it's an older Minecraft version. if (isLegacy(parsedVersion)) { diff --git a/src/utils/FileDownloader.ts b/src/utils/FileDownloader.ts deleted file mode 100644 index e026566..0000000 --- a/src/utils/FileDownloader.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { createWriteStream, existsSync, mkdirSync, unlinkSync } from 'node:fs'; -import { Agent as http } from 'node:http'; -import { Agent as https } from 'node:https'; -import { join } from 'node:path'; -import { checkSum } from '@utils'; -import { config } from '@utils/config'; -import { log } from '@utils/log'; -import axios, { AxiosInstance } from 'axios'; - -interface DownloadableFile { - url: string; - directory: string; - name: string; - type: string; - hash?: string; - retriedCount?: number; -} - -class FileDownloader { - axios: AxiosInstance; - maxParallel: number; - maxRetries: number; - queue: DownloadableFile[] = []; - private _counter: number = 0; - private _total: number = 0; - - constructor(maxParallel?: number, maxRetries?: number) { - this.axios = axios.create({ - responseType: 'stream', - timeout: config.timeout || 50000, - httpAgent: new http({ maxSockets: config.maxSockets || Infinity }), - httpsAgent: new https({ maxSockets: config.maxSockets || Infinity }), - }); - this.maxParallel = maxParallel || 5; - this.maxRetries = maxRetries || 5; - } - - public add(file: DownloadableFile) { - this.queue.push(file); - this._total++; - } - - public reset() { - this.queue = []; - this._counter = 0; - this._total = 0; - } - - public get counter() { - return this._counter; - } - - public get total() { - return this._total; - } - - public async start() { - const promises: Promise[] = []; - - while (this.queue.length > 0 && this.counter < this.maxParallel) { - const file = this.queue.shift(); - if (file) { - this._counter++; - promises.push(this.download(file)); - } - } - - try { - await Promise.all(promises); - } catch (err) { - console.error(err); - } - } - - private onDownloadFinished() { - this._counter++; - const nextFile = this.queue.shift(); - if (nextFile) this.download(nextFile); - } - - public async download(file: DownloadableFile): Promise { - const fileToCheck = join(file.directory, file.name); - - try { - mkdirSync(file.directory, { recursive: true }); - - const response = await this.axios.get(file.url); - const totalBytes = parseInt(response.headers['content-length']); - let receivedBytes = 0; - - response.data.on('data', (data: Buffer | string) => { - typeof data === 'string' ? (receivedBytes += Buffer.byteLength(data)) : (receivedBytes += data.length); - - log('download-status', { - name: file.name, - type: file.type, - current: receivedBytes, - total: totalBytes, - }); - }); - - const fileStream = createWriteStream(fileToCheck); - response.data.pipe(fileStream); - - return await new Promise((resolve, reject) => { - fileStream.on('finish', async () => { - if (file.hash) { - const sum = await checkSum(file.hash, fileToCheck); - if (!sum) this.onFileDownloadFailed(file); - } - - this.onDownloadFinished(); - resolve(true); - }); - - fileStream.on('error', (error: Error) => { - log('debug', `Failed to download asset to ${fileToCheck} due\n${error}. Retrying...`); - if (existsSync(fileToCheck)) unlinkSync(fileToCheck); - - this.onFileDownloadFailed(file); - reject(); - }); - }); - } catch (error) { - log('debug', `Failed to download asset to ${fileToCheck} due\n${error}. Retrying...`); - this.onFileDownloadFailed(file); - return false; - } - } - - private onFileDownloadFailed(file: DownloadableFile) { - file.retriedCount = file.retriedCount ? file.retriedCount + 1 : 1; - if (file.retriedCount >= this.maxRetries) - throw new Error( - `Failed to download asset too many times. ${file.name} has been retried ${this.maxRetries} times and still failed.`, - ); - - this._counter--; - this._total--; - this.add(file); - return; - } -} - -export default FileDownloader; From a177e14b0f21d3494c2facff1e4d87d67db105b5 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 6 Apr 2024 22:36:14 +0300 Subject: [PATCH 63/97] Remake the custom paths --- src/authenticator.ts | 2 +- src/handler.ts | 10 +++++----- src/index.ts | 4 ++-- src/launcher.ts | 6 +++--- src/types/Custom.ts | 2 +- src/types/Options.ts | 2 +- src/types/Version.ts | 2 +- src/types/index.ts | 11 +++++------ src/utils/config.ts | 2 +- src/utils/index.ts | 6 +++--- tsconfig.json | 4 ---- 11 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/authenticator.ts b/src/authenticator.ts index 5c06d59..fb2a8f9 100644 --- a/src/authenticator.ts +++ b/src/authenticator.ts @@ -1,4 +1,4 @@ -import { User } from '@types'; +import { User } from '@/types'; import { v3 } from 'uuid'; export const offline = (username: string): User => { diff --git a/src/handler.ts b/src/handler.ts index e7e0f8e..039f5c9 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -12,11 +12,11 @@ import { import { Agent as http } from 'node:http'; import { Agent as https } from 'node:https'; import { join, resolve, sep } from 'node:path'; -import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, Version } from '@types'; -import { checkSum, cleanUp, getOS, isLegacy, popString } from '@utils'; -import { config } from '@utils/config'; -import Counter from '@utils/Counter'; -import { log } from '@utils/log'; +import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, Version } from '@/types'; +import { checkSum, cleanUp, getOS, isLegacy, popString } from '@/utils'; +import { config } from '@/utils/config'; +import Counter from '@/utils/Counter'; +import { log } from '@/utils/log'; import Zip from 'adm-zip'; import axios from 'axios'; diff --git a/src/index.ts b/src/index.ts index 04bf7a2..0c49e10 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ export * as Client from '@/launcher'; export { offline } from '@/authenticator'; -export { config, defineConfig } from '@utils/config'; -export { onLog } from '@utils/log'; +export { config, defineConfig } from '@/utils/config'; +export { onLog } from '@/utils/log'; diff --git a/src/launcher.ts b/src/launcher.ts index a6b1d69..b06f074 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -15,9 +15,9 @@ import { getVersion, } from '@/handler'; import mclc from '@/mclc'; -import { cleanUp, getOS } from '@utils'; -import { config, defineConfig } from '@utils/config'; -import { log } from '@utils/log'; +import { cleanUp, getOS } from '@/utils'; +import { config, defineConfig } from '@/utils/config'; +import { log } from '@/utils/log'; export const launch = () => { throw Error( diff --git a/src/types/Custom.ts b/src/types/Custom.ts index c57ff00..3a0c71a 100644 --- a/src/types/Custom.ts +++ b/src/types/Custom.ts @@ -1,4 +1,4 @@ -import { Rule } from '@types'; +import { Rule } from '@/types'; export type CustomArtifactType = { name: string; diff --git a/src/types/Options.ts b/src/types/Options.ts index 6ca0f8d..582a9f6 100644 --- a/src/types/Options.ts +++ b/src/types/Options.ts @@ -1,4 +1,4 @@ -import { OS, User } from '@types'; +import { OS, User } from '@/types'; export default interface Options { /** diff --git a/src/types/Version.ts b/src/types/Version.ts index 873e68f..e6c7f09 100644 --- a/src/types/Version.ts +++ b/src/types/Version.ts @@ -1,4 +1,4 @@ -import { LibType, Rule } from '@types'; +import { LibType, Rule } from '@/types'; export default interface Version { assetIndex: { diff --git a/src/types/index.ts b/src/types/index.ts index bd6a018..a1ce43d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,9 +1,8 @@ -// There's no other way to make it work -import { CustomArtifactType, CustomLibType } from './Custom'; -import Fields from './Fields'; -import Options from './Options'; -import User from './User'; -import Version from './Version'; +import { CustomArtifactType, CustomLibType } from '@/types/Custom'; +import Fields from '@/types/Fields'; +import Options from '@/types/Options'; +import User from '@/types/User'; +import Version from '@/types/Version'; export type OS = 'windows' | 'osx' | 'linux'; diff --git a/src/utils/config.ts b/src/utils/config.ts index 1decfe9..2a2464d 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,6 +1,6 @@ import { join } from 'node:path'; import { offline } from '@/authenticator'; -import { Options } from '@types'; +import { Options } from '@/types'; let config: Options = { root: './minecraft', diff --git a/src/utils/index.ts b/src/utils/index.ts index 828062d..9212389 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,9 +1,9 @@ import { createHash } from 'node:crypto'; import { createReadStream, stat } from 'node:fs'; import { resolve as _resolve } from 'node:path'; -import { OS, Version } from '@types'; -import { config } from '@utils/config'; -import { log } from '@utils/log'; +import { OS, Version } from '@/types'; +import { config } from '@/utils/config'; +import { log } from '@/utils/log'; const popString = (path: string) => path.split('/').slice(0, -1).join('/'); const cleanUp = (array: string[]) => [...new Set(Object.values(array).filter((value) => value !== null))]; diff --git a/tsconfig.json b/tsconfig.json index f302a89..8752c2c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,10 +19,6 @@ "target": "ESNext", "types": ["node"], "paths": { - "@types": ["src/types/"], - "@utils": ["src/utils/"], - "@utils/*": ["src/utils/*"], - "@": ["src/"], "@/*": ["src/*"] } }, From 76d8370bc7469fd6d1b300e3d43ff232470e2d1d Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 6 Apr 2024 22:46:42 +0300 Subject: [PATCH 64/97] Use rimraf --- clean.js | 5 -- package.json | 4 +- yarn.lock | 174 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 173 insertions(+), 10 deletions(-) delete mode 100644 clean.js diff --git a/clean.js b/clean.js deleted file mode 100644 index 7347871..0000000 --- a/clean.js +++ /dev/null @@ -1,5 +0,0 @@ -const { existsSync, rm } = require('node:fs'); - -// A simple way to delete the `build` folder -// instead of `rm -rf` which is limited per OS -if (existsSync('build')) rm('build', { recursive: true, force: true }, () => void 0); diff --git a/package.json b/package.json index 7ef391b..2a6b335 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "minecraft-launcher-core", "version": "3.19.0", "description": "Lightweight module that downloads and runs Minecraft using javascript / NodeJS", + "type": "module", "repository": { "type": "git", "url": "git+https://github.com/Pierce01/MinecraftLauncher-core.git" @@ -27,7 +28,7 @@ "./build/" ], "scripts": { - "clean": "node clean.js", + "clean": "rimraf build", "test": "vitest", "build": "yarn clean && yarn build:esm && tsc", "build:esm": "tsc --module esnext --declaration --outDir ./build/esm", @@ -40,6 +41,7 @@ "dependencies": { "adm-zip": "^0.5.10", "axios": "^1.6.7", + "rimraf": "^5.0.5", "uuid": "^8.3.2" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index c95b296..17b0b36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -379,6 +379,18 @@ "@babel/types" "^7.21.5" semver "^7.5.2" +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -447,6 +459,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + "@pkgr/core@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" @@ -751,6 +768,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -758,7 +780,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -770,6 +792,11 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -972,7 +999,7 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -1029,11 +1056,26 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + electron-to-chromium@^1.4.668: version "1.4.683" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.683.tgz#b68167ed66dbea01feb86915aca92c09bc1b651a" integrity sha512-FmopjiJjkUzqa5F5Sv+wxd8KimtCxyLFOFgRPwEeMLVmP+vHH/GjNGCuIYrCIchbMSiOe+nG/OPBbR/XoExBNA== +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + esbuild@^0.19.3: version "0.19.12" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.12.tgz#dc82ee5dc79e82f5a5c3b4323a2a641827db3e04" @@ -1282,6 +1324,14 @@ follow-redirects@^1.15.4: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== +foreground-child@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" + integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^4.0.1" + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -1330,6 +1380,17 @@ glob-parent@^6.0.2: dependencies: is-glob "^4.0.3" +glob@^10.3.7: + version "10.3.12" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" + integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^2.3.6" + minimatch "^9.0.1" + minipass "^7.0.4" + path-scurry "^1.10.2" + glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -1434,6 +1495,11 @@ is-extglob@^2.1.1: resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -1461,6 +1527,15 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +jackspeak@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" + integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -1550,6 +1625,11 @@ loupe@^2.3.6, loupe@^2.3.7: dependencies: get-func-name "^2.0.1" +lru-cache@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -1625,6 +1705,18 @@ minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.1: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4: + version "7.0.4" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" + integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== + mlly@^1.2.0, mlly@^1.4.2: version "1.6.1" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.6.1.tgz#0983067dc3366d6314fc5e12712884e6978d028f" @@ -1746,6 +1838,14 @@ path-key@^4.0.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== +path-scurry@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" + integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -1871,6 +1971,13 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rimraf@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" + integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== + dependencies: + glob "^10.3.7" + rollup@^4.2.0: version "4.13.0" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.13.0.tgz#dd2ae144b4cdc2ea25420477f68d4937a721237a" @@ -1929,7 +2036,7 @@ siginfo@^2.0.0: resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== -signal-exit@^4.1.0: +signal-exit@^4.0.1, signal-exit@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== @@ -1954,13 +2061,54 @@ std-env@^3.5.0: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== -strip-ansi@^6.0.1: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-final-newline@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" @@ -2207,6 +2355,24 @@ why-is-node-running@^2.2.2: siginfo "^2.0.0" stackback "0.0.2" +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From f4e21e8736eb70e76093e3fa9098f6aa598bac7d Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 6 Apr 2024 23:49:06 +0300 Subject: [PATCH 65/97] Use prebuild instead of clean --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 2a6b335..ff7659d 100644 --- a/package.json +++ b/package.json @@ -28,10 +28,9 @@ "./build/" ], "scripts": { - "clean": "rimraf build", "test": "vitest", - "build": "yarn clean && yarn build:esm && tsc", - "build:esm": "tsc --module esnext --declaration --outDir ./build/esm", + "prebuild": "rimraf build", + "build": "tsc && tsc --module esnext --declaration --outDir ./build/esm", "postbuild": "tsc-alias && tsc-alias --outDir ./build/esm", "lint": "eslint --color .", "prettier": "prettier --check .", From b6457136b99250983ac10c5539841a245acccb9e Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sun, 7 Apr 2024 00:41:48 +0300 Subject: [PATCH 66/97] Refactor on README.md --- README.md | 166 +++++++++++++++++++----------------------------------- 1 file changed, 57 insertions(+), 109 deletions(-) diff --git a/README.md b/README.md index 7090714..8987b11 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -![Main Logo](/imgs/header.png) +![MCLC](/imgs/header.png) [![MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![Version](https://img.shields.io/badge/stable_version-3.19.0-blue) MCLC (Minecraft Launcher Core) is a NodeJS solution for launching modded and vanilla Minecraft without having to download and format everything yourself. -Basically a core for your Electron or script based launchers. +Basically a core for your Electron or script based launcher. ### Getting support @@ -28,145 +28,93 @@ pnpm add minecraft-launcher-core ### Example ```js -import { Authenticator, Client } from 'minecraft-launcher-core'; - -const launcher = new Client(); -const options = { - // This will launch in offline mode, if you want - // to use a Microsoft Account, see details below - authorization: Authenticator.getAuth('Steve'), - root: './minecraft', +import { Client, defineConfig, onLog, offline } from 'minecraft-launcher-core'; + +defineConfig({ + // This will launch in offline mode, if you want to use + // a Microsoft Account, see details below + authorization: offline('Steve'), + // 1.14.4 is the default version, you can remove it if you are using it version: { number: '1.14.4', type: 'release', - }, - memory: { - max: '4G', - min: '2G', - }, -}; + } +}); -launcher.launch(options); +await Client.install(); +await Client.launch(); -launcher.on('debug', (e) => console.log(e)); -launcher.on('data', (e) => console.log(e)); +onLog('debug', (e) => console.log(e)); +onLog('data', (e) => console.log(e)); ``` ### Using a Microsoft Account -In order to authenticate with a Microsoft Account, you would need to use [MSMC](https://github.com/Hanro50/MSMC). -Make sure to install it, as it doesn't come by default +In order to authenticate with a Microsoft Account, you would need to use [MSMC](https://npm.im/msmc). +Make sure to install it, as it doesn't come by default. #### Example ```js -import { Authenticator, Client } from 'minecraft-launcher-core'; +import { Client, defineConfig, onLog } from 'minecraft-launcher-core'; import { Auth } from 'msmc'; const authManager = new Auth('select_account'); const xboxManager = await authManager.launch('raw'); // Can be 'electron' or 'nwjs' const token = await xboxManager.getMinecraft(); -const launcher = new Client(); -const options = { - authorization: token.mclc(), - root: './minecraft', - version: { - number: '1.14.4', - type: 'release', - }, - memory: { - max: '4G', - min: '2G', - }, -}; +defineConfig({ + authorization: token.mclc() +}); -launcher.launch(options); +await Client.install(); +await Client.launch(); -launcher.on('debug', (e) => console.log(e)); -launcher.on('data', (e) => console.log(e)); +onLog('debug', (e) => console.log(e)); +onLog('data', (e) => console.log(e)); ``` -### Having modded version - - - -MCLC by default only has Vanilla. In order to automate the process of installing [Forge](https://minecraftforge.net), [Fabric](https://fabricmc.net) and [Quilt](https://quiltmc.org) you would need to use lorem ipsum - -### Documentation - -#### Client Functions - - - -| Function | Type | Description | -| -------- | ------- | ------------------------------------------------------------------------------------------ | -| `launch` | Promise | Launches the client with the specified `options` as a parameter. Returns child the process | - -##### launch +### Modded versions - +MCLC only supports installing Vanilla automatically. In order to automate the process of installing [Forge](https://minecraftforge.net), [Fabric](https://fabricmc.net), [Quilt](https://quiltmc.org) and [NeoForge](https://neoforged.net) you would need to install [tomate-loaders](https://npm.im/tomate-loaders). -| Parameter | Type | Description | Required | -| ------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------- | -------- | -| `options.removePackage` | Boolean | Option to remove the client package zip file after its finished extracting. | False | -| `options.root` | String | Path where you want the launcher to work in. `C:/Users/user/AppData/Roaming/.mc` | True | -| `options.cache` | String | Path where launcher files will be cached in. `C:/Users/user/AppData/Roaming/.mc/cache` | False | -| `options.os` | String | windows, osx or linux. MCLC will auto determine the OS if this field isn't provided. | False | -| `options.customLaunchArgs` | Array | Array of custom Minecraft arguments you want to add. | False | -| `options.customArgs` | Array | Array of custom Java arguments you want to add. | False | -| `options.features` | Array | Array of game argument feature flags. ex: `is_demo_user` or `has_custom_resolution` | False | -| `options.version.number` | String | Minecraft version that is going to be launched. | True | -| `options.version.type` | String | Any string. The actual Minecraft launcher uses `release` and `snapshot`. | True | -| `options.version.custom` | String | The name of the folder, jar file, and version json in the version folder. | False | -| `options.memory.max` | String | Max amount of memory being used by Minecraft. | True | -| `options.memory.min` | String | Min amount of memory being used by Minecraft. | True | -| `options.forge` | String | Path to Forge Jar. (Versions below 1.12.2 should be the "universal" jar while versions above 1.13 should be the "installer" jar) | False | -| `options.javaPath` | String | Path to the JRE executable file, will default to `java` if not entered. | False | -| `options.quickPlay.type` | String | The type of the quickPlay session. `singleplayer`, `multiplayer`, `realms`, `legacy` | False | -| `options.quickPlay.identifier` | String | The folder name, server address, or realm ID, relating to the specified type. `legacy` follows `multiplayer` format. | False | -| `options.quickPlay.path` | String | The specified path for logging (relative to the run directory) | False | -| `options.proxy.host` | String | Host url to the proxy, don't include the port. | False | -| `options.proxy.port` | String | Port of the host proxy, will default to `8080` if not entered. | False | -| `options.proxy.username` | String | Username for the proxy. | False | -| `options.proxy.password` | String | Password for the proxy. | False | -| `options.timeout` | Integer | Timeout on download requests. | False | -| `options.window.width` | String | Width of the Minecraft Client. | False | -| `options.window.height` | String | Height of the Minecraft Client. | False | -| `options.window.fullscreen` | Boolean | Fullscreen the Minecraft Client. | False | -| `options.overrides` | Object | Json object redefining paths for better customization. Example below. | False | +If you wish to not use `tomate-loaders`, MCLC supports installing Forge and NeoForge for you (you would need to install the installer yourself) -#### Authenticator Functions - -##### getAuth - -| Parameter | Type | Description | Required | -| ---------- | ------ | ----------------- | -------- | -| `username` | String | Email or username | True | +#### Example -#### Events +```js +import { Client, defineConfig, onLog, offline } from 'minecraft-launcher-core'; +import { join } from 'path'; -| Event Name | Type | Description | -| ----------------- | ------- | ----------------------------------------------------------------------------------- | -| `arguments` | Object | Emitted when launch arguments are set for the Minecraft Jar. | -| `data` | String | Emitted when information is returned from the Minecraft Process | -| `close` | Integer | Code number that is returned by the Minecraft Process | -| `download` | String | Emitted when a file successfully downloads | -| `download-status` | Object | Emitted when data is received while downloading | -| `debug` | String | Emitted when functions occur, made to help debug if errors occur | -| `progress` | Object | Emitted when files are being downloaded in order. (Assets, Forge, Natives, Classes) | +defineConfig({ + authorization: offline('Steve'), + version: { + number: '1.14.4', + type: 'release', + forge: join('path', 'to', 'forge-installer.jar') + } +}); -#### What should it look like running from console? +await Client.install(); +await Client.launch(); -The `pid` is printed in console after the process is launched. -![gif](https://owo.whats-th.is/3N3PMC4.gif) +onLog('debug', (e) => console.log(e)); +onLog('data', (e) => console.log(e)); +``` ## Contributors These are the people that helped out that aren't listed [here](https://github.com/Pierce01/MinecraftLauncher-core/graphs/contributors)! -- [Pyker](https://github.com/Pyker) - Forge dependency parsing. -- [Khionu](https://github.com/khionu) - Research on how Minecraft's `natives` are handled. -- [Coding-Kiwi](https://github.com/Coding-Kiwi) - Pointed out I didn't pass `clientToken` in initial authentication function. -- maxbsoft - Pointed out that a certain JVM option causes OSX Minecraft to bug out. -- [Noé](https://github.com/NoXeDev) - Pointed out launch args weren't being passed for Forge 1.13+. +- [Pyker](https://github.com/Pyker) - Forge dependency parsing. +- [Khionu](https://github.com/khionu) - Research on how Minecraft's `natives` are handled. +- [Coding-Kiwi](https://github.com/Coding-Kiwi) - Pointed out I didn't pass `clientToken` in initial authentication function. +- maxbsoft - Pointed out that a certain JVM option causes OSX Minecraft to bug out. +- [Noé](https://github.com/NoXeDev) - Pointed out launch args weren't being passed for Forge 1.13+. + +### Related projects + +- [MSMC](https://npm.im/msmc) - Allows using a Microsoft Account for the authorization +- [tomate-loaders](https://npm.im/tomate-loaders) - Downloads mod loaders automatically + + \ No newline at end of file From d4ded9c28f585b963314178984c80ab7703651c6 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 19:42:10 +0300 Subject: [PATCH 67/97] Make use of classes again. Finish configuration --- src/index.ts | 3 +- src/launcher.ts | 286 ++++++++++++++++++++++++----------------------- tests/vanilla.ts | 112 ++++++++++--------- 3 files changed, 206 insertions(+), 195 deletions(-) diff --git a/src/index.ts b/src/index.ts index 0c49e10..61ae45e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,3 @@ -export * as Client from '@/launcher'; +export { Client } from '@/launcher'; export { offline } from '@/authenticator'; -export { config, defineConfig } from '@/utils/config'; export { onLog } from '@/utils/log'; diff --git a/src/launcher.ts b/src/launcher.ts index b06f074..3eefb80 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -18,159 +18,167 @@ import mclc from '@/mclc'; import { cleanUp, getOS } from '@/utils'; import { config, defineConfig } from '@/utils/config'; import { log } from '@/utils/log'; +import { Options } from './types'; -export const launch = () => { - throw Error( - 'This function is no longer used. In order to install Minecraft, use the install function. To start Minecraft, use the start function', - ); -}; - -export const install = async () => { - log('version', `MCLC version ${mclc}`); - - if (!existsSync(config.root)) { - log('debug', 'Attempting to create root folder'); - mkdirSync(config.root); +export class Client { + constructor(config: Options) { + defineConfig(config); } - if (config.gameDirectory) { - defineConfig({ gameDirectory: resolve(config.gameDirectory) }); - if (!existsSync(config.gameDirectory)) mkdirSync(config.gameDirectory, { recursive: true }); + launch() { + throw Error( + 'This function is no longer used. In order to install Minecraft, use the install function. To start Minecraft, use the start function', + ); } - await getVersion(); - const mcPath = - config.minecraftJar || - (config.version.custom - ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) - : join(config.directory, `${config.version.number}.jar`)); - await getNatives(); - - if (!existsSync(mcPath)) { - log('debug', 'Attempting to download Minecraft version jar'); - await getJar(); - } + async install() { + log('version', `MCLC version ${mclc}`); - let modifyJson = null; - if (config.version.custom) { - log('debug', 'Detected custom in options, setting custom version file'); - modifyJson = JSON.parse( - readFileSync(join(config.root, 'versions', config.version.custom, `${config.version.custom}.json`), { - encoding: 'utf8', - }), - ); - } + if (!existsSync(config.root)) { + log('debug', 'Attempting to create root folder'); + mkdirSync(config.root); + } - cleanUp(await getClasses(modifyJson)); + if (config.gameDirectory) { + defineConfig({ gameDirectory: resolve(config.gameDirectory) }); + if (!existsSync(config.gameDirectory)) mkdirSync(config.gameDirectory, { recursive: true }); + } - log('debug', 'Attempting to download assets'); - await getAssets(); + await getVersion(); + const mcPath = + config.minecraftJar || + (config.version.custom + ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) + : join(config.directory, `${config.version.number}.jar`)); + await getNatives(); + + if (!existsSync(mcPath)) { + log('debug', 'Attempting to download Minecraft version jar'); + await getJar(); + } - log('debug', `Successfully installed Minecraft ${config.version.number}`); - return; -}; + let modifyJson = null; + if (config.version.custom) { + log('debug', 'Detected custom in options, setting custom version file'); + modifyJson = JSON.parse( + readFileSync(join(config.root, 'versions', config.version.custom, `${config.version.custom}.json`), { + encoding: 'utf8', + }), + ); + } -export const start = async () => { - log('version', `MCLC version ${mclc}`); + cleanUp(await getClasses(modifyJson)); - const java = await checkJava(config.javaPath || 'java'); - if (!java || !java.run) { - log('debug', `Couldn't start Minecraft due to: ${java.message}`); - return log('close', 1); - } + log('debug', 'Attempting to download assets'); + await getAssets(); - const versionFile = await getVersion(); - const mcPath = - config.minecraftJar || - (config.version.custom - ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) - : join(config.directory, `${config.version.number}.jar`)); - const nativePath = await getNatives(); - - const args: string[] = []; - - let modifyJson = null; - if (config.version.custom) { - log('debug', 'Detected custom in options, setting custom version file'); - modifyJson = JSON.parse( - readFileSync(join(config.root, 'versions', config.version.custom, `${config.version.custom}.json`), { - encoding: 'utf8', - }), - ); - } else if (config.forge) { - defineConfig({ forge: resolve(config.forge) }); - log('debug', 'Detected Forge in options, getting dependencies'); - modifyJson = await getForgedWrapped(); + log('debug', `Successfully installed Minecraft ${config.version.number}`); + return; } - const jvm = [ - '-XX:-UseAdaptiveSizePolicy', - '-XX:-OmitStackTraceInFastThrow', - '-Dfml.ignorePatchDiscrepancies=true', - '-Dfml.ignoreInvalidMinecraftCertificates=true', - `-Djava.library.path=${resolve(nativePath)}`, - `-Xmx${getMemory()[0]}`, - `-Xms${getMemory()[1]}`, - ]; - if (getOS() === 'osx') { - if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await getJVM()); - } else jvm.push(await getJVM()); - - if (config.customArgs) jvm.concat(config.customArgs); - if (config.logj4ConfigurationFile) jvm.push(`-Dlog4j.configurationFile=${resolve(config.logj4ConfigurationFile)}`); - // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition - if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) - jvm.push('-Dlog4j2.formatMsgNoLookups=true'); - if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); - if (parseInt(versionFile.id.split('.')[1]) < 17) { - if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { - const configPath = resolve(config.root); - const intVersion = parseInt(versionFile.id.split('.')[1]); - if (intVersion >= 12) { - await downloadAsync( - 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', - configPath, - 'log4j2_112-116.xml', - true, - 'log4j', - ); - jvm.push(`-Dlog4j.configurationFile=${resolve(join(configPath, 'log4j2_112-116.xml'))}`); - } else if (intVersion >= 7) { - await downloadAsync( - 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', - configPath, - 'log4j2_17-111.xml', - true, - 'log4j', - ); - jvm.push(`-Dlog4j.configurationFile=${resolve(join(configPath, 'log4j2_17-111.xml'))}`); + async start() { + log('version', `MCLC version ${mclc}`); + + const java = await checkJava(config.javaPath || 'java'); + if (!java || !java.run) { + log('debug', `Couldn't start Minecraft due to: ${java.message}`); + return log('close', 1); + } + + const versionFile = await getVersion(); + const mcPath = + config.minecraftJar || + (config.version.custom + ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) + : join(config.directory, `${config.version.number}.jar`)); + const nativePath = await getNatives(); + + const args: string[] = []; + + let modifyJson = null; + if (config.version.custom) { + log('debug', 'Detected custom in options, setting custom version file'); + modifyJson = JSON.parse( + readFileSync(join(config.root, 'versions', config.version.custom, `${config.version.custom}.json`), { + encoding: 'utf8', + }), + ); + } else if (config.forge) { + defineConfig({ forge: resolve(config.forge) }); + log('debug', 'Detected Forge in options, getting dependencies'); + modifyJson = await getForgedWrapped(); + } + + const jvm = [ + '-XX:-UseAdaptiveSizePolicy', + '-XX:-OmitStackTraceInFastThrow', + '-Dfml.ignorePatchDiscrepancies=true', + '-Dfml.ignoreInvalidMinecraftCertificates=true', + `-Djava.library.path=${resolve(nativePath)}`, + `-Xmx${getMemory()[0]}`, + `-Xms${getMemory()[1]}`, + ]; + if (getOS() === 'osx') { + if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await getJVM()); + } else jvm.push(await getJVM()); + + if (config.customArgs) jvm.concat(config.customArgs); + if (config.logj4ConfigurationFile) + jvm.push(`-Dlog4j.configurationFile=${resolve(config.logj4ConfigurationFile)}`); + // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition + if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) + jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); + if (parseInt(versionFile.id.split('.')[1]) < 17) { + if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { + const configPath = resolve(config.root); + const intVersion = parseInt(versionFile.id.split('.')[1]); + if (intVersion >= 12) { + await downloadAsync( + 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', + configPath, + 'log4j2_112-116.xml', + true, + 'log4j', + ); + jvm.push(`-Dlog4j.configurationFile=${resolve(join(configPath, 'log4j2_112-116.xml'))}`); + } else if (intVersion >= 7) { + await downloadAsync( + 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', + configPath, + 'log4j2_17-111.xml', + true, + 'log4j', + ); + jvm.push(`-Dlog4j.configurationFile=${resolve(join(configPath, 'log4j2_17-111.xml'))}`); + } } } - } - const classes = config.classes || cleanUp(await getClasses(modifyJson)); - const classPaths = ['-cp']; - const separator = getOS() === 'windows' ? ';' : ':'; - log('debug', `Using ${separator} to separate class paths`); - // Handling launch arguments. - const file = modifyJson || versionFile; - // So mods like fabric work. - const jar = existsSync(mcPath) - ? `${separator}${resolve(mcPath)}` - : `${separator}${resolve(join(config.directory, `${config.version.number}.jar`))}`; - classPaths.push(`${config.forge ? `${config.forge}${separator}` : ''}${classes.join(separator)}${jar}`); - classPaths.push(file.mainClass); - - const launchconfig = await getLaunchOptions(modifyJson); - const launchArguments = args.concat(jvm, classPaths, launchconfig); - log('arguments', launchArguments); - log('debug', `Launching with arguments ${launchArguments.join(' ')}`); - - const minecraft = spawn(config.javaPath ?? 'java', launchArguments, { - detached: config.detached, - }); - minecraft.stdout.on('data', (data) => log('data', data.toString('utf-8'))); - minecraft.stderr.on('data', (data) => log('data', data.toString('utf-8'))); - minecraft.on('close', (code) => code && log('close', code)); - return minecraft; -}; + const classes = config.classes || cleanUp(await getClasses(modifyJson)); + const classPaths = ['-cp']; + const separator = getOS() === 'windows' ? ';' : ':'; + log('debug', `Using ${separator} to separate class paths`); + // Handling launch arguments. + const file = modifyJson || versionFile; + // So mods like fabric work. + const jar = existsSync(mcPath) + ? `${separator}${resolve(mcPath)}` + : `${separator}${resolve(join(config.directory, `${config.version.number}.jar`))}`; + classPaths.push(`${config.forge ? `${config.forge}${separator}` : ''}${classes.join(separator)}${jar}`); + classPaths.push(file.mainClass); + + const launchconfig = await getLaunchOptions(modifyJson); + const launchArguments = args.concat(jvm, classPaths, launchconfig); + log('arguments', launchArguments); + log('debug', `Launching with arguments ${launchArguments.join(' ')}`); + + const minecraft = spawn(config.javaPath ?? 'java', launchArguments, { + detached: config.detached, + }); + minecraft.stdout.on('data', (data) => log('data', data.toString('utf-8'))); + minecraft.stderr.on('data', (data) => log('data', data.toString('utf-8'))); + minecraft.on('close', (code) => code && log('close', code)); + return minecraft; + } +} diff --git a/tests/vanilla.ts b/tests/vanilla.ts index 7613d36..7455b67 100644 --- a/tests/vanilla.ts +++ b/tests/vanilla.ts @@ -1,26 +1,22 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process'; import { existsSync, rmdirSync } from 'node:fs'; import { resolve } from 'node:path'; -import { afterAll, beforeAll, describe, expect, test } from 'vitest'; -import { Client, defineConfig } from '../src'; +import { afterAll, describe, expect, test } from 'vitest'; +import { Client } from '../src'; describe('Minecraft Vanilla Legacy (1.8.9)', () => { - beforeAll(() => { - defineConfig({ - version: { - number: '1.8.9', - type: 'release', - }, - }); - }); - test( 'Installation', async () => { - await Client.install(); - expect(existsSync(resolve('./minecraft/cache/json/1.8.9.json'))).toBe(true); + await new Client({ + version: { + number: '1.8.9', + type: 'release', + }, + }).install(); expect(existsSync(resolve('./minecraft/natives/1.8.9'))).toBe(true); expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.jar'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.json'))).toBe(true); }, 3 * 60 * 1000, ); @@ -28,7 +24,12 @@ describe('Minecraft Vanilla Legacy (1.8.9)', () => { test( 'Starting', async () => { - const process = await Client.start(); + const process = await new Client({ + version: { + number: '1.8.9', + type: 'release', + }, + }).start(); expect(process && typeof process.kill === 'function').toBe(true); await new Promise((resolve) => { setTimeout(() => { @@ -49,45 +50,48 @@ describe('Minecraft Vanilla Legacy (1.8.9)', () => { }); }); -// describe('Minecraft Vanilla Modern (1.14.4)', () => { -// defineOptions({ -// version: { -// number: '1.14.4', -// type: 'release', -// }, -// }); - -// test( -// 'Installation', -// async () => { -// await Client.install(); -// expect(existsSync(resolve('./minecraft/cache/json/1.14.4.json'))).toBe(true); -// expect(existsSync(resolve('./minecraft/natives/1.14.4'))).toBe(true); -// expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.jar'))).toBe(true); -// }, -// 3 * 60 * 1000, -// ); +describe('Minecraft Vanilla Modern (1.14.4)', () => { + test( + 'Installation', + async () => { + await new Client({ + version: { + number: '1.14.4', + type: 'release', + }, + }).install(); + expect(existsSync(resolve('./minecraft/natives/1.14.4'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.jar'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.json'))).toBe(true); + }, + 3 * 60 * 1000, + ); -// test( -// 'Starting', -// async () => { -// const process = await Client.start(); -// expect(process && typeof process.kill === 'function').toBe(true); -// await new Promise((resolve) => { -// setTimeout(() => { -// (process as ChildProcessWithoutNullStreams).kill(); -// resolve(); -// }, 20 * 1000); -// }); -// expect(existsSync(resolve('./minecraft/saves'))).toBe(true); -// expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); -// }, -// 3 * 60 * 1000, -// ); + test( + 'Starting', + async () => { + const process = await new Client({ + version: { + number: '1.14.4', + type: 'release', + }, + }).start(); + expect(process && typeof process.kill === 'function').toBe(true); + await new Promise((resolve) => { + setTimeout(() => { + (process as ChildProcessWithoutNullStreams).kill(); + resolve(); + }, 10 * 1000); + }); + expect(existsSync(resolve('./minecraft/saves'))).toBe(true); + expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); + }, + 3 * 60 * 1000, + ); -// // Cleanup for other tests -// afterAll(() => { -// rmdirSync(resolve('./minecraft/saves')); -// rmdirSync(resolve('./minecraft/resourcepacks')); -// }); -// }); + // Cleanup for other tests + afterAll(() => { + rmdirSync(resolve('./minecraft/saves')); + rmdirSync(resolve('./minecraft/resourcepacks')); + }); +}); From 0cd50ad9bab9a8dba75a31724c26fb34fcf48be3 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 19:55:01 +0300 Subject: [PATCH 68/97] Adapt README to the latest commit --- README.md | 35 ++++++++++++++++------------------- {imgs => assets}/header.png | Bin 2 files changed, 16 insertions(+), 19 deletions(-) rename {imgs => assets}/header.png (100%) diff --git a/README.md b/README.md index 8987b11..9bb81da 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![MCLC](/imgs/header.png) +![MCLC](/assets/header.png) [![MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![Version](https://img.shields.io/badge/stable_version-3.19.0-blue) @@ -28,9 +28,9 @@ pnpm add minecraft-launcher-core ### Example ```js -import { Client, defineConfig, onLog, offline } from 'minecraft-launcher-core'; +import { Client, onLog, offline } from 'minecraft-launcher-core'; -defineConfig({ +const client = new Client({ // This will launch in offline mode, if you want to use // a Microsoft Account, see details below authorization: offline('Steve'), @@ -41,8 +41,8 @@ defineConfig({ } }); -await Client.install(); -await Client.launch(); +await client.install(); +await client.launch(); onLog('debug', (e) => console.log(e)); onLog('data', (e) => console.log(e)); @@ -56,19 +56,19 @@ Make sure to install it, as it doesn't come by default. #### Example ```js -import { Client, defineConfig, onLog } from 'minecraft-launcher-core'; +import { Client, onLog } from 'minecraft-launcher-core'; import { Auth } from 'msmc'; const authManager = new Auth('select_account'); const xboxManager = await authManager.launch('raw'); // Can be 'electron' or 'nwjs' const token = await xboxManager.getMinecraft(); -defineConfig({ +const client = new Client({ authorization: token.mclc() }); -await Client.install(); -await Client.launch(); +await client.install(); +await client.launch(); onLog('debug', (e) => console.log(e)); onLog('data', (e) => console.log(e)); @@ -76,17 +76,16 @@ onLog('data', (e) => console.log(e)); ### Modded versions -MCLC only supports installing Vanilla automatically. In order to automate the process of installing [Forge](https://minecraftforge.net), [Fabric](https://fabricmc.net), [Quilt](https://quiltmc.org) and [NeoForge](https://neoforged.net) you would need to install [tomate-loaders](https://npm.im/tomate-loaders). - -If you wish to not use `tomate-loaders`, MCLC supports installing Forge and NeoForge for you (you would need to install the installer yourself) +MCLC only supports installing Vanilla automatically, but it also +supports installing Forge and NeoForge for you (you would need to install the installer yourself) #### Example ```js -import { Client, defineConfig, onLog, offline } from 'minecraft-launcher-core'; +import { Client, onLog, offline } from 'minecraft-launcher-core'; import { join } from 'path'; -defineConfig({ +const client = new Client({ authorization: offline('Steve'), version: { number: '1.14.4', @@ -95,8 +94,8 @@ defineConfig({ } }); -await Client.install(); -await Client.launch(); +await client.install(); +await client.launch(); onLog('debug', (e) => console.log(e)); onLog('data', (e) => console.log(e)); @@ -115,6 +114,4 @@ These are the people that helped out that aren't listed [here](https://github.co ### Related projects - [MSMC](https://npm.im/msmc) - Allows using a Microsoft Account for the authorization -- [tomate-loaders](https://npm.im/tomate-loaders) - Downloads mod loaders automatically - - \ No newline at end of file +- [tomate-loaders](https://npm.im/tomate-loaders) - Downloads mod loaders automatically \ No newline at end of file diff --git a/imgs/header.png b/assets/header.png similarity index 100% rename from imgs/header.png rename to assets/header.png From 56dfa206b375d3e82715c72512b6c04b4445af1d Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:10:21 +0300 Subject: [PATCH 69/97] [WIP] Create a workflow --- .github/workflows/tests.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/tests.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..b3ac1ba --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,25 @@ +name: Vitest & Prettier + +on: [push, pull_request] + +jobs: + setup: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "14.x" + - run: yarn install --frozen-lockfile + + vitest: + needs: setup + runs-on: ubuntu-latest + steps: + - run: yarn test + + prettier: + needs: setup + runs-on: ubuntu-latest + steps: + - run: yarn prettier From a77c7a121a4e031b570453b5b5b77703428cd1e0 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:16:20 +0300 Subject: [PATCH 70/97] Formatting --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 9bb81da..36b0657 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ pnpm add minecraft-launcher-core ### Example ```js -import { Client, onLog, offline } from 'minecraft-launcher-core'; +import { Client, offline, onLog } from 'minecraft-launcher-core'; const client = new Client({ // This will launch in offline mode, if you want to use @@ -38,7 +38,7 @@ const client = new Client({ version: { number: '1.14.4', type: 'release', - } + }, }); await client.install(); @@ -64,7 +64,7 @@ const xboxManager = await authManager.launch('raw'); // Can be 'electron' or 'nw const token = await xboxManager.getMinecraft(); const client = new Client({ - authorization: token.mclc() + authorization: token.mclc(), }); await client.install(); @@ -82,16 +82,16 @@ supports installing Forge and NeoForge for you (you would need to install the in #### Example ```js -import { Client, onLog, offline } from 'minecraft-launcher-core'; import { join } from 'path'; +import { Client, offline, onLog } from 'minecraft-launcher-core'; const client = new Client({ authorization: offline('Steve'), version: { number: '1.14.4', type: 'release', - forge: join('path', 'to', 'forge-installer.jar') - } + forge: join('path', 'to', 'forge-installer.jar'), + }, }); await client.install(); @@ -105,13 +105,13 @@ onLog('data', (e) => console.log(e)); These are the people that helped out that aren't listed [here](https://github.com/Pierce01/MinecraftLauncher-core/graphs/contributors)! -- [Pyker](https://github.com/Pyker) - Forge dependency parsing. -- [Khionu](https://github.com/khionu) - Research on how Minecraft's `natives` are handled. -- [Coding-Kiwi](https://github.com/Coding-Kiwi) - Pointed out I didn't pass `clientToken` in initial authentication function. -- maxbsoft - Pointed out that a certain JVM option causes OSX Minecraft to bug out. -- [Noé](https://github.com/NoXeDev) - Pointed out launch args weren't being passed for Forge 1.13+. +- [Pyker](https://github.com/Pyker) - Forge dependency parsing. +- [Khionu](https://github.com/khionu) - Research on how Minecraft's `natives` are handled. +- [Coding-Kiwi](https://github.com/Coding-Kiwi) - Pointed out I didn't pass `clientToken` in initial authentication function. +- maxbsoft - Pointed out that a certain JVM option causes OSX Minecraft to bug out. +- [Noé](https://github.com/NoXeDev) - Pointed out launch args weren't being passed for Forge 1.13+. ### Related projects -- [MSMC](https://npm.im/msmc) - Allows using a Microsoft Account for the authorization -- [tomate-loaders](https://npm.im/tomate-loaders) - Downloads mod loaders automatically \ No newline at end of file +- [MSMC](https://npm.im/msmc) - Allows using a Microsoft Account for the authorization +- [tomate-loaders](https://npm.im/tomate-loaders) - Downloads mod loaders automatically From d26fcbef2004fd274b5b7e8afe1a26ae9b9d0319 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:17:25 +0300 Subject: [PATCH 71/97] Bump workflow's NodeJS version to v18 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b3ac1ba..ff34cac 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: "14.x" + node-version: "16.x" - run: yarn install --frozen-lockfile vitest: From 3f566797832f9aacda90a62192cee959b21dc379 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:18:07 +0300 Subject: [PATCH 72/97] Bump NodeJS from v16 to v18 --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index ff34cac..a4ca44f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: "16.x" + node-version: "18.x" - run: yarn install --frozen-lockfile vitest: From 5f78c09c12c4b205305a4f34422792cb1e05bcb9 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:20:40 +0300 Subject: [PATCH 73/97] Move workflow runner into the repository's folder --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a4ca44f..cd3d186 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,7 +10,9 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" - - run: yarn install --frozen-lockfile + - run: | + cd minecraft-utils-pierce/minecraft-utils-pierce + yarn install --frozen-lockfile vitest: needs: setup From 3b10c39412d252083b51c1d4c2f71f8e8c2c4771 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:24:35 +0300 Subject: [PATCH 74/97] Fix workflows --- .github/workflows/tests.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cd3d186..6b2bebe 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,18 +10,20 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" - - run: | - cd minecraft-utils-pierce/minecraft-utils-pierce - yarn install --frozen-lockfile + - run: yarn install --frozen-lockfile vitest: needs: setup runs-on: ubuntu-latest steps: - - run: yarn test + - run: | + cd minecraft-utils-pierce/minecraft-utils-pierce + yarn test prettier: needs: setup runs-on: ubuntu-latest steps: - - run: yarn prettier + - run: | + cd minecraft-utils-pierce/minecraft-utils-pierce + yarn prettier From 852e6c655300908e90d2d3431df681ec1fdc4db0 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:26:11 +0300 Subject: [PATCH 75/97] Update tests.yml --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6b2bebe..b42e13e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - run: | - cd minecraft-utils-pierce/minecraft-utils-pierce + cd minecraft-utils-pierce yarn test prettier: @@ -25,5 +25,5 @@ jobs: runs-on: ubuntu-latest steps: - run: | - cd minecraft-utils-pierce/minecraft-utils-pierce + cd minecraft-utils-pierce yarn prettier From 28abaf48923a91426034eb176a393ad369c3c37d Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:46:36 +0300 Subject: [PATCH 76/97] Fully fix workflows (looks cluttered, need help) --- .github/workflows/tests.yml | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b42e13e..09cba90 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -3,27 +3,24 @@ name: Vitest & Prettier on: [push, pull_request] jobs: - setup: + vitest: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "18.x" - - run: yarn install --frozen-lockfile - - vitest: - needs: setup - runs-on: ubuntu-latest - steps: - run: | - cd minecraft-utils-pierce + yarn install --frozen-lockfile yarn test prettier: - needs: setup runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "18.x" - run: | - cd minecraft-utils-pierce + yarn install --frozen-lockfile yarn prettier From 1a8c3a063292bab16a363d0bdc3a7fb2f4d4df14 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:50:33 +0300 Subject: [PATCH 77/97] Setup Java --- .github/workflows/tests.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 09cba90..a251bd9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -21,6 +21,10 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" + - uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: "8" - run: | yarn install --frozen-lockfile yarn prettier From 3a2017b70c19a9697af9b575fc55609258b314e8 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:53:07 +0300 Subject: [PATCH 78/97] Testing --- .github/workflows/tests.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a251bd9..17729ca 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,9 +10,8 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" - - run: | - yarn install --frozen-lockfile - yarn test + # - run: yarn install --frozen-lockfile + # - run: yarn test prettier: runs-on: ubuntu-latest @@ -25,6 +24,6 @@ jobs: with: distribution: "temurin" java-version: "8" - - run: | - yarn install --frozen-lockfile - yarn prettier + - run: java -v + # - run: yarn install --frozen-lockfile + # - run: yarn prettier From bb0e72d260d4e1230f7a408e43065c89578d514a Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 20:54:47 +0300 Subject: [PATCH 79/97] Fix workflows for the last time --- .github/workflows/tests.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 17729ca..1919995 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,8 +10,12 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" - # - run: yarn install --frozen-lockfile - # - run: yarn test + - uses: actions/setup-java@v4 + with: + distribution: "temurin" + java-version: "8" + - run: yarn install --frozen-lockfile + - run: yarn test prettier: runs-on: ubuntu-latest @@ -20,10 +24,5 @@ jobs: - uses: actions/setup-node@v4 with: node-version: "18.x" - - uses: actions/setup-java@v4 - with: - distribution: "temurin" - java-version: "8" - - run: java -v - # - run: yarn install --frozen-lockfile - # - run: yarn prettier + - run: yarn install --frozen-lockfile + - run: yarn prettier From 04a024c8a3616435341ef290993a11442808d757 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Mon, 22 Apr 2024 21:09:55 +0300 Subject: [PATCH 80/97] Add workflow badge to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 36b0657..9a964e4 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![Version](https://img.shields.io/badge/stable_version-3.19.0-blue) +![Workflow](https://github.com/Pierce01/MinecraftLauncher-core/actions/workflows/tests.yml/badge.svg) MCLC (Minecraft Launcher Core) is a NodeJS solution for launching modded and vanilla Minecraft without having to download and format everything yourself. Basically a core for your Electron or script based launcher. From b62558d8bc80d65eaf29322fd0ee39ea5990dfad Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 22:08:23 +0300 Subject: [PATCH 81/97] Rewrite handler to a class (+fixing config) --- src/handler.ts | 1165 +++++++++++++++++++++--------------------- src/launcher.ts | 173 ++++--- src/types/Options.ts | 4 + src/utils/config.ts | 30 -- src/utils/index.ts | 5 +- tests/vanilla.ts | 42 +- 6 files changed, 724 insertions(+), 695 deletions(-) delete mode 100644 src/utils/config.ts diff --git a/src/handler.ts b/src/handler.ts index 039f5c9..9afe5dc 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -12,182 +12,163 @@ import { import { Agent as http } from 'node:http'; import { Agent as https } from 'node:https'; import { join, resolve, sep } from 'node:path'; -import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Rule, Version } from '@/types'; +import { ArtifactType, CustomArtifactType, CustomLibType, Fields, LibType, Options, Rule, Version } from '@/types'; import { checkSum, cleanUp, getOS, isLegacy, popString } from '@/utils'; -import { config } from '@/utils/config'; import Counter from '@/utils/Counter'; import { log } from '@/utils/log'; import Zip from 'adm-zip'; import axios from 'axios'; -const counter = new Counter(); -let parsedVersion: Version; +class Handler { + config: Options; + counter: Counter; + parsedVersion!: Version; -const checkJava = (java: string): Promise<{ run: boolean; message?: ExecException }> => - new Promise((resolve) => { - exec(`"${java}" -version`, (error, _, stderr) => { - if (error) - return resolve({ - run: false, - message: error, - }); + constructor(config: Options) { + this.config = config; + this.counter = new Counter(); + this.parsedVersion; + } - log( - 'debug', - `Using Java version ${stderr.match(/"(.*?)"/)?.pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`, - ); - resolve({ run: true }); + checkJava(java: string): Promise<{ run: boolean; message?: ExecException }> { + return new Promise((resolve) => { + exec(`"${java}" -version`, (error, _, stderr) => { + if (error) + return resolve({ + run: false, + message: error, + }); + + log( + 'debug', + `Using Java version ${stderr.match(/"(.*?)"/)?.pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`, + ); + resolve({ run: true }); + }); }); - }); + } -const downloadAsync = async (url: string, directory: string, name: string, retry: boolean, type: string) => { - try { - mkdirSync(directory, { recursive: true }); + async downloadAsync(url: string, directory: string, name: string, retry: boolean, type: string) { + try { + mkdirSync(directory, { recursive: true }); - const response = await axios.get(url, { - responseType: 'stream', - timeout: config.timeout || 50000, - httpAgent: new http({ maxSockets: config.maxSockets || Infinity }), - httpsAgent: new https({ maxSockets: config.maxSockets || Infinity }), - }); + const response = await axios.get(url, { + responseType: 'stream', + timeout: this.config.timeout || 50000, + httpAgent: new http({ maxSockets: this.config.maxSockets || Infinity }), + httpsAgent: new https({ maxSockets: this.config.maxSockets || Infinity }), + }); - const totalBytes = parseInt(response.headers['content-length']); - let receivedBytes = 0; + const totalBytes = parseInt(response.headers['content-length']); + let receivedBytes = 0; - response.data.on('data', (data: Buffer | string) => { - typeof data === 'string' ? (receivedBytes += Buffer.byteLength(data)) : (receivedBytes += data.length); + response.data.on('data', (data: Buffer | string) => { + typeof data === 'string' ? (receivedBytes += Buffer.byteLength(data)) : (receivedBytes += data.length); - log('download-status', { - name: name, - type: type, - current: receivedBytes, - total: totalBytes, + log('download-status', { + name: name, + type: type, + current: receivedBytes, + total: totalBytes, + }); }); - }); - - const file = createWriteStream(join(directory, name)); - response.data.pipe(file); - await new Promise((resolve) => { - file.on('finish', resolve); - file.on('error', async (e) => { - log('debug', `Failed to download asset to ${join(directory, name)} due to\n${e}. Retrying... ${retry}`); - if (existsSync(join(directory, name))) unlinkSync(join(directory, name)); - if (retry) await downloadAsync(url, directory, name, false, type); - return resolve(e); + const file = createWriteStream(join(directory, name)); + response.data.pipe(file); + + await new Promise((resolve) => { + file.on('finish', resolve); + file.on('error', async (e) => { + log( + 'debug', + `Failed to download asset to ${join(directory, name)} due to\n${e}. Retrying... ${retry}`, + ); + if (existsSync(join(directory, name))) unlinkSync(join(directory, name)); + if (retry) await this.downloadAsync(url, directory, name, false, type); + return resolve(e); + }); }); - }); - log('download', name); - return { - failed: false, - asset: null, - }; - } catch (error) { - log('debug', `Failed to download asset to ${join(directory, name)} due\n${error}. Retrying... ${retry}`); - if (retry) await downloadAsync(url, directory, name, false, type); - return; + log('download', name); + return { + failed: false, + asset: null, + }; + } catch (error) { + log('debug', `Failed to download asset to ${join(directory, name)} due\n${error}. Retrying... ${retry}`); + if (retry) await this.downloadAsync(url, directory, name, false, type); + return; + } } -}; -const getVersion = async () => { - const versionJsonPath = config.versionJson || join(config.directory, `${config.version.number}.json`); - if (existsSync(versionJsonPath)) { - parsedVersion = JSON.parse(readFileSync(versionJsonPath).toString()); - return parsedVersion; - } + async getVersion() { + const versionJsonPath = + this.config.versionJson || join(this.config.directory, `${this.config.version.number}.json`); + if (existsSync(versionJsonPath)) { + this.parsedVersion = JSON.parse(readFileSync(versionJsonPath).toString()); + return this.parsedVersion; + } - const manifest = `${config.url.meta}/mc/game/version_manifest.json`; - const cache = config.cache ? `${config.cache}/json` : `${config.root}/cache/json`; - const { data } = await axios.get(manifest); + const manifest = `${this.config.url.meta}/mc/game/version_manifest.json`; + const cache = this.config.cache ? `${this.config.cache}/json` : `${this.config.root}/cache/json`; + const { data } = await axios.get(manifest); - if (!existsSync(cache)) { - mkdirSync(cache, { recursive: true }); - log('debug', 'Cache directory created.'); - } + if (!existsSync(cache)) { + mkdirSync(cache, { recursive: true }); + log('debug', 'Cache directory created.'); + } - writeFileSync(join(cache, 'version_manifest.json'), JSON.stringify(data)); - log('debug', 'Cached version_manifest.json'); + writeFileSync(join(cache, 'version_manifest.json'), JSON.stringify(data)); + log('debug', 'Cached version_manifest.json'); - const desiredVersion = data.versions.find((version: { id: string }) => version.id === config.version.number); - if (desiredVersion) { - const { data } = await axios.get(desiredVersion.url); + const desiredVersion = data.versions.find( + (version: { id: string }) => version.id === this.config.version.number, + ); + if (desiredVersion) { + const { data } = await axios.get(desiredVersion.url); - log('debug', 'Parsed version from version manifest'); - parsedVersion = data; - return parsedVersion; - } else { - throw Error(`Failed to find version ${config.version.number} in version_manifest.json`); + log('debug', 'Parsed version from version manifest'); + this.parsedVersion = data; + return this.parsedVersion; + } else { + throw Error(`Failed to find version ${this.config.version.number} in version_manifest.json`); + } } -}; - -const getJar = async () => { - await downloadAsync( - parsedVersion.downloads.client.url, - config.directory, - `${config.version.custom ?? config.version.number}.jar`, - true, - 'version-jar', - ); - writeFileSync(join(config.directory, `${config.version.number}.json`), JSON.stringify(parsedVersion, null, 4)); - return log('debug', 'Downloaded version jar and wrote version json'); -}; - -const getAssets = async () => { - const assetDirectory = resolve(config.assetRoot || join(config.root, 'assets')); - const assetId = config.version.custom || config.version.number; - - if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) - await downloadAsync( - parsedVersion.assetIndex.url, - join(assetDirectory, 'indexes'), - `${assetId}.json`, + + async getJar() { + await this.downloadAsync( + this.parsedVersion.downloads.client.url, + this.config.directory, + `${this.config.version.custom ?? this.config.version.number}.jar`, true, - 'asset-json', + 'version-jar', ); + writeFileSync( + join(this.config.directory, `${this.config.version.number}.json`), + JSON.stringify(this.parsedVersion, null, 4), + ); + return log('debug', 'Downloaded version jar and wrote version json'); + } - const index = JSON.parse(readFileSync(join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' })); - - log('progress', { - type: 'assets', - task: 0, - total: Object.keys(index.objects).length, - }); - - await Promise.all( - Object.keys(index.objects).map(async (asset) => { - const hash = index.objects[asset].hash; - const subhash = hash.substring(0, 2); - const subAsset = join(assetDirectory, 'objects', subhash); - - if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) - await downloadAsync(`${config.url.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets'); - counter.increment(); - log('progress', { - type: 'assets', - task: counter.getValue(), - total: Object.keys(index.objects).length, - }); - }), - ); - counter.reset(); - - // Copy assets to legacy if it's an older Minecraft version. - if (isLegacy(parsedVersion)) { - if (existsSync(join(assetDirectory, 'legacy'))) { - log( - 'debug', - "The 'legacy' directory is no longer used as Minecraft looks " + - "for the resouces folder regardless of what is passed in the assetDirecotry launch option. I'd " + - `recommend removing the directory (${join(assetDirectory, 'legacy')})`, + async getAssets() { + const assetDirectory = resolve(this.config.assetRoot || join(this.config.root, 'assets')); + const assetId = this.config.version.custom || this.config.version.number; + + if (!existsSync(join(assetDirectory, 'indexes', `${assetId}.json`))) + await this.downloadAsync( + this.parsedVersion.assetIndex.url, + join(assetDirectory, 'indexes'), + `${assetId}.json`, + true, + 'asset-json', ); - } - const legacyDirectory = join(config.root, 'resources'); - log('debug', `Copying assets over to ${legacyDirectory}`); + const index = JSON.parse( + readFileSync(join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' }), + ); log('progress', { - type: 'assets-copy', + type: 'assets', task: 0, total: Object.keys(index.objects).length, }); @@ -198,488 +179,534 @@ const getAssets = async () => { const subhash = hash.substring(0, 2); const subAsset = join(assetDirectory, 'objects', subhash); - const legacyAsset = asset.split('/'); - legacyAsset.pop(); - - if (!existsSync(join(legacyDirectory, legacyAsset.join('/')))) { - mkdirSync(join(legacyDirectory, legacyAsset.join('/')), { recursive: true }); - } - - if (!existsSync(join(legacyDirectory, asset))) { - copyFileSync(join(subAsset, hash), join(legacyDirectory, asset)); - } - counter.increment(); + if (!existsSync(join(subAsset, hash)) || !(await checkSum(hash, join(subAsset, hash)))) + await this.downloadAsync( + `${this.config.url.resource}/${subhash}/${hash}`, + subAsset, + hash, + true, + 'assets', + ); + this.counter.increment(); log('progress', { - type: 'assets-copy', - task: counter.getValue(), + type: 'assets', + task: this.counter.getValue(), total: Object.keys(index.objects).length, }); }), ); - } - counter.reset(); + this.counter.reset(); + + // Copy assets to legacy if it's an older Minecraft version. + if (isLegacy(this.parsedVersion)) { + if (existsSync(join(assetDirectory, 'legacy'))) { + log( + 'debug', + "The 'legacy' directory is no longer used as Minecraft looks " + + "for the resouces folder regardless of what is passed in the assetDirecotry launch option. I'd " + + `recommend removing the directory (${join(assetDirectory, 'legacy')})`, + ); + } + + const legacyDirectory = join(this.config.root, 'resources'); + log('debug', `Copying assets over to ${legacyDirectory}`); + + log('progress', { + type: 'assets-copy', + task: 0, + total: Object.keys(index.objects).length, + }); + + await Promise.all( + Object.keys(index.objects).map(async (asset) => { + const hash = index.objects[asset].hash; + const subhash = hash.substring(0, 2); + const subAsset = join(assetDirectory, 'objects', subhash); + + const legacyAsset = asset.split('/'); + legacyAsset.pop(); + + if (!existsSync(join(legacyDirectory, legacyAsset.join('/')))) { + mkdirSync(join(legacyDirectory, legacyAsset.join('/')), { recursive: true }); + } + + if (!existsSync(join(legacyDirectory, asset))) { + copyFileSync(join(subAsset, hash), join(legacyDirectory, asset)); + } + this.counter.increment(); + log('progress', { + type: 'assets-copy', + task: this.counter.getValue(), + total: Object.keys(index.objects).length, + }); + }), + ); + } + this.counter.reset(); - log('debug', 'Downloaded assets'); -}; + log('debug', 'Downloaded assets'); + } -const parseRule = (lib: LibType) => { - if (!lib.rules) return false; - if (lib.rules.length <= 1 && lib.rules[0].action === 'allow' && lib.rules[0].os) - return lib.rules[0].os.name !== getOS(); - if (lib.rules[0].action === 'allow' && lib.rules[1].action === 'disallow' && lib.rules[1].os.name === 'osx') - return getOS() === 'osx'; + parseRule(lib: LibType) { + if (!lib.rules) return false; + if (lib.rules.length <= 1 && lib.rules[0].action === 'allow' && lib.rules[0].os) + return lib.rules[0].os.name !== getOS(this.config.os); + if (lib.rules[0].action === 'allow' && lib.rules[1].action === 'disallow' && lib.rules[1].os.name === 'osx') + return getOS(this.config.os) === 'osx'; - return true; -}; + return true; + } -const getNatives = async () => { - const nativeDirectory = resolve(config.natives || join(config.root, 'natives', parsedVersion.id)); + async getNatives() { + const nativeDirectory = resolve( + this.config.natives || join(this.config.root, 'natives', this.parsedVersion.id), + ); - if (parseInt(parsedVersion.id.split('.')[1]) >= 19) return config.root; + if (parseInt(this.parsedVersion.id.split('.')[1]) >= 19) return this.config.root; + + if (!existsSync(nativeDirectory) || !readdirSync(nativeDirectory).length) { + mkdirSync(nativeDirectory, { recursive: true }); + + const natives = async () => { + const natives: ArtifactType[] = []; + await Promise.all( + this.parsedVersion.libraries.map(async (lib: LibType) => { + if (!lib.downloads || !lib.downloads.classifiers) return; + if (this.parseRule(lib)) return; + + const native = + getOS(this.config.os) === 'osx' + ? lib.downloads.classifiers['natives-osx'] + ? (lib.downloads.classifiers['natives-osx'] as ArtifactType) + : (lib.downloads.classifiers['natives-macos'] as ArtifactType) + : (lib.downloads.classifiers[`natives-${getOS(this.config.os)}`] as ArtifactType); + + natives.push(native); + }), + ); + return natives; + }; + const stat = await natives(); - if (!existsSync(nativeDirectory) || !readdirSync(nativeDirectory).length) { - mkdirSync(nativeDirectory, { recursive: true }); + log('progress', { + type: 'natives', + task: 0, + total: stat.length, + }); - const natives = async () => { - const natives: ArtifactType[] = []; await Promise.all( - parsedVersion.libraries.map(async (lib: LibType) => { - if (!lib.downloads || !lib.downloads.classifiers) return; - if (parseRule(lib)) return; - - const native = - getOS() === 'osx' - ? lib.downloads.classifiers['natives-osx'] - ? (lib.downloads.classifiers['natives-osx'] as ArtifactType) - : (lib.downloads.classifiers['natives-macos'] as ArtifactType) - : (lib.downloads.classifiers[`natives-${getOS()}`] as ArtifactType); - - natives.push(native); + stat.map(async (native) => { + if (!native) return; + const name = native.path.split('/').pop(); + + // Shouldn't even be happening + if (!name) return; + await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); + const downloaded = await checkSum(native.sha1, join(nativeDirectory, name)); + if (!existsSync(join(nativeDirectory, name)) || !downloaded) + await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives'); + try { + new Zip(join(nativeDirectory, name)).extractAllTo(nativeDirectory, true); + } catch (e) { + // Only doing a console.warn since a stupid error happens. You can basically ignore + // if it says Invalid file name, just means two files were downloaded and both were deleted. + // All is well. + console.warn(e); + } + unlinkSync(join(nativeDirectory, name)); + this.counter.increment(); + log('progress', { + type: 'natives', + task: this.counter.getValue(), + total: stat.length, + }); }), ); - return natives; - }; - const stat = await natives(); + log('debug', 'Downloaded and extracted natives'); + } - log('progress', { - type: 'natives', - task: 0, - total: stat.length, - }); + this.counter.reset(); + log('debug', `Set native path to ${nativeDirectory}`); - await Promise.all( - stat.map(async (native) => { - if (!native) return; - const name = native.path.split('/').pop(); - - // Shouldn't even be happening - if (!name) return; - await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); - const downloaded = await checkSum(native.sha1, join(nativeDirectory, name)); - if (!existsSync(join(nativeDirectory, name)) || !downloaded) - await downloadAsync(native.url, nativeDirectory, name, true, 'natives'); - try { - new Zip(join(nativeDirectory, name)).extractAllTo(nativeDirectory, true); - } catch (e) { - // Only doing a console.warn since a stupid error happens. You can basically ignore - // if it says Invalid file name, just means two files were downloaded and both were deleted. - // All is well. - console.warn(e); - } - unlinkSync(join(nativeDirectory, name)); - counter.increment(); - log('progress', { - type: 'natives', - task: counter.getValue(), - total: stat.length, - }); - }), + return nativeDirectory; + } + + fwAddArgs() { + const forgeWrapperAgrs = [ + `-Dforgewrapper.librariesDir=${resolve(this.config.libraryRoot || join(this.config.root, 'libraries'))}`, + `-Dforgewrapper.installer=${this.config.forge}`, + `-Dforgewrapper.minecraft=${resolve(join(this.config.directory, `${this.config.version.number}.jar`))}`, + ]; + this.config.customArgs + ? (this.config.customArgs = this.config.customArgs.concat(forgeWrapperAgrs)) + : (this.config.customArgs = forgeWrapperAgrs); + + return; + } + + // I don't see a better way of putting anything else (for now) + isModern(json: any): boolean { + return ( + json.inheritsFrom && + json.inheritsFrom.split('.')[1] >= 12 && + !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') ); - log('debug', 'Downloaded and extracted natives'); } - counter.reset(); - log('debug', `Set native path to ${nativeDirectory}`); - - return nativeDirectory; -}; - -const fwAddArgs = () => { - const forgeWrapperAgrs = [ - `-Dforgewrapper.librariesDir=${resolve(config.libraryRoot || join(config.root, 'libraries'))}`, - `-Dforgewrapper.installer=${config.forge}`, - `-Dforgewrapper.minecraft=${resolve(join(config.directory, `${config.version.number}.jar`))}`, - ]; - config.customArgs - ? (config.customArgs = config.customArgs.concat(forgeWrapperAgrs)) - : (config.customArgs = forgeWrapperAgrs); - - return; -}; - -// I don't see a better way of putting anything else (for now) -const isModern = (json: any): boolean => - json.inheritsFrom && - json.inheritsFrom.split('.')[1] >= 12 && - !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847'); - -const getForgedWrapped = async () => { - let json = null; - let installerJson = null; - const versionPath = join(config.root, 'forge', `${parsedVersion.id}`, 'version.json'); - // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not - // be re-generated on the next run. - if (existsSync(versionPath)) { - try { - json = JSON.parse(readFileSync(versionPath).toString()); - // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. - if (isModern(json)) { - fwAddArgs(); - config.forge = undefined; + async getForgedWrapped() { + let json = null; + let installerJson = null; + const versionPath = join(this.config.root, 'forge', `${this.parsedVersion.id}`, 'version.json'); + // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not + // be re-generated on the next run. + if (existsSync(versionPath)) { + try { + json = JSON.parse(readFileSync(versionPath).toString()); + // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. + if (this.isModern(json)) { + this.fwAddArgs(); + this.config.forge = undefined; + } + return json; + } catch (e) { + console.warn(e); + log('debug', 'Failed to parse Forge version JSON, re-generating'); } - return json; - } catch (e) { - console.warn(e); - log('debug', 'Failed to parse Forge version JSON, re-generating'); } - } - log('debug', 'Generating Forge version json, this might take a bit'); - const zipFile = new Zip(config.forge); - json = zipFile.readAsText('version.json'); - - if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); - try { - json = JSON.parse(json); - if (installerJson) installerJson = JSON.parse(installerJson); - } catch (e) { - log('debug', 'Failed to load json files for ForgeWrapper, using Vanilla instead'); - return null; - } - // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. - if (installerJson) - json.mavenFiles - ? (json.mavenFiles = json.mavenFiles.concat(installerJson.libraries)) - : (json.mavenFiles = installerJson.libraries); - - // Holder for the specifc jar ending which depends on the specifc forge version. - let jarEnding = 'universal'; - // We need to handle modern forge differently than legacy. - if (isModern(json)) { - // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. - if (json.inheritsFrom !== '1.12.2') { - fwAddArgs(); - json.libraries.push({ - name: 'io:github:zekerzhayard:ForgeWrapper:1.6.0', - downloads: { - artifact: { - path: 'io/github/zekerzhayard/ForgeWrapper/1.6.0/ForgeWrapper-1.6.0.jar', - url: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/1.6.0/ForgeWrapper-1.6.0.jar', - sha1: '035a51fe6439792a61507630d89382f621da0f1f', - size: 28679, + log('debug', 'Generating Forge version json, this might take a bit'); + const zipFile = new Zip(this.config.forge); + json = zipFile.readAsText('version.json'); + + if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json'); + try { + json = JSON.parse(json); + if (installerJson) installerJson = JSON.parse(installerJson); + } catch (e) { + log('debug', 'Failed to load json files for ForgeWrapper, using Vanilla instead'); + return null; + } + // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. + if (installerJson) + json.mavenFiles + ? (json.mavenFiles = json.mavenFiles.concat(installerJson.libraries)) + : (json.mavenFiles = installerJson.libraries); + + // Holder for the specifc jar ending which depends on the specifc forge version. + let jarEnding = 'universal'; + // We need to handle modern forge differently than legacy. + if (this.isModern(json)) { + // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. + if (json.inheritsFrom !== '1.12.2') { + this.fwAddArgs(); + json.libraries.push({ + name: 'io:github:zekerzhayard:ForgeWrapper:1.6.0', + downloads: { + artifact: { + path: 'io/github/zekerzhayard/ForgeWrapper/1.6.0/ForgeWrapper-1.6.0.jar', + url: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/1.6.0/ForgeWrapper-1.6.0.jar', + sha1: '035a51fe6439792a61507630d89382f621da0f1f', + size: 28679, + }, }, - }, - }); - json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main'; - jarEnding = 'launcher'; + }); + json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main'; + jarEnding = 'launcher'; - // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. - for (const library of json.mavenFiles) { - const lib = library.name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - library.downloads.artifact.url = `https://files.minecraftforge.net/maven/${library.downloads.artifact.path}`; - break; + // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. + for (const library of json.mavenFiles) { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { + library.downloads.artifact.url = `https://files.minecraftforge.net/maven/${library.downloads.artifact.path}`; + break; + } + } + } else { + // Remove the forge dependent since we're going to overwrite the first entry anyways. + for (const library in json.mavenFiles) { + const lib = json.mavenFiles[library].name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { + delete json.mavenFiles[library]; + break; + } } } } else { - // Remove the forge dependent since we're going to overwrite the first entry anyways. - for (const library in json.mavenFiles) { - const lib = json.mavenFiles[library].name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { - delete json.mavenFiles[library]; - break; - } + // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. + await Promise.all( + json.libraries.map( + async (library: { name: string; url?: string; serverreq: boolean; clientreq?: boolean }) => { + const lib = library.name.split(':'); + if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; + if (!library.url && !(library.serverreq || library.clientreq)) return; + + library.url = library.url + ? 'https://files.minecraftforge.net/maven/' + : 'https://libraries.minecraft.net/'; + const downloadLink = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${lib[1]}-${lib[2]}.jar`; + // Checking if the file still exists on Forge's server, if not, replace it with the fallback. + // Not checking for sucess, only if it 404s. + await axios + .get(downloadLink, { + timeout: this.config.timeout || 50000, + httpAgent: new http({ maxSockets: this.config.maxSockets || Infinity }), + httpsAgent: new https({ maxSockets: this.config.maxSockets || Infinity }), + }) + .then( + ({ status }) => + status === 404 && + (library.url = 'https://search.maven.org/remotecontent?filepath='), + ) + .catch(() => log('debug', `Failed checking request for ${downloadLink}`)); + }, + ), + ); + } + // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. + // If it doesn't, we simply remove it since we're already providing the universal jar. + const firstLibrary = json.libraries[0]; + if (firstLibrary.downloads) { + if (firstLibrary.name.includes('minecraftforge:forge') && !firstLibrary.name.includes('universal')) { + firstLibrary.name = `${firstLibrary.name}:${jarEnding}`; + firstLibrary.downloads.artifact.path = firstLibrary.downloads.artifact.replace( + '.jar', + `-${jarEnding}.jar`, + ); + firstLibrary.downloads.artifact.url = `https://files.minecraftforge.net/maven/${firstLibrary.downloads.artifact.path}`; } + + json.libraries[0] = firstLibrary; + } else { + delete json.libraries[0]; } - } else { - // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. + + // Removing duplicates and null types + json.libraries = cleanUp(json.libraries); + if (json.mavenFiles) json.mavenFiles = cleanUp(json.mavenFiles); + + // Saving file for next run! + if (!existsSync(join(this.config.root, 'forge', this.parsedVersion.id))) + mkdirSync(join(this.config.root, 'forge', this.parsedVersion.id), { recursive: true }); + writeFileSync(versionPath, JSON.stringify(json, null, 4)); + + // Make MCLC treat modern forge as a custom version json rather then legacy forge. + if ( + json.inheritsFrom && + json.inheritsFrom.split('.')[1] >= 12 && + !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') + ) + this.config.forge = undefined; + + return json; + } + + async downloadToDirectory(directory: string, libraries: LibType[] | CustomArtifactType[], eventName: string) { + const libs: string[] = []; + await Promise.all( - json.libraries.map( - async (library: { name: string; url?: string; serverreq: boolean; clientreq?: boolean }) => { - const lib = library.name.split(':'); - if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return; - if (!library.url && !(library.serverreq || library.clientreq)) return; - - library.url = library.url - ? 'https://files.minecraftforge.net/maven/' - : 'https://libraries.minecraft.net/'; - const downloadLink = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${lib[1]}-${lib[2]}.jar`; - // Checking if the file still exists on Forge's server, if not, replace it with the fallback. - // Not checking for sucess, only if it 404s. - await axios - .get(downloadLink, { - timeout: config.timeout || 50000, - httpAgent: new http({ maxSockets: config.maxSockets || Infinity }), - httpsAgent: new https({ maxSockets: config.maxSockets || Infinity }), - }) - .then( - ({ status }) => - status === 404 && (library.url = 'https://search.maven.org/remotecontent?filepath='), - ) - .catch(() => log('debug', `Failed checking request for ${downloadLink}`)); - }, - ), + libraries.map(async (library) => { + if (!library) return; + if ('downloads' in library && this.parseRule(library)) return; + const lib = library.name.split(':'); + + let jarPath: string; + let name: string; + if ('downloads' in library && library.downloads.artifact && library.downloads.artifact.path) { + name = + library.downloads.artifact.path.split('/')[ + library.downloads.artifact.path.split('/').length - 1 + ]; + jarPath = join(directory, popString(library.downloads.artifact.path)); + } else { + name = `${lib[1]}-${lib[2]}${lib[3] ? `-${lib[3]}` : ''}.jar`; + jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); + } + + const downloadLibrary = async (library: LibType | CustomArtifactType) => { + if ('url' in library) { + const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; + await this.downloadAsync(url, jarPath, name, true, eventName); + } else if ('downloads' in library && library.downloads.artifact && library.downloads.artifact.url) { + // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. + await this.downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); + } + }; + + if (!existsSync(join(jarPath, name))) await downloadLibrary(library); + if ('downloads' in library && library.downloads.artifact) + if (!checkSum(library.downloads.artifact.sha1, join(jarPath, name))) await downloadLibrary(library); + + this.counter.increment(); + log('progress', { + type: eventName, + task: this.counter.getValue(), + total: libraries.length, + }); + libs.push(`${jarPath}${sep}${name}`); + }), ); + this.counter.reset(); + + return libs; } - // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. - // If it doesn't, we simply remove it since we're already providing the universal jar. - const firstLibrary = json.libraries[0]; - if (firstLibrary.downloads) { - if (firstLibrary.name.includes('minecraftforge:forge') && !firstLibrary.name.includes('universal')) { - firstLibrary.name = `${firstLibrary.name}:${jarEnding}`; - firstLibrary.downloads.artifact.path = firstLibrary.downloads.artifact.replace('.jar', `-${jarEnding}.jar`); - firstLibrary.downloads.artifact.url = `https://files.minecraftforge.net/maven/${firstLibrary.downloads.artifact.path}`; + + async getClasses(classJson: CustomLibType) { + let libs: string[] = []; + const libraryDirectory = resolve(this.config.libraryRoot || join(this.config.root, 'libraries')); + + if (classJson) { + if (classJson.mavenFiles) + await this.downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom'); + libs = await this.downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom'); } - json.libraries[0] = firstLibrary; - } else { - delete json.libraries[0]; + const parsed = this.parsedVersion.libraries.filter(Boolean).map((lib: LibType) => { + if (lib.downloads && lib.downloads.artifact && !this.parseRule(lib)) return lib; + }); + + libs = libs.concat(await this.downloadToDirectory(libraryDirectory, parsed as LibType[], 'classes')); + this.counter.reset(); + + if (classJson) libs.sort(); + + log('debug', 'Collected class paths'); + return libs; } - // Removing duplicates and null types - json.libraries = cleanUp(json.libraries); - if (json.mavenFiles) json.mavenFiles = cleanUp(json.mavenFiles); - - // Saving file for next run! - if (!existsSync(join(config.root, 'forge', parsedVersion.id))) - mkdirSync(join(config.root, 'forge', parsedVersion.id), { recursive: true }); - writeFileSync(versionPath, JSON.stringify(json, null, 4)); - - // Make MCLC treat modern forge as a custom version json rather then legacy forge. - if ( - json.inheritsFrom && - json.inheritsFrom.split('.')[1] >= 12 && - !(json.inheritsFrom === '1.12.2' && json.id.split('.')[json.id.split('.').length - 1] === '2847') - ) - config.forge = undefined; - - return json; -}; - -const downloadToDirectory = async ( - directory: string, - libraries: LibType[] | CustomArtifactType[], - eventName: string, -) => { - const libs: string[] = []; - - await Promise.all( - libraries.map(async (library) => { - if (!library) return; - if ('downloads' in library && parseRule(library)) return; - const lib = library.name.split(':'); - - let jarPath: string; - let name: string; - if ('downloads' in library && library.downloads.artifact && library.downloads.artifact.path) { - name = - library.downloads.artifact.path.split('/')[library.downloads.artifact.path.split('/').length - 1]; - jarPath = join(directory, popString(library.downloads.artifact.path)); - } else { - name = `${lib[1]}-${lib[2]}${lib[3] ? `-${lib[3]}` : ''}.jar`; - jarPath = join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`); + processArguments(...args: (string | Rule | string[])[]): string[] { + const result: string[] = []; + args.forEach((arg) => { + if (Array.isArray(arg)) { + result.push(...arg.filter((item) => typeof item !== 'object')); + } else if (typeof arg === 'string') { + result.push(arg); } + }); - const downloadLibrary = async (library: LibType | CustomArtifactType) => { - if ('url' in library) { - const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}`; - await downloadAsync(url, jarPath, name, true, eventName); - } else if ('downloads' in library && library.downloads.artifact && library.downloads.artifact.url) { - // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. - await downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName); - } - }; + return result; + } - if (!existsSync(join(jarPath, name))) await downloadLibrary(library); - if ('downloads' in library && library.downloads.artifact) - if (!checkSum(library.downloads.artifact.sha1, join(jarPath, name))) await downloadLibrary(library); + async getLaunchOptions(modification: CustomLibType | null): Promise { + const type = Object.assign({}, this.parsedVersion, modification); + const args = type.minecraftArguments + ? type.minecraftArguments.split(' ') + : this.processArguments(type.arguments.game); + const assetPath = resolve( + isLegacy(this.parsedVersion) + ? join(this.config.root, 'resources') + : join(this.config.assetRoot || join(this.config.root, 'assets')), + ); - counter.increment(); - log('progress', { - type: eventName, - task: counter.getValue(), - total: libraries.length, - }); - libs.push(`${jarPath}${sep}${name}`); - }), - ); - counter.reset(); - - return libs; -}; - -const getClasses = async (classJson: CustomLibType) => { - let libs: string[] = []; - const libraryDirectory = resolve(config.libraryRoot || join(config.root, 'libraries')); - - if (classJson) { - if (classJson.mavenFiles) - await downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom'); - libs = await downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom'); - } + if (this.config.customLaunchArgs) args.concat(this.config.customLaunchArgs); + + this.config.authorization = await Promise.resolve(this.config.authorization); + this.config.authorization.meta = this.config.authorization.meta ?? { demo: false, type: 'mojang' }; + const fields: Fields = { + '${auth_access_token}': this.config.authorization.access_token, + '${auth_session}': this.config.authorization.access_token, + '${auth_player_name}': this.config.authorization.name, + '${auth_uuid}': this.config.authorization.uuid, + '${auth_xuid}': this.config.authorization.access_token, + '${user_properties}': '{}', + '${user_type}': this.config.authorization.meta.type, + '${version_name}': this.config.version.number || this.config.versionName, + '${assets_index_name}': this.config.assetIndex || this.config.version.custom || this.config.version.number, + '${game_directory}': this.config.gameDirectory || resolve(this.config.root), + '${assets_root}': assetPath, + '${game_assets}': assetPath, + '${version_type}': this.config.version.type, + '${clientid}': this.config.authorization.client_token || this.config.authorization.access_token, + '${resolution_width}': this.config.window ? this.config.window.width : 856, + '${resolution_height}': this.config.window ? this.config.window.height : 482, + }; - const parsed = parsedVersion.libraries.filter(Boolean).map((lib: LibType) => { - if (lib.downloads && lib.downloads.artifact && !parseRule(lib)) return lib; - }); + if ( + this.config.authorization.meta.demo && + (this.config.features ? !this.config.features.includes('is_demo_user') : true) + ) + args.push('--demo'); - libs = libs.concat(await downloadToDirectory(libraryDirectory, parsed as LibType[], 'classes')); - counter.reset(); + if (this.config.window) { + if (this.config.window.fullscreen) { + args.push('--fullscreen'); + } else { + if (this.config.window.width) args.push('--width', this.config.window.width.toString()); + if (this.config.window.height) args.push('--height', this.config.window.height.toString()); + } + } - if (classJson) libs.sort(); + if (this.config.quickPlay) { + const types = { + singleplayer: '--quickPlaySingleplayer', + multiplayer: '--quickPlayMultiplayer', + realms: '--quickPlayRealms', + legacy: null, + }; - log('debug', 'Collected class paths'); - return libs; -}; + const { type, identifier, path } = this.config.quickPlay; + const keys = Object.keys(types); + if (!keys.includes(type)) { + log('debug', `quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); + } else { + const returnArgs = + type === 'legacy' + ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] + : [types[type], identifier]; -const processArguments = (...args: (string | Rule | string[])[]): string[] => { - const result: string[] = []; - args.forEach((arg) => { - if (Array.isArray(arg)) { - result.push(...arg.filter((item) => typeof item !== 'object')); - } else if (typeof arg === 'string') { - result.push(arg); - } - }); - - return result; -}; - -const getLaunchOptions = async (modification: CustomLibType | null): Promise => { - const type = Object.assign({}, parsedVersion, modification); - const args = type.minecraftArguments ? type.minecraftArguments.split(' ') : processArguments(type.arguments.game); - const assetPath = resolve( - isLegacy(parsedVersion) - ? join(config.root, 'resources') - : join(config.assetRoot || join(config.root, 'assets')), - ); - - if (config.customLaunchArgs) args.concat(config.customLaunchArgs); - - config.authorization = await Promise.resolve(config.authorization); - config.authorization.meta = config.authorization.meta ?? { demo: false, type: 'mojang' }; - const fields: Fields = { - '${auth_access_token}': config.authorization.access_token, - '${auth_session}': config.authorization.access_token, - '${auth_player_name}': config.authorization.name, - '${auth_uuid}': config.authorization.uuid, - '${auth_xuid}': config.authorization.access_token, - '${user_properties}': '{}', - '${user_type}': config.authorization.meta.type, - '${version_name}': config.version.number || config.versionName, - '${assets_index_name}': config.assetIndex || config.version.custom || config.version.number, - '${game_directory}': config.gameDirectory || resolve(config.root), - '${assets_root}': assetPath, - '${game_assets}': assetPath, - '${version_type}': config.version.type, - '${clientid}': config.authorization.client_token || config.authorization.access_token, - '${resolution_width}': config.window ? config.window.width : 856, - '${resolution_height}': config.window ? config.window.height : 482, - }; - - if (config.authorization.meta.demo && (config.features ? !config.features.includes('is_demo_user') : true)) - args.push('--demo'); - - if (config.window) { - if (config.window.fullscreen) { - args.push('--fullscreen'); - } else { - if (config.window.width) args.push('--width', config.window.width.toString()); - if (config.window.height) args.push('--height', config.window.height.toString()); + if (path) returnArgs.push('--quickPlayPath', path); + args.concat(returnArgs); + } } - } - - if (config.quickPlay) { - const types = { - singleplayer: '--quickPlaySingleplayer', - multiplayer: '--quickPlayMultiplayer', - realms: '--quickPlayRealms', - legacy: null, - }; - const { type, identifier, path } = config.quickPlay; - const keys = Object.keys(types); - if (!keys.includes(type)) { - log('debug', `quickPlay type is not valid. Valid types are: ${keys.join(', ')}`); - } else { - const returnArgs = - type === 'legacy' - ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] - : [types[type], identifier]; + if (this.config.proxy) { + args.push('--proxyHost', this.config.proxy.host, '--proxyPort', this.config.proxy.port || '8080'); - if (path) returnArgs.push('--quickPlayPath', path); - args.concat(returnArgs); + if (this.config.proxy.username) args.push('--proxyUser', this.config.proxy.username); + if (this.config.proxy.password) args.push('--proxyPass', this.config.proxy.password); } - } - if (config.proxy) { - args.push('--proxyHost', config.proxy.host, '--proxyPort', config.proxy.port || '8080'); + log('debug', 'Set launch options'); + return args.map((arg) => + Object.entries(fields).reduce( + (acc, [placeholder, replacement]) => + acc.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), replacement), + arg, + ), + ); + } - if (config.proxy.username) args.push('--proxyUser', config.proxy.username); - if (config.proxy.password) args.push('--proxyPass', config.proxy.password); + async getJVM() { + return { + windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', + osx: '-XstartOnFirstThread', + linux: '-Xss1M', + }[getOS(this.config.os)]; } - log('debug', 'Set launch options'); - return args.map((arg) => - Object.entries(fields).reduce( - (acc, [placeholder, replacement]) => - acc.replace(new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), replacement), - arg, - ), - ); -}; - -const getJVM = async () => - ({ - windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', - osx: '-XstartOnFirstThread', - linux: '-Xss1M', - })[getOS()]; - -const getMemory = () => { - if (typeof config.memory.min === 'number' && typeof config.memory.max === 'number') { - if (config.memory.max < config.memory.min) { - log('debug', 'MIN memory is higher then MAX! Resetting!'); - config.memory = { + getMemory() { + if (typeof this.config.memory.min === 'number' && typeof this.config.memory.max === 'number') { + if (this.config.memory.max < this.config.memory.min) { + log('debug', 'MIN memory is higher then MAX! Resetting!'); + this.config.memory = { + min: Math.pow(2, 9), + max: Math.pow(2, 10), + }; + } + return [`${this.config.memory.max}M`, `${this.config.memory.min}M`]; + } else if (typeof this.config.memory.min === 'string' && typeof this.config.memory.max === 'string') { + return [`${this.config.memory.max}`, `${this.config.memory.min}`]; + } else { + log( + 'debug', + `MIN memory is a ${typeof this.config.memory.min} while MAX is ${typeof this.config.memory.max}! Resetting!`, + ); + this.config.memory = { min: Math.pow(2, 9), max: Math.pow(2, 10), }; + return [`${this.config.memory.max}M`, `${this.config.memory.min}M`]; } - return [`${config.memory.max}M`, `${config.memory.min}M`]; - } else if (typeof config.memory.min === 'string' && typeof config.memory.max === 'string') { - return [`${config.memory.max}`, `${config.memory.min}`]; - } else { - log( - 'debug', - `MIN memory is a ${typeof config.memory.min} while MAX is ${typeof config.memory.max}! Resetting!`, - ); - config.memory = { - min: Math.pow(2, 9), - max: Math.pow(2, 10), - }; - return [`${config.memory.max}M`, `${config.memory.min}M`]; } -}; - -export { - checkJava, - downloadAsync, - getVersion, - getJar, - getAssets, - getNatives, - getForgedWrapped, - getClasses, - getLaunchOptions, - getJVM, - getMemory, -}; +} + +export default Handler; diff --git a/src/launcher.ts b/src/launcher.ts index 3eefb80..52cbb01 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -1,28 +1,45 @@ import { spawn } from 'node:child_process'; import { existsSync, mkdirSync, readFileSync } from 'node:fs'; import { join, resolve } from 'node:path'; -import { - checkJava, - downloadAsync, - getAssets, - getClasses, - getForgedWrapped, - getJar, - getJVM, - getLaunchOptions, - getMemory, - getNatives, - getVersion, -} from '@/handler'; +import { offline } from '@/authenticator'; +import Handler from '@/handler'; import mclc from '@/mclc'; +import { Options } from '@/types'; import { cleanUp, getOS } from '@/utils'; -import { config, defineConfig } from '@/utils/config'; import { log } from '@/utils/log'; -import { Options } from './types'; + +const initialConfig: Options = { + mclc_log: true, + root: './minecraft', + directory: '', + authorization: offline('Steve'), + detached: true, + version: { + number: '1.14.4', + type: 'release', + }, + url: { + meta: 'https://launchermeta.mojang.com', + resource: 'https://resources.download.minecraft.net', + }, + memory: { + min: Math.pow(2, 9), + max: Math.pow(2, 10), + }, +}; export class Client { + config: Options; + handler: Handler; + constructor(config: Options) { - defineConfig(config); + this.config = { ...initialConfig, ...config }; + this.config.directory = join( + this.config.root, + 'versions', + this.config.version.custom || this.config.version.number, + ); + this.handler = new Handler(this.config); } launch() { @@ -32,81 +49,97 @@ export class Client { } async install() { - log('version', `MCLC version ${mclc}`); + this.config.mclc_log && log('version', `MCLC version ${mclc}`); - if (!existsSync(config.root)) { + if (!existsSync(this.config.root)) { log('debug', 'Attempting to create root folder'); - mkdirSync(config.root); + mkdirSync(this.config.root); } - if (config.gameDirectory) { - defineConfig({ gameDirectory: resolve(config.gameDirectory) }); - if (!existsSync(config.gameDirectory)) mkdirSync(config.gameDirectory, { recursive: true }); + if (this.config.gameDirectory) { + this.config.gameDirectory = resolve(this.config.gameDirectory); + if (!existsSync(this.config.gameDirectory)) mkdirSync(this.config.gameDirectory, { recursive: true }); } - await getVersion(); + await this.handler.getVersion(); const mcPath = - config.minecraftJar || - (config.version.custom - ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) - : join(config.directory, `${config.version.number}.jar`)); - await getNatives(); + this.config.minecraftJar || + (this.config.version.custom + ? join(this.config.root, 'versions', this.config.version.custom, `${this.config.version.custom}.jar`) + : join(this.config.directory, `${this.config.version.number}.jar`)); + await this.handler.getNatives(); if (!existsSync(mcPath)) { log('debug', 'Attempting to download Minecraft version jar'); - await getJar(); + await this.handler.getJar(); } let modifyJson = null; - if (config.version.custom) { + if (this.config.version.custom) { log('debug', 'Detected custom in options, setting custom version file'); modifyJson = JSON.parse( - readFileSync(join(config.root, 'versions', config.version.custom, `${config.version.custom}.json`), { - encoding: 'utf8', - }), + readFileSync( + join( + this.config.root, + 'versions', + this.config.version.custom, + `${this.config.version.custom}.json`, + ), + { + encoding: 'utf8', + }, + ), ); } - cleanUp(await getClasses(modifyJson)); + cleanUp(await this.handler.getClasses(modifyJson)); log('debug', 'Attempting to download assets'); - await getAssets(); + await this.handler.getAssets(); - log('debug', `Successfully installed Minecraft ${config.version.number}`); + log('debug', `Successfully installed Minecraft ${this.config.version.number}`); return; } async start() { - log('version', `MCLC version ${mclc}`); + this.config.mclc_log && log('version', `MCLC version ${mclc}`); - const java = await checkJava(config.javaPath || 'java'); + const java = await this.handler.checkJava(this.config.javaPath || 'java'); if (!java || !java.run) { log('debug', `Couldn't start Minecraft due to: ${java.message}`); return log('close', 1); } - const versionFile = await getVersion(); + const versionFile = await this.handler.getVersion(); const mcPath = - config.minecraftJar || - (config.version.custom - ? join(config.root, 'versions', config.version.custom, `${config.version.custom}.jar`) - : join(config.directory, `${config.version.number}.jar`)); - const nativePath = await getNatives(); + this.config.minecraftJar || + (this.config.version.custom + ? join(this.config.root, 'versions', this.config.version.custom, `${this.config.version.custom}.jar`) + : join(this.config.directory, `${this.config.version.number}.jar`)); + const nativePath = await this.handler.getNatives(); const args: string[] = []; let modifyJson = null; - if (config.version.custom) { + if (this.config.version.custom) { log('debug', 'Detected custom in options, setting custom version file'); modifyJson = JSON.parse( - readFileSync(join(config.root, 'versions', config.version.custom, `${config.version.custom}.json`), { - encoding: 'utf8', - }), + readFileSync( + join( + this.config.root, + 'versions', + this.config.version.custom, + `${this.config.version.custom}.json`, + ), + { + encoding: 'utf8', + }, + ), ); - } else if (config.forge) { - defineConfig({ forge: resolve(config.forge) }); + } else if (this.config.forge) { + this.config.forge = resolve(this.config.forge); log('debug', 'Detected Forge in options, getting dependencies'); - modifyJson = await getForgedWrapped(); + modifyJson = await this.handler.getForgedWrapped(); } const jvm = [ @@ -115,26 +148,26 @@ export class Client { '-Dfml.ignorePatchDiscrepancies=true', '-Dfml.ignoreInvalidMinecraftCertificates=true', `-Djava.library.path=${resolve(nativePath)}`, - `-Xmx${getMemory()[0]}`, - `-Xms${getMemory()[1]}`, + `-Xmx${this.handler.getMemory()[0]}`, + `-Xms${this.handler.getMemory()[1]}`, ]; - if (getOS() === 'osx') { - if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await getJVM()); - } else jvm.push(await getJVM()); + if (getOS(this.config.os) === 'osx') { + if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()); + } else jvm.push(await this.handler.getJVM()); - if (config.customArgs) jvm.concat(config.customArgs); - if (config.logj4ConfigurationFile) - jvm.push(`-Dlog4j.configurationFile=${resolve(config.logj4ConfigurationFile)}`); + if (this.config.customArgs) jvm.concat(this.config.customArgs); + if (this.config.logj4ConfigurationFile) + jvm.push(`-Dlog4j.configurationFile=${resolve(this.config.logj4ConfigurationFile)}`); // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true'); if (parseInt(versionFile.id.split('.')[1]) < 17) { if (!jvm.find((arg) => arg.includes('Dlog4j.configurationFile'))) { - const configPath = resolve(config.root); + const configPath = resolve(this.config.root); const intVersion = parseInt(versionFile.id.split('.')[1]); if (intVersion >= 12) { - await downloadAsync( + await this.handler.downloadAsync( 'https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', configPath, 'log4j2_112-116.xml', @@ -143,7 +176,7 @@ export class Client { ); jvm.push(`-Dlog4j.configurationFile=${resolve(join(configPath, 'log4j2_112-116.xml'))}`); } else if (intVersion >= 7) { - await downloadAsync( + await this.handler.downloadAsync( 'https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', configPath, 'log4j2_17-111.xml', @@ -155,26 +188,28 @@ export class Client { } } - const classes = config.classes || cleanUp(await getClasses(modifyJson)); + const classes = this.config.classes || cleanUp(await this.handler.getClasses(modifyJson)); const classPaths = ['-cp']; - const separator = getOS() === 'windows' ? ';' : ':'; + const separator = getOS(this.config.os) === 'windows' ? ';' : ':'; log('debug', `Using ${separator} to separate class paths`); // Handling launch arguments. const file = modifyJson || versionFile; // So mods like fabric work. const jar = existsSync(mcPath) ? `${separator}${resolve(mcPath)}` - : `${separator}${resolve(join(config.directory, `${config.version.number}.jar`))}`; - classPaths.push(`${config.forge ? `${config.forge}${separator}` : ''}${classes.join(separator)}${jar}`); + : `${separator}${resolve(join(this.config.directory, `${this.config.version.number}.jar`))}`; + classPaths.push( + `${this.config.forge ? `${this.config.forge}${separator}` : ''}${classes.join(separator)}${jar}`, + ); classPaths.push(file.mainClass); - const launchconfig = await getLaunchOptions(modifyJson); + const launchconfig = await this.handler.getLaunchOptions(modifyJson); const launchArguments = args.concat(jvm, classPaths, launchconfig); log('arguments', launchArguments); log('debug', `Launching with arguments ${launchArguments.join(' ')}`); - const minecraft = spawn(config.javaPath ?? 'java', launchArguments, { - detached: config.detached, + const minecraft = spawn(this.config.javaPath ?? 'java', launchArguments, { + detached: this.config.detached, }); minecraft.stdout.on('data', (data) => log('data', data.toString('utf-8'))); minecraft.stderr.on('data', (data) => log('data', data.toString('utf-8'))); diff --git a/src/types/Options.ts b/src/types/Options.ts index 582a9f6..745210c 100644 --- a/src/types/Options.ts +++ b/src/types/Options.ts @@ -1,6 +1,10 @@ import { OS, User } from '@/types'; export default interface Options { + /** + * console.log the MCLC version + */ + mclc_log?: boolean; /** * if true MCLC will remove the client package zip file after its finished extracting. */ diff --git a/src/utils/config.ts b/src/utils/config.ts deleted file mode 100644 index 2a2464d..0000000 --- a/src/utils/config.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { join } from 'node:path'; -import { offline } from '@/authenticator'; -import { Options } from '@/types'; - -let config: Options = { - root: './minecraft', - directory: '', - authorization: offline('Steve'), - detached: true, - version: { - number: '1.14.4', - type: 'release', - }, - url: { - meta: 'https://launchermeta.mojang.com', - resource: 'https://resources.download.minecraft.net', - }, - memory: { - min: Math.pow(2, 9), - max: Math.pow(2, 10), - }, -}; - -const defineConfig = (newConfig: Partial): void => { - config = { ...config, ...newConfig }; - config.directory = join(config.root, 'versions', config.version.custom || config.version.number); - return; -}; - -export { config, defineConfig }; diff --git a/src/utils/index.ts b/src/utils/index.ts index 9212389..46b2395 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,14 +2,13 @@ import { createHash } from 'node:crypto'; import { createReadStream, stat } from 'node:fs'; import { resolve as _resolve } from 'node:path'; import { OS, Version } from '@/types'; -import { config } from '@/utils/config'; import { log } from '@/utils/log'; const popString = (path: string) => path.split('/').slice(0, -1).join('/'); const cleanUp = (array: string[]) => [...new Set(Object.values(array).filter((value) => value !== null))]; -const getOS = (): OS => { - if (config.os) return config.os; +const getOS = (os?: OS): OS => { + if (os) return os; switch (process.platform) { case 'win32': diff --git a/tests/vanilla.ts b/tests/vanilla.ts index 7455b67..aabb57c 100644 --- a/tests/vanilla.ts +++ b/tests/vanilla.ts @@ -5,15 +5,17 @@ import { afterAll, describe, expect, test } from 'vitest'; import { Client } from '../src'; describe('Minecraft Vanilla Legacy (1.8.9)', () => { + const client = new Client({ + version: { + number: '1.8.9', + type: 'release', + }, + }); + test( 'Installation', async () => { - await new Client({ - version: { - number: '1.8.9', - type: 'release', - }, - }).install(); + await client.install(); expect(existsSync(resolve('./minecraft/natives/1.8.9'))).toBe(true); expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.jar'))).toBe(true); expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.json'))).toBe(true); @@ -24,12 +26,7 @@ describe('Minecraft Vanilla Legacy (1.8.9)', () => { test( 'Starting', async () => { - const process = await new Client({ - version: { - number: '1.8.9', - type: 'release', - }, - }).start(); + const process = await client.start(); expect(process && typeof process.kill === 'function').toBe(true); await new Promise((resolve) => { setTimeout(() => { @@ -51,15 +48,17 @@ describe('Minecraft Vanilla Legacy (1.8.9)', () => { }); describe('Minecraft Vanilla Modern (1.14.4)', () => { + const client = new Client({ + version: { + number: '1.14.4', + type: 'release', + }, + }); + test( 'Installation', async () => { - await new Client({ - version: { - number: '1.14.4', - type: 'release', - }, - }).install(); + await client.install(); expect(existsSync(resolve('./minecraft/natives/1.14.4'))).toBe(true); expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.jar'))).toBe(true); expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.json'))).toBe(true); @@ -70,12 +69,7 @@ describe('Minecraft Vanilla Modern (1.14.4)', () => { test( 'Starting', async () => { - const process = await new Client({ - version: { - number: '1.14.4', - type: 'release', - }, - }).start(); + const process = await client.start(); expect(process && typeof process.kill === 'function').toBe(true); await new Promise((resolve) => { setTimeout(() => { From e184a900ed6ea55cab33121e245afe182c9d09dc Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 23:21:16 +0300 Subject: [PATCH 82/97] Testing --- .github/workflows/tests.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1919995..345ec9a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,13 +16,5 @@ jobs: java-version: "8" - run: yarn install --frozen-lockfile - run: yarn test - - prettier: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: "18.x" - - run: yarn install --frozen-lockfile - - run: yarn prettier + - run: ls + - run: ls minecraft From 73d39e9b5f7db8face84b1841a86ed0650d114af Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 23:23:47 +0300 Subject: [PATCH 83/97] Update tests.yml --- .github/workflows/tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 345ec9a..2a9acfd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,4 +17,6 @@ jobs: - run: yarn install --frozen-lockfile - run: yarn test - run: ls + if: always() - run: ls minecraft + if: always() From 8d46b9847c3163914d6fcb5ecfd453a4c50e9a67 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 23:31:02 +0300 Subject: [PATCH 84/97] More testing --- .github/workflows/tests.yml | 4 +--- src/launcher.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2a9acfd..69ab7c3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,5 @@ jobs: java-version: "8" - run: yarn install --frozen-lockfile - run: yarn test - - run: ls - if: always() - - run: ls minecraft + - run: ls minecraft/versions if: always() diff --git a/src/launcher.ts b/src/launcher.ts index 52cbb01..cc10015 100644 --- a/src/launcher.ts +++ b/src/launcher.ts @@ -206,7 +206,7 @@ export class Client { const launchconfig = await this.handler.getLaunchOptions(modifyJson); const launchArguments = args.concat(jvm, classPaths, launchconfig); log('arguments', launchArguments); - log('debug', `Launching with arguments ${launchArguments.join(' ')}`); + console.log('debug', `Launching with arguments ${launchArguments.join(' ')}`); const minecraft = spawn(this.config.javaPath ?? 'java', launchArguments, { detached: this.config.detached, From a17fb2c12ada995c353999bc1b74484bc3336b4b Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 23:37:04 +0300 Subject: [PATCH 85/97] Launch MC manually --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 69ab7c3..e954519 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,5 +16,5 @@ jobs: java-version: "8" - run: yarn install --frozen-lockfile - run: yarn test - - run: ls minecraft/versions + - run: java -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignorePatchDiscrepancies=true -Dfml.ignoreInvalidMinecraftCertificates=true -Djava.library.path=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/natives/1.14.4 -Xmx1024M -Xms512M -Xss1M -Dlog4j.configurationFile=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/log4j2_112-116.xml -cp /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/patchy/1.3.9/patchy-1.3.9.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/oshi-project/oshi-core/1.1/oshi-core-1.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/jna/4.4.0/jna-4.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/javabridge/1.0.22/javabridge-1.0.22.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/sf/jopt-simple/jopt-simple/5.0.3/jopt-simple-5.0.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/io/netty/netty-all/4.1.25.Final/netty-all-4.1.25.Final.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/guava/guava/21.0/guava-21.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-io/commons-io/2.5/commons-io-2.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/brigadier/1.0.17/brigadier-1.0.17.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/datafixerupper/2.0.24/datafixerupper-2.0.24.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/code/gson/gson/2.8.0/gson-2.8.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/authlib/1.5.25/authlib-1.5.25.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/it/unimi/dsi/fastutil/8.2.1/fastutil-8.2.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-api/2.8.1/log4j-api-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-core/2.8.1/log4j-core-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl/3.2.2/lwjgl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-jemalloc/3.2.2/lwjgl-jemalloc-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-openal/3.2.2/lwjgl-openal-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-opengl/3.2.2/lwjgl-opengl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-glfw/3.2.2/lwjgl-glfw-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-stb/3.2.2/lwjgl-stb-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/versions/1.14.4/1.14.4.jar net.minecraft.client.main.Main --username Steve --version 1.14.4 --gameDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft --assetsDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/assets --assetIndex 1.14.4 --uuid e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --accessToken e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --userType mojang --versionType release if: always() From 1e7d6cae39393d63d076fcaf5d979727578a2695 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 23:43:38 +0300 Subject: [PATCH 86/97] -Dfml.earlyprogresswindow=false --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e954519..f4eb9f6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,5 +16,5 @@ jobs: java-version: "8" - run: yarn install --frozen-lockfile - run: yarn test - - run: java -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignorePatchDiscrepancies=true -Dfml.ignoreInvalidMinecraftCertificates=true -Djava.library.path=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/natives/1.14.4 -Xmx1024M -Xms512M -Xss1M -Dlog4j.configurationFile=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/log4j2_112-116.xml -cp /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/patchy/1.3.9/patchy-1.3.9.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/oshi-project/oshi-core/1.1/oshi-core-1.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/jna/4.4.0/jna-4.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/javabridge/1.0.22/javabridge-1.0.22.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/sf/jopt-simple/jopt-simple/5.0.3/jopt-simple-5.0.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/io/netty/netty-all/4.1.25.Final/netty-all-4.1.25.Final.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/guava/guava/21.0/guava-21.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-io/commons-io/2.5/commons-io-2.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/brigadier/1.0.17/brigadier-1.0.17.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/datafixerupper/2.0.24/datafixerupper-2.0.24.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/code/gson/gson/2.8.0/gson-2.8.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/authlib/1.5.25/authlib-1.5.25.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/it/unimi/dsi/fastutil/8.2.1/fastutil-8.2.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-api/2.8.1/log4j-api-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-core/2.8.1/log4j-core-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl/3.2.2/lwjgl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-jemalloc/3.2.2/lwjgl-jemalloc-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-openal/3.2.2/lwjgl-openal-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-opengl/3.2.2/lwjgl-opengl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-glfw/3.2.2/lwjgl-glfw-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-stb/3.2.2/lwjgl-stb-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/versions/1.14.4/1.14.4.jar net.minecraft.client.main.Main --username Steve --version 1.14.4 --gameDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft --assetsDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/assets --assetIndex 1.14.4 --uuid e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --accessToken e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --userType mojang --versionType release + - run: java -Dfml.earlyprogresswindow=false -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignorePatchDiscrepancies=true -Dfml.ignoreInvalidMinecraftCertificates=true -Djava.library.path=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/natives/1.14.4 -Xmx1024M -Xms512M -Xss1M -Dlog4j.configurationFile=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/log4j2_112-116.xml -cp /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/patchy/1.3.9/patchy-1.3.9.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/oshi-project/oshi-core/1.1/oshi-core-1.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/jna/4.4.0/jna-4.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/javabridge/1.0.22/javabridge-1.0.22.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/sf/jopt-simple/jopt-simple/5.0.3/jopt-simple-5.0.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/io/netty/netty-all/4.1.25.Final/netty-all-4.1.25.Final.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/guava/guava/21.0/guava-21.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-io/commons-io/2.5/commons-io-2.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/brigadier/1.0.17/brigadier-1.0.17.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/datafixerupper/2.0.24/datafixerupper-2.0.24.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/code/gson/gson/2.8.0/gson-2.8.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/authlib/1.5.25/authlib-1.5.25.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/it/unimi/dsi/fastutil/8.2.1/fastutil-8.2.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-api/2.8.1/log4j-api-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-core/2.8.1/log4j-core-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl/3.2.2/lwjgl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-jemalloc/3.2.2/lwjgl-jemalloc-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-openal/3.2.2/lwjgl-openal-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-opengl/3.2.2/lwjgl-opengl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-glfw/3.2.2/lwjgl-glfw-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-stb/3.2.2/lwjgl-stb-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/versions/1.14.4/1.14.4.jar net.minecraft.client.main.Main --username Steve --version 1.14.4 --gameDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft --assetsDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/assets --assetIndex 1.14.4 --uuid e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --accessToken e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --userType mojang --versionType release if: always() From 204bd71cb068c9fb080aa0a7b63f1efb962b3007 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 23:51:24 +0300 Subject: [PATCH 87/97] Testing -Dorg.lwjgl.glfw.libname=glfw_wayland --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index f4eb9f6..20ef9aa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,5 +16,5 @@ jobs: java-version: "8" - run: yarn install --frozen-lockfile - run: yarn test - - run: java -Dfml.earlyprogresswindow=false -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignorePatchDiscrepancies=true -Dfml.ignoreInvalidMinecraftCertificates=true -Djava.library.path=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/natives/1.14.4 -Xmx1024M -Xms512M -Xss1M -Dlog4j.configurationFile=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/log4j2_112-116.xml -cp /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/patchy/1.3.9/patchy-1.3.9.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/oshi-project/oshi-core/1.1/oshi-core-1.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/jna/4.4.0/jna-4.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/javabridge/1.0.22/javabridge-1.0.22.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/sf/jopt-simple/jopt-simple/5.0.3/jopt-simple-5.0.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/io/netty/netty-all/4.1.25.Final/netty-all-4.1.25.Final.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/guava/guava/21.0/guava-21.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-io/commons-io/2.5/commons-io-2.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/brigadier/1.0.17/brigadier-1.0.17.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/datafixerupper/2.0.24/datafixerupper-2.0.24.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/code/gson/gson/2.8.0/gson-2.8.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/authlib/1.5.25/authlib-1.5.25.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/it/unimi/dsi/fastutil/8.2.1/fastutil-8.2.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-api/2.8.1/log4j-api-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-core/2.8.1/log4j-core-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl/3.2.2/lwjgl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-jemalloc/3.2.2/lwjgl-jemalloc-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-openal/3.2.2/lwjgl-openal-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-opengl/3.2.2/lwjgl-opengl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-glfw/3.2.2/lwjgl-glfw-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-stb/3.2.2/lwjgl-stb-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/versions/1.14.4/1.14.4.jar net.minecraft.client.main.Main --username Steve --version 1.14.4 --gameDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft --assetsDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/assets --assetIndex 1.14.4 --uuid e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --accessToken e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --userType mojang --versionType release + - run: java -Dorg.lwjgl.glfw.libname=glfw_wayland -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignorePatchDiscrepancies=true -Dfml.ignoreInvalidMinecraftCertificates=true -Djava.library.path=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/natives/1.14.4 -Xmx1024M -Xms512M -Xss1M -Dlog4j.configurationFile=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/log4j2_112-116.xml -cp /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/patchy/1.3.9/patchy-1.3.9.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/oshi-project/oshi-core/1.1/oshi-core-1.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/jna/4.4.0/jna-4.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/javabridge/1.0.22/javabridge-1.0.22.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/sf/jopt-simple/jopt-simple/5.0.3/jopt-simple-5.0.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/io/netty/netty-all/4.1.25.Final/netty-all-4.1.25.Final.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/guava/guava/21.0/guava-21.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-io/commons-io/2.5/commons-io-2.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/brigadier/1.0.17/brigadier-1.0.17.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/datafixerupper/2.0.24/datafixerupper-2.0.24.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/code/gson/gson/2.8.0/gson-2.8.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/authlib/1.5.25/authlib-1.5.25.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/it/unimi/dsi/fastutil/8.2.1/fastutil-8.2.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-api/2.8.1/log4j-api-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-core/2.8.1/log4j-core-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl/3.2.2/lwjgl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-jemalloc/3.2.2/lwjgl-jemalloc-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-openal/3.2.2/lwjgl-openal-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-opengl/3.2.2/lwjgl-opengl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-glfw/3.2.2/lwjgl-glfw-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-stb/3.2.2/lwjgl-stb-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/versions/1.14.4/1.14.4.jar net.minecraft.client.main.Main --username Steve --version 1.14.4 --gameDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft --assetsDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/assets --assetIndex 1.14.4 --uuid e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --accessToken e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --userType mojang --versionType release if: always() From d20479bb03aea347b90dbcd216fda246cb133360 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 23:57:50 +0300 Subject: [PATCH 88/97] Finish with workflows --- .github/workflows/tests.yml | 32 +++++++++---- tests/minecraft.ts | 45 ++++++++++++++++++ tests/vanilla.ts | 91 ------------------------------------- 3 files changed, 69 insertions(+), 99 deletions(-) create mode 100644 tests/minecraft.ts delete mode 100644 tests/vanilla.ts diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 20ef9aa..a028228 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,14 +7,30 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + + - name: Install NodeJS v18 + uses: actions/setup-node@v4 with: node-version: "18.x" - - uses: actions/setup-java@v4 + + - name: Install packages + run: yarn install --frozen-lockfile + + - name: Run Vitest + run: yarn test + + prettier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install NodeJS v18 + uses: actions/setup-node@v4 with: - distribution: "temurin" - java-version: "8" - - run: yarn install --frozen-lockfile - - run: yarn test - - run: java -Dorg.lwjgl.glfw.libname=glfw_wayland -XX:-UseAdaptiveSizePolicy -XX:-OmitStackTraceInFastThrow -Dfml.ignorePatchDiscrepancies=true -Dfml.ignoreInvalidMinecraftCertificates=true -Djava.library.path=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/natives/1.14.4 -Xmx1024M -Xms512M -Xss1M -Dlog4j.configurationFile=/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/log4j2_112-116.xml -cp /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/patchy/1.3.9/patchy-1.3.9.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/oshi-project/oshi-core/1.1/oshi-core-1.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/jna/4.4.0/jna-4.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/dev/jna/platform/3.4.0/platform-3.4.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/ibm/icu/icu4j-core-mojang/51.2/icu4j-core-mojang-51.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/javabridge/1.0.22/javabridge-1.0.22.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/sf/jopt-simple/jopt-simple/5.0.3/jopt-simple-5.0.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/io/netty/netty-all/4.1.25.Final/netty-all-4.1.25.Final.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/guava/guava/21.0/guava-21.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-lang3/3.5/commons-lang3-3.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-io/commons-io/2.5/commons-io-2.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-codec/commons-codec/1.10/commons-codec-1.10.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/net/java/jutils/jutils/1.0.0/jutils-1.0.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/brigadier/1.0.17/brigadier-1.0.17.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/datafixerupper/2.0.24/datafixerupper-2.0.24.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/google/code/gson/gson/2.8.0/gson-2.8.0.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/authlib/1.5.25/authlib-1.5.25.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/commons/commons-compress/1.8.1/commons-compress-1.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/httpcomponents/httpcore/4.3.2/httpcore-4.3.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/it/unimi/dsi/fastutil/8.2.1/fastutil-8.2.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-api/2.8.1/log4j-api-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/apache/logging/log4j/log4j-core/2.8.1/log4j-core-2.8.1.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl/3.2.2/lwjgl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-jemalloc/3.2.2/lwjgl-jemalloc-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-openal/3.2.2/lwjgl-openal-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-opengl/3.2.2/lwjgl-opengl-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-glfw/3.2.2/lwjgl-glfw-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/org/lwjgl/lwjgl-stb/3.2.2/lwjgl-stb-3.2.2.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/libraries/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar:/home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/versions/1.14.4/1.14.4.jar net.minecraft.client.main.Main --username Steve --version 1.14.4 --gameDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft --assetsDir /home/runner/work/minecraft-utils-pierce/minecraft-utils-pierce/minecraft/assets --assetIndex 1.14.4 --uuid e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --accessToken e9df5bd1-28bb-31c6-8eb0-4ad41f47d874 --userType mojang --versionType release - if: always() + node-version: "18.x" + + - name: Install packages + run: yarn install --frozen-lockfile + + - name: Run Prettier + run: yarn prettier diff --git a/tests/minecraft.ts b/tests/minecraft.ts new file mode 100644 index 0000000..42c5ab1 --- /dev/null +++ b/tests/minecraft.ts @@ -0,0 +1,45 @@ +import { ChildProcessWithoutNullStreams } from 'node:child_process'; +import { existsSync, rmdirSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { afterAll, describe, expect, test } from 'vitest'; +import { Client } from '../src'; + +describe('Minecraft 1.8.9', () => { + const client = new Client({ + version: { + number: '1.8.9', + type: 'release', + }, + }); + + test( + 'Installation', + async () => { + await client.install(); + expect(existsSync(resolve('./minecraft/natives/1.8.9'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.jar'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.json'))).toBe(true); + }, + 3 * 60 * 1000, + ); +}); + +describe('Minecraft 1.14.4', () => { + const client = new Client({ + version: { + number: '1.14.4', + type: 'release', + }, + }); + + test( + 'Installation', + async () => { + await client.install(); + expect(existsSync(resolve('./minecraft/natives/1.14.4'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.jar'))).toBe(true); + expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.json'))).toBe(true); + }, + 3 * 60 * 1000, + ); +}); diff --git a/tests/vanilla.ts b/tests/vanilla.ts deleted file mode 100644 index aabb57c..0000000 --- a/tests/vanilla.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { ChildProcessWithoutNullStreams } from 'node:child_process'; -import { existsSync, rmdirSync } from 'node:fs'; -import { resolve } from 'node:path'; -import { afterAll, describe, expect, test } from 'vitest'; -import { Client } from '../src'; - -describe('Minecraft Vanilla Legacy (1.8.9)', () => { - const client = new Client({ - version: { - number: '1.8.9', - type: 'release', - }, - }); - - test( - 'Installation', - async () => { - await client.install(); - expect(existsSync(resolve('./minecraft/natives/1.8.9'))).toBe(true); - expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.jar'))).toBe(true); - expect(existsSync(resolve('./minecraft/versions/1.8.9/1.8.9.json'))).toBe(true); - }, - 3 * 60 * 1000, - ); - - test( - 'Starting', - async () => { - const process = await client.start(); - expect(process && typeof process.kill === 'function').toBe(true); - await new Promise((resolve) => { - setTimeout(() => { - (process as ChildProcessWithoutNullStreams).kill(); - resolve(); - }, 10 * 1000); - }); - expect(existsSync(resolve('./minecraft/saves'))).toBe(true); - expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); - }, - 3 * 60 * 1000, - ); - - // Cleanup for other tests - afterAll(() => { - rmdirSync(resolve('./minecraft/saves')); - rmdirSync(resolve('./minecraft/resourcepacks')); - }); -}); - -describe('Minecraft Vanilla Modern (1.14.4)', () => { - const client = new Client({ - version: { - number: '1.14.4', - type: 'release', - }, - }); - - test( - 'Installation', - async () => { - await client.install(); - expect(existsSync(resolve('./minecraft/natives/1.14.4'))).toBe(true); - expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.jar'))).toBe(true); - expect(existsSync(resolve('./minecraft/versions/1.14.4/1.14.4.json'))).toBe(true); - }, - 3 * 60 * 1000, - ); - - test( - 'Starting', - async () => { - const process = await client.start(); - expect(process && typeof process.kill === 'function').toBe(true); - await new Promise((resolve) => { - setTimeout(() => { - (process as ChildProcessWithoutNullStreams).kill(); - resolve(); - }, 10 * 1000); - }); - expect(existsSync(resolve('./minecraft/saves'))).toBe(true); - expect(existsSync(resolve('./minecraft/resourcepacks'))).toBe(true); - }, - 3 * 60 * 1000, - ); - - // Cleanup for other tests - afterAll(() => { - rmdirSync(resolve('./minecraft/saves')); - rmdirSync(resolve('./minecraft/resourcepacks')); - }); -}); From 708687125c18927d996b1b6ac5b7a588ba6062c9 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 7 May 2024 23:58:37 +0300 Subject: [PATCH 89/97] Remove unused imports --- tests/minecraft.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/minecraft.ts b/tests/minecraft.ts index 42c5ab1..f1e2f81 100644 --- a/tests/minecraft.ts +++ b/tests/minecraft.ts @@ -1,7 +1,6 @@ -import { ChildProcessWithoutNullStreams } from 'node:child_process'; -import { existsSync, rmdirSync } from 'node:fs'; +import { existsSync } from 'node:fs'; import { resolve } from 'node:path'; -import { afterAll, describe, expect, test } from 'vitest'; +import { describe, expect, test } from 'vitest'; import { Client } from '../src'; describe('Minecraft 1.8.9', () => { From 2125f3e42f3d621b18dfcc35efa2ac8c05f8896b Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 12 Jun 2024 00:18:23 +0300 Subject: [PATCH 90/97] Proper LICENSE update my bad --- LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 9059f3e..1a65842 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 Pierce Harriz +Copyright (c) 2019-2024 Pierce Harriz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. \ No newline at end of file +SOFTWARE. From 652392bead666ea6debeab852e409736161e3c01 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 12 Jun 2024 00:22:13 +0300 Subject: [PATCH 91/97] Remove deleted file from .eslintignore --- .eslintignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.eslintignore b/.eslintignore index 85b6a63..707ca87 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,3 @@ tests/ build/ -clean.js -vitest.config.ts \ No newline at end of file +vitest.config.ts From 52579286e16b9c69c3cace286660c74c28109ebb Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 12 Jun 2024 14:47:05 +0300 Subject: [PATCH 92/97] Remove browser env in ESLint config --- .eslintrc.cjs | 1 - 1 file changed, 1 deletion(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index f75825f..9543889 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -7,7 +7,6 @@ module.exports = { tsconfigRootDir: './', }, env: { - browser: true, es6: true, }, plugins: ['prettier', '@typescript-eslint'], From 80e9e4c75e2bb742a38216bd9a0f03ecf4acce85 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 12 Jun 2024 14:47:47 +0300 Subject: [PATCH 93/97] Comment in .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4ef9888..20f41bb 100644 --- a/.gitignore +++ b/.gitignore @@ -66,4 +66,5 @@ typings/ # IntelliJ Files .idea/ -minecraft/ \ No newline at end of file +# Minecraft folder +minecraft/ From 80242d239f5d7c0190dfe59de88f13de8865c370 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 12 Jun 2024 14:48:27 +0300 Subject: [PATCH 94/97] Remove JSX from Prettier config --- .prettierrc.json | 1 - 1 file changed, 1 deletion(-) diff --git a/.prettierrc.json b/.prettierrc.json index 0514d38..ac020d9 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -4,7 +4,6 @@ "useTabs": false, "semi": true, "singleQuote": true, - "jsxSingleQuote": true, "endOfLine": "lf", "plugins": ["@ianvs/prettier-plugin-sort-imports"] } From 7ecba6365a160702d9de50058a2dd87fb27e0439 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 12 Jun 2024 15:05:43 +0300 Subject: [PATCH 95/97] Remove unused type and add default for maxSockets --- src/types/Options.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/types/Options.ts b/src/types/Options.ts index 745210c..8346ea9 100644 --- a/src/types/Options.ts +++ b/src/types/Options.ts @@ -130,10 +130,6 @@ export default interface Options { */ path?: string; }; - /** - * The amount of launch arguments specified in the version file before it adds the default again - */ - minArgs?: number; minecraftJar?: string; versionJson?: string; versionName?: string; @@ -159,7 +155,7 @@ export default interface Options { */ classes?: Array; /** - * Max sockets for downloadAsync. + * Max sockets for downloadAsync. Defaults is Infinity */ maxSockets?: number; /** From 3b330b1196dcbfa605224d0f8cfdb7368839d591 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Wed, 12 Jun 2024 15:07:14 +0300 Subject: [PATCH 96/97] Array -> string[] --- src/types/Options.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/types/Options.ts b/src/types/Options.ts index 8346ea9..79329d2 100644 --- a/src/types/Options.ts +++ b/src/types/Options.ts @@ -23,15 +23,15 @@ export default interface Options { /** * Array of custom Minecraft arguments. */ - customLaunchArgs?: Array; + customLaunchArgs?: string[]; /** * Array of custom Java arguments */ - customArgs?: Array; + customArgs?: string[]; /** * Array of game argument feature flags */ - features?: Array; + features?: string[]; /** * minecraft version info */ @@ -153,7 +153,7 @@ export default interface Options { * List of classes. * All class paths are required if you use this. */ - classes?: Array; + classes?: string[]; /** * Max sockets for downloadAsync. Defaults is Infinity */ From 9afafe028ae97fc623464489a2bf8b72761bdf80 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Tue, 13 Aug 2024 23:06:29 +0300 Subject: [PATCH 97/97] forgot about this 1 --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9a964e4..707b82a 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ const client = new Client({ }); await client.install(); -await client.launch(); +await client.start(); onLog('debug', (e) => console.log(e)); onLog('data', (e) => console.log(e)); @@ -69,7 +69,7 @@ const client = new Client({ }); await client.install(); -await client.launch(); +await client.start(); onLog('debug', (e) => console.log(e)); onLog('data', (e) => console.log(e)); @@ -96,7 +96,7 @@ const client = new Client({ }); await client.install(); -await client.launch(); +await client.start(); onLog('debug', (e) => console.log(e)); onLog('data', (e) => console.log(e));