├── .eslintrc.json ├── .gitattributes ├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── components ├── authenticator.js ├── handler.js └── launcher.js ├── index.d.ts ├── index.js ├── package-lock.json └── package.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true 6 | }, 7 | "extends": [ 8 | "standard" 9 | ], 10 | "globals": { 11 | "Atomics": "readonly", 12 | "SharedArrayBuffer": "readonly" 13 | }, 14 | "parserOptions": { 15 | "ecmaVersion": 2018 16 | }, 17 | "rules": { 18 | "camelcase": "off", 19 | "no-template-curly-in-string": "off" 20 | } 21 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: Pierce01 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # configs 2 | config.json 3 | 4 | # Logs 5 | logs 6 | *.log 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # Coverage directory used by tools like istanbul 21 | coverage 22 | 23 | # nyc test coverage 24 | .nyc_output 25 | 26 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 27 | .grunt 28 | 29 | # Bower dependency directory (https://bower.io/) 30 | bower_components 31 | 32 | # node-waf configuration 33 | .lock-wscript 34 | 35 | # Compiled binary addons (http://nodejs.org/api/addons.html) 36 | build/Release 37 | 38 | # Dependency directories 39 | node_modules/ 40 | jspm_packages/ 41 | 42 | # Typescript v1 declaration files 43 | typings/ 44 | 45 | # Optional npm cache directory 46 | .npm 47 | 48 | # Optional eslint cache 49 | .eslintcache 50 | 51 | # Optional REPL history 52 | .node_repl_history 53 | 54 | # Output of 'npm pack' 55 | *.tgz 56 | 57 | # Yarn Integrity file 58 | .yarn-integrity 59 | 60 | # dotenv environment variables file 61 | .env 62 | 63 | # VSCode Files (https://code.visualstudio.com) 64 | .vscode/ 65 | 66 | # IntelliJ Files 67 | .idea/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Pierce Harriz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![logo](https://owo.whats-th.is/8mT5kxc.png) 2 | ##### Project rewrite coming soon™ 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | ![version](https://img.shields.io/badge/stable_version-3.18.2-blue) 5 | 6 | MCLC (Minecraft Launcher Core) is a NodeJS solution for launching modded and vanilla Minecraft without having to download and format everything yourself. 7 | Basically a core for your Electron or script based launchers. 8 | 9 | ### Getting support 10 | I've created a Discord server for anyone who needs to get in contact with me or get help! 11 |

12 | 13 | chat on Discord 15 |

16 | 17 | ### Installing 18 | 19 | `npm i minecraft-launcher-core` 20 | 21 | ### Standard Example 22 | ```javascript 23 | const { Client, Authenticator } = require('minecraft-launcher-core'); 24 | const launcher = new Client(); 25 | 26 | let opts = { 27 | // For production launchers, I recommend not passing 28 | // the getAuth function through the authorization field and instead 29 | // handling authentication outside before you initialize 30 | // MCLC so you can handle auth based errors and validation! 31 | authorization: Authenticator.getAuth("username", "password"), 32 | root: "./minecraft", 33 | version: { 34 | number: "1.14", 35 | type: "release" 36 | }, 37 | memory: { 38 | max: "6G", 39 | min: "4G" 40 | } 41 | } 42 | 43 | launcher.launch(opts); 44 | 45 | launcher.on('debug', (e) => console.log(e)); 46 | launcher.on('data', (e) => console.log(e)); 47 | ``` 48 | ### Documentation 49 | 50 | #### Client Functions 51 | 52 | | Function | Type | Description | 53 | |----------|---------|-----------------------------------------------------------------------------------------| 54 | | `launch` | Promise | Launches the client with the specified `options` as a parameter. Returns child the process | 55 | 56 | ##### launch 57 | 58 | | Parameter | Type | Description | Required | 59 | |--------------------------|----------|-------------------------------------------------------------------------------------------|----------| 60 | | `options.clientPackage` | String | Path or URL to a zip file, which will be extracted to the root directory. (Not recommended for production use)| False | 61 | | `options.removePackage` | Boolean | Option to remove the client package zip file after its finished extracting. | False | 62 | | `options.root` | String | Path where you want the launcher to work in. `C:/Users/user/AppData/Roaming/.mc` | True | 63 | | `options.cache` | String | Path where launcher files will be cached in. `C:/Users/user/AppData/Roaming/.mc/cache` | False | 64 | | `options.os` | String | windows, osx or linux. MCLC will auto determine the OS if this field isn't provided. | False | 65 | | `options.customLaunchArgs`| Array | Array of custom Minecraft arguments you want to add. | False | 66 | | `options.customArgs` | Array | Array of custom Java arguments you want to add. | False | 67 | | `options.features` | Array | Array of game argument feature flags. ex: `is_demo_user` or `has_custom_resolution` | False | 68 | | `options.version.number` | String | Minecraft version that is going to be launched. | True | 69 | | `options.version.type` | String | Any string. The actual Minecraft launcher uses `release` and `snapshot`. | True | 70 | | `options.version.custom` | String | The name of the folder, jar file, and version json in the version folder. | False | 71 | | `options.memory.max` | String | Max amount of memory being used by Minecraft. | True | 72 | | `options.memory.min` | String | Min amount of memory being used by Minecraft. | True | 73 | | `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 | 74 | | `options.javaPath` | String | Path to the JRE executable file, will default to `java` if not entered. | False | 75 | | `options.quickPlay.type` | String | The type of the quickPlay session. `singleplayer`, `multiplayer`, `realms`, `legacy` | False | 76 | | `options.quickPlay.identifier` | String | The folder name, server address, or realm ID, relating to the specified type. `legacy` follows `multiplayer` format. | False | 77 | | `options.quickPlay.path` | String | The specified path for logging (relative to the run directory) | False | 78 | | `options.proxy.host` | String | Host url to the proxy, don't include the port. | False | 79 | | `options.proxy.port` | String | Port of the host proxy, will default to `8080` if not entered. | False | 80 | | `options.proxy.username` | String | Username for the proxy. | False | 81 | | `options.proxy.password` | String | Password for the proxy. | False | 82 | | `options.timeout` | Integer | Timeout on download requests. | False | 83 | | `options.window.width` | String | Width of the Minecraft Client. | False | 84 | | `options.window.height` | String | Height of the Minecraft Client. | False | 85 | | `options.window.fullscreen`| Boolean| Fullscreen the Minecraft Client. | False | 86 | | `options.overrides` | Object | Json object redefining paths for better customization. Example below. | False | 87 | #### IF YOU'RE NEW TO MCLC, LET IT HANDLE EVERYTHING! DO NOT USE OVERRIDES! 88 | ```js 89 | let opts = { 90 | otherOps..., 91 | overrides: { 92 | gameDirectory: '', // where the game process generates folders like saves and resource packs. 93 | minecraftJar: '', 94 | versionName: '', // replaces the value after the version flag. 95 | versionJson: '', 96 | directory: '', // where the Minecraft jar and version json are located. 97 | natives: '', // native directory path. 98 | assetRoot: '', 99 | assetIndex: '', 100 | libraryRoot: '', 101 | cwd: '', // working directory of the java process. 102 | detached: true, // whether or not the client is detached from the parent / launcher. 103 | classes: [], // all class paths are required if you use this. 104 | minArgs: 11, // The amount of launch arguments specified in the version file before it adds the default again 105 | maxSockets: 2, // max sockets for downloadAsync. 106 | // The following is for launcher developers located in countries that have the Minecraft and Forge resource servers 107 | // blocked for what ever reason. They obviously need to mirror the formatting of the original JSONs / file structures. 108 | url: { 109 | meta: 'https://launchermeta.mojang.com', // List of versions. 110 | resource: 'https://resources.download.minecraft.net', // Minecraft resources. 111 | mavenForge: 'http://files.minecraftforge.net/maven/', // Forge resources. 112 | defaultRepoForge: 'https://libraries.minecraft.net/', // for Forge only, you need to redefine the library url 113 | // in the version json. 114 | fallbackMaven: 'https://search.maven.org/remotecontent?filepath=' 115 | }, 116 | // The following is options for which version of ForgeWrapper MCLC uses. This allows us to launch modern Forge. 117 | fw: { 118 | baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', 119 | version: '1.5.1', 120 | sh1: '90104e9aaa8fbedf6c3d1f6d0b90cabce080b5a9', 121 | size: 29892, 122 | }, 123 | logj4ConfigurationFile: '' 124 | } 125 | } 126 | ``` 127 | 128 | #### Notes 129 | ##### Custom 130 | 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. 131 | 132 | #### Authentication (Deprecated) 133 | 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. 134 | ```js 135 | { 136 | access_token: '', 137 | client_token: '', 138 | uuid: '', 139 | name: '', 140 | user_properties: '{}', 141 | meta: { 142 | type: 'mojang' || 'msa', 143 | demo: true || false, // Demo can also be specified by adding 'is_demo_user' to the options.feature array 144 | // properties only exists for specific Minecraft versions. 145 | xuid: '', 146 | clientId: '' 147 | } 148 | } 149 | ``` 150 | 151 | #### Authenticator Functions 152 | 153 | ##### getAuth 154 | 155 | | Parameter | Type | Description | Required | 156 | |-----------|--------|--------------------------------------------------------------|----------| 157 | | `username`| String | Email or username | True | 158 | | `password`| String | Password for the Mojang account being used if online mode. | False | 159 | | `client_token`| String | Client token that will be used. If one is not specified, one will be generated | False | 160 | 161 | ##### validate 162 | 163 | | Parameter | Type | Description | Required | 164 | |--------------|--------|-------------------------------------------------------------------|----------| 165 | | `access_token` | String | Token being checked if it can be used to login with (online mode). | True | 166 | | `client_token` | String | Client token being checked to see if there was a change of client (online mode). | True | 167 | 168 | ##### refreshAuth 169 | 170 | | Parameter | Type | Description | Required | 171 | |--------------------|--------|-------------------------------------------------------------------------------------|----------| 172 | | `access_token` | String | Token being checked if it can be used to login with (online mode). | True | 173 | | `client_token` | String | Token being checked if it's the same client that the access_token was created from. | True | 174 | 175 | ##### invalidate 176 | 177 | | Parameter | Type | Description | Required | 178 | |--------------|--------|-------------------------------------------------------------------|----------| 179 | | `access_token` | String | Token being checked if it can be used to login with (online mode). | True | 180 | | `client_token` | String | Token being checked if it's the same client that the access_token was created from. | True | 181 | 182 | ##### signOut 183 | 184 | | Parameter | Type | Description | Required | 185 | |--------------|--------|--------------------------------------|----------| 186 | | `username` | String | Username used to login with | True | 187 | | `password` | String | Password used to login with | True | 188 | 189 | ##### changeApiUrl 190 | 191 | | Parameter | Type | Description | Required | 192 | |-----------|--------|--------------------------------------------------------------|----------| 193 | | `url` | String | New URL that MCLC will make calls to authenticate the login. | True | 194 | 195 | #### Events 196 | 197 | | Event Name | Type | Description | 198 | |-------------------|---------|---------------------------------------------------------------------------------------| 199 | | `arguments` | Object | Emitted when launch arguments are set for the Minecraft Jar. | 200 | | `data` | String | Emitted when information is returned from the Minecraft Process | 201 | | `close` | Integer | Code number that is returned by the Minecraft Process | 202 | | `package-extract` | null | Emitted when `clientPackage` finishes being extracted | 203 | | `download` | String | Emitted when a file successfully downloads | 204 | | `download-status` | Object | Emitted when data is received while downloading | 205 | | `debug` | String | Emitted when functions occur, made to help debug if errors occur | 206 | | `progress` | Object | Emitted when files are being downloaded in order. (Assets, Forge, Natives, Classes) | 207 | 208 | 209 | #### What should it look like running from console? 210 | The `pid` is printed in console after the process is launched. 211 | ![gif](https://owo.whats-th.is/3N3PMC4.gif) 212 | 213 | ## Contributors 214 | These are the people that helped out that aren't listed [here](https://github.com/Pierce01/MinecraftLauncher-core/graphs/contributors)! 215 | * [Pyker](https://github.com/Pyker) - Forge dependency parsing. 216 | * [Khionu](https://github.com/khionu) - Research on how Minecraft's`natives` are handled. 217 | * [Coding-Kiwi](https://github.com/Coding-Kiwi) - Pointed out I didn't pass `clientToken` in initial authentication function. 218 | * maxbsoft - Pointed out that a certain JVM option causes OSX Minecraft to bug out. 219 | * [Noé](https://github.com/NoXeDev) - Pointed out launch args weren't being passed for Forge 1.13+. 220 | -------------------------------------------------------------------------------- /components/authenticator.js: -------------------------------------------------------------------------------- 1 | const request = require('request') 2 | const { v3 } = require('uuid') 3 | 4 | let uuid 5 | let api_url = 'https://authserver.mojang.com' 6 | 7 | module.exports.getAuth = function (username, password, client_token = null) { 8 | return new Promise((resolve, reject) => { 9 | getUUID(username) 10 | if (!password) { 11 | const user = { 12 | access_token: uuid, 13 | client_token: client_token || uuid, 14 | uuid, 15 | name: username, 16 | user_properties: '{}' 17 | } 18 | 19 | return resolve(user) 20 | } 21 | 22 | const requestObject = { 23 | url: api_url + '/authenticate', 24 | json: { 25 | agent: { 26 | name: 'Minecraft', 27 | version: 1 28 | }, 29 | username, 30 | password, 31 | clientToken: uuid, 32 | requestUser: true 33 | } 34 | } 35 | 36 | request.post(requestObject, function (error, response, body) { 37 | if (error) return reject(error) 38 | if (!body || !body.selectedProfile) { 39 | return reject(new Error('Validation error: ' + response.statusMessage)) 40 | } 41 | 42 | const userProfile = { 43 | access_token: body.accessToken, 44 | client_token: body.clientToken, 45 | uuid: body.selectedProfile.id, 46 | name: body.selectedProfile.name, 47 | selected_profile: body.selectedProfile, 48 | user_properties: parsePropts(body.user.properties) 49 | } 50 | 51 | resolve(userProfile) 52 | }) 53 | }) 54 | } 55 | 56 | module.exports.validate = function (accessToken, clientToken) { 57 | return new Promise((resolve, reject) => { 58 | const requestObject = { 59 | url: api_url + '/validate', 60 | json: { 61 | accessToken, 62 | clientToken 63 | } 64 | } 65 | 66 | request.post(requestObject, async function (error, response, body) { 67 | if (error) return reject(error) 68 | 69 | if (!body) resolve(true) 70 | else reject(body) 71 | }) 72 | }) 73 | } 74 | 75 | module.exports.refreshAuth = function (accessToken, clientToken) { 76 | return new Promise((resolve, reject) => { 77 | const requestObject = { 78 | url: api_url + '/refresh', 79 | json: { 80 | accessToken, 81 | clientToken, 82 | requestUser: true 83 | } 84 | } 85 | 86 | request.post(requestObject, function (error, response, body) { 87 | if (error) return reject(error) 88 | if (!body || !body.selectedProfile) { 89 | return reject(new Error('Validation error: ' + response.statusMessage)) 90 | } 91 | 92 | const userProfile = { 93 | access_token: body.accessToken, 94 | client_token: getUUID(body.selectedProfile.name), 95 | uuid: body.selectedProfile.id, 96 | name: body.selectedProfile.name, 97 | user_properties: parsePropts(body.user.properties) 98 | } 99 | 100 | return resolve(userProfile) 101 | }) 102 | }) 103 | } 104 | 105 | module.exports.invalidate = function (accessToken, clientToken) { 106 | return new Promise((resolve, reject) => { 107 | const requestObject = { 108 | url: api_url + '/invalidate', 109 | json: { 110 | accessToken, 111 | clientToken 112 | } 113 | } 114 | 115 | request.post(requestObject, function (error, response, body) { 116 | if (error) return reject(error) 117 | 118 | if (!body) return resolve(true) 119 | else return reject(body) 120 | }) 121 | }) 122 | } 123 | 124 | module.exports.signOut = function (username, password) { 125 | return new Promise((resolve, reject) => { 126 | const requestObject = { 127 | url: api_url + '/signout', 128 | json: { 129 | username, 130 | password 131 | } 132 | } 133 | 134 | request.post(requestObject, function (error, response, body) { 135 | if (error) return reject(error) 136 | 137 | if (!body) return resolve(true) 138 | else return reject(body) 139 | }) 140 | }) 141 | } 142 | 143 | module.exports.changeApiUrl = function (url) { 144 | api_url = url 145 | } 146 | 147 | function parsePropts (array) { 148 | if (array) { 149 | const newObj = {} 150 | for (const entry of array) { 151 | if (newObj[entry.name]) { 152 | newObj[entry.name].push(entry.value) 153 | } else { 154 | newObj[entry.name] = [entry.value] 155 | } 156 | } 157 | return JSON.stringify(newObj) 158 | } else { 159 | return '{}' 160 | } 161 | } 162 | 163 | function getUUID (value) { 164 | if (!uuid) { 165 | uuid = v3(value, v3.DNS) 166 | } 167 | return uuid 168 | } 169 | -------------------------------------------------------------------------------- /components/handler.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const request = require('request') 4 | const checksum = require('checksum') 5 | const Zip = require('adm-zip') 6 | const child = require('child_process') 7 | let counter = 0 8 | 9 | class Handler { 10 | constructor (client) { 11 | this.client = client 12 | this.options = client.options 13 | this.baseRequest = request.defaults({ 14 | pool: { maxSockets: this.options.overrides.maxSockets || 2 }, 15 | timeout: this.options.timeout || 50000 16 | }) 17 | } 18 | 19 | checkJava (java) { 20 | return new Promise(resolve => { 21 | child.exec(`"${java}" -version`, (error, stdout, stderr) => { 22 | if (error) { 23 | resolve({ 24 | run: false, 25 | message: error 26 | }) 27 | } else { 28 | this.client.emit('debug', `[MCLC]: Using Java version ${stderr.match(/"(.*?)"/).pop()} ${stderr.includes('64-Bit') ? '64-bit' : '32-Bit'}`) 29 | resolve({ 30 | run: true 31 | }) 32 | } 33 | }) 34 | }) 35 | } 36 | 37 | downloadAsync (url, directory, name, retry, type) { 38 | return new Promise(resolve => { 39 | fs.mkdirSync(directory, { recursive: true }) 40 | 41 | const _request = this.baseRequest(url) 42 | 43 | let receivedBytes = 0 44 | let totalBytes = 0 45 | 46 | _request.on('response', (data) => { 47 | if (data.statusCode === 404) { 48 | this.client.emit('debug', `[MCLC]: Failed to download ${url} due to: File not found...`) 49 | return resolve(false) 50 | } 51 | 52 | totalBytes = parseInt(data.headers['content-length']) 53 | }) 54 | 55 | _request.on('error', async (error) => { 56 | this.client.emit('debug', `[MCLC]: Failed to download asset to ${path.join(directory, name)} due to\n${error}.` + 57 | ` Retrying... ${retry}`) 58 | if (retry) await this.downloadAsync(url, directory, name, false, type) 59 | resolve() 60 | }) 61 | 62 | _request.on('data', (data) => { 63 | receivedBytes += data.length 64 | this.client.emit('download-status', { 65 | name: name, 66 | type: type, 67 | current: receivedBytes, 68 | total: totalBytes 69 | }) 70 | }) 71 | 72 | const file = fs.createWriteStream(path.join(directory, name)) 73 | _request.pipe(file) 74 | 75 | file.once('finish', () => { 76 | this.client.emit('download', name) 77 | resolve({ 78 | failed: false, 79 | asset: null 80 | }) 81 | }) 82 | 83 | file.on('error', async (e) => { 84 | this.client.emit('debug', `[MCLC]: Failed to download asset to ${path.join(directory, name)} due to\n${e}.` + 85 | ` Retrying... ${retry}`) 86 | if (fs.existsSync(path.join(directory, name))) fs.unlinkSync(path.join(directory, name)) 87 | if (retry) await this.downloadAsync(url, directory, name, false, type) 88 | resolve() 89 | }) 90 | }) 91 | } 92 | 93 | checkSum (hash, file) { 94 | return new Promise((resolve, reject) => { 95 | checksum.file(file, (err, sum) => { 96 | if (err) { 97 | this.client.emit('debug', `[MCLC]: Failed to check file hash due to ${err}`) 98 | return resolve(false) 99 | } 100 | return resolve(hash === sum) 101 | }) 102 | }) 103 | } 104 | 105 | getVersion () { 106 | return new Promise(resolve => { 107 | const versionJsonPath = this.options.overrides.versionJson || path.join(this.options.directory, `${this.options.version.number}.json`) 108 | if (fs.existsSync(versionJsonPath)) { 109 | this.version = JSON.parse(fs.readFileSync(versionJsonPath)) 110 | return resolve(this.version) 111 | } 112 | 113 | const manifest = `${this.options.overrides.url.meta}/mc/game/version_manifest.json` 114 | const cache = this.options.cache ? `${this.options.cache}/json` : `${this.options.root}/cache/json` 115 | request.get(manifest, (error, response, body) => { 116 | if (error && error.code !== 'ENOTFOUND') return resolve(error) 117 | if (!error) { 118 | if (!fs.existsSync(cache)) { 119 | fs.mkdirSync(cache, { recursive: true }) 120 | this.client.emit('debug', '[MCLC]: Cache directory created.') 121 | } 122 | fs.writeFile(path.join(`${cache}/version_manifest.json`), body, (err) => { 123 | if (err) return resolve(err) 124 | this.client.emit('debug', '[MCLC]: Cached version_manifest.json') 125 | }) 126 | } 127 | const parsed = (error && error.code === 'ENOTFOUND') 128 | ? JSON.parse(fs.readFileSync(`${cache}/version_manifest.json`)) 129 | : JSON.parse(body) 130 | const desiredVersion = Object.values(parsed.versions).find(version => version.id === this.options.version.number) 131 | if (desiredVersion) { 132 | request.get(desiredVersion.url, (error, response, body) => { 133 | if (error && error.code !== 'ENOTFOUND') throw Error(error) 134 | if (!error) { 135 | fs.writeFile(path.join(`${cache}/${this.options.version.number}.json`), body, (err) => { 136 | if (err) throw Error(err) 137 | this.client.emit('debug', `[MCLC]: Cached ${this.options.version.number}.json`) 138 | }) 139 | } 140 | 141 | this.client.emit('debug', '[MCLC]: Parsed version from version manifest') 142 | this.version = error && error.code === 'ENOTFOUND' 143 | ? JSON.parse(fs.readFileSync(`${cache}/${this.options.version.number}.json`)) 144 | : JSON.parse(body) 145 | return resolve(this.version) 146 | }) 147 | } else { 148 | throw Error(`Failed to find version ${this.options.version.number} in version_manifest.json`) 149 | } 150 | }) 151 | }) 152 | } 153 | 154 | async getJar () { 155 | 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') 156 | fs.writeFileSync(path.join(this.options.directory, `${this.options.version.number}.json`), JSON.stringify(this.version, null, 4)) 157 | return this.client.emit('debug', '[MCLC]: Downloaded version jar and wrote version json') 158 | } 159 | 160 | async getAssets () { 161 | const assetDirectory = path.resolve(this.options.overrides.assetRoot || path.join(this.options.root, 'assets')) 162 | const assetId = this.options.version.custom || this.options.version.number 163 | if (!fs.existsSync(path.join(assetDirectory, 'indexes', `${assetId}.json`))) { 164 | await this.downloadAsync(this.version.assetIndex.url, path.join(assetDirectory, 'indexes'), `${assetId}.json`, true, 'asset-json') 165 | } 166 | 167 | const index = JSON.parse(fs.readFileSync(path.join(assetDirectory, 'indexes', `${assetId}.json`), { encoding: 'utf8' })) 168 | 169 | this.client.emit('progress', { 170 | type: 'assets', 171 | task: 0, 172 | total: Object.keys(index.objects).length 173 | }) 174 | 175 | await Promise.all(Object.keys(index.objects).map(async asset => { 176 | const hash = index.objects[asset].hash 177 | const subhash = hash.substring(0, 2) 178 | const subAsset = path.join(assetDirectory, 'objects', subhash) 179 | 180 | if (!fs.existsSync(path.join(subAsset, hash)) || !await this.checkSum(hash, path.join(subAsset, hash))) { 181 | await this.downloadAsync(`${this.options.overrides.url.resource}/${subhash}/${hash}`, subAsset, hash, true, 'assets') 182 | } 183 | counter++ 184 | this.client.emit('progress', { 185 | type: 'assets', 186 | task: counter, 187 | total: Object.keys(index.objects).length 188 | }) 189 | })) 190 | counter = 0 191 | 192 | // Copy assets to legacy if it's an older Minecraft version. 193 | if (this.isLegacy()) { 194 | if (fs.existsSync(path.join(assetDirectory, 'legacy'))) { 195 | this.client.emit('debug', '[MCLC]: The \'legacy\' directory is no longer used as Minecraft looks ' + 196 | 'for the resouces folder regardless of what is passed in the assetDirecotry launch option. I\'d ' + 197 | `recommend removing the directory (${path.join(assetDirectory, 'legacy')})`) 198 | } 199 | 200 | const legacyDirectory = path.join(this.options.root, 'resources') 201 | this.client.emit('debug', `[MCLC]: Copying assets over to ${legacyDirectory}`) 202 | 203 | this.client.emit('progress', { 204 | type: 'assets-copy', 205 | task: 0, 206 | total: Object.keys(index.objects).length 207 | }) 208 | 209 | await Promise.all(Object.keys(index.objects).map(async asset => { 210 | const hash = index.objects[asset].hash 211 | const subhash = hash.substring(0, 2) 212 | const subAsset = path.join(assetDirectory, 'objects', subhash) 213 | 214 | const legacyAsset = asset.split('/') 215 | legacyAsset.pop() 216 | 217 | if (!fs.existsSync(path.join(legacyDirectory, legacyAsset.join('/')))) { 218 | fs.mkdirSync(path.join(legacyDirectory, legacyAsset.join('/')), { recursive: true }) 219 | } 220 | 221 | if (!fs.existsSync(path.join(legacyDirectory, asset))) { 222 | fs.copyFileSync(path.join(subAsset, hash), path.join(legacyDirectory, asset)) 223 | } 224 | counter++ 225 | this.client.emit('progress', { 226 | type: 'assets-copy', 227 | task: counter, 228 | total: Object.keys(index.objects).length 229 | }) 230 | })) 231 | } 232 | counter = 0 233 | 234 | this.client.emit('debug', '[MCLC]: Downloaded assets') 235 | } 236 | 237 | parseRule (lib) { 238 | if (lib.rules) { 239 | if (lib.rules.length > 1) { 240 | if (lib.rules[0].action === 'allow' && lib.rules[1].action === 'disallow' && lib.rules[1].os.name === 'osx') { 241 | return this.getOS() === 'osx' 242 | } 243 | return true 244 | } else { 245 | if (lib.rules[0].action === 'allow' && lib.rules[0].os) return lib.rules[0].os.name !== this.getOS() 246 | } 247 | } else { 248 | return false 249 | } 250 | } 251 | 252 | async getNatives () { 253 | const nativeDirectory = path.resolve(this.options.overrides.natives || path.join(this.options.root, 'natives', this.version.id)) 254 | 255 | if (parseInt(this.version.id.split('.')[1]) >= 19) return this.options.overrides.cwd || this.options.root 256 | 257 | if (!fs.existsSync(nativeDirectory) || !fs.readdirSync(nativeDirectory).length) { 258 | fs.mkdirSync(nativeDirectory, { recursive: true }) 259 | 260 | const natives = async () => { 261 | const natives = [] 262 | await Promise.all(this.version.libraries.map(async (lib) => { 263 | if (!lib.downloads || !lib.downloads.classifiers) return 264 | if (this.parseRule(lib)) return 265 | 266 | const native = this.getOS() === 'osx' 267 | ? lib.downloads.classifiers['natives-osx'] || lib.downloads.classifiers['natives-macos'] 268 | : lib.downloads.classifiers[`natives-${this.getOS()}`] 269 | 270 | natives.push(native) 271 | })) 272 | return natives 273 | } 274 | const stat = await natives() 275 | 276 | this.client.emit('progress', { 277 | type: 'natives', 278 | task: 0, 279 | total: stat.length 280 | }) 281 | 282 | await Promise.all(stat.map(async (native) => { 283 | if (!native) return 284 | const name = native.path.split('/').pop() 285 | await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives') 286 | if (!await this.checkSum(native.sha1, path.join(nativeDirectory, name))) { 287 | await this.downloadAsync(native.url, nativeDirectory, name, true, 'natives') 288 | } 289 | try { 290 | new Zip(path.join(nativeDirectory, name)).extractAllTo(nativeDirectory, true) 291 | } catch (e) { 292 | // Only doing a console.warn since a stupid error happens. You can basically ignore this. 293 | // if it says Invalid file name, just means two files were downloaded and both were deleted. 294 | // All is well. 295 | console.warn(e) 296 | } 297 | fs.unlinkSync(path.join(nativeDirectory, name)) 298 | counter++ 299 | this.client.emit('progress', { 300 | type: 'natives', 301 | task: counter, 302 | total: stat.length 303 | }) 304 | })) 305 | this.client.emit('debug', '[MCLC]: Downloaded and extracted natives') 306 | } 307 | 308 | counter = 0 309 | this.client.emit('debug', `[MCLC]: Set native path to ${nativeDirectory}`) 310 | 311 | return nativeDirectory 312 | } 313 | 314 | fwAddArgs () { 315 | const forgeWrapperAgrs = [ 316 | `-Dforgewrapper.librariesDir=${path.resolve(this.options.overrides.libraryRoot || path.join(this.options.root, 'libraries'))}`, 317 | `-Dforgewrapper.installer=${this.options.forge}`, 318 | `-Dforgewrapper.minecraft=${this.options.mcPath}` 319 | ] 320 | this.options.customArgs 321 | ? this.options.customArgs = this.options.customArgs.concat(forgeWrapperAgrs) 322 | : this.options.customArgs = forgeWrapperAgrs 323 | } 324 | 325 | isModernForge (json) { 326 | return json.inheritsFrom && json.inheritsFrom.split('.')[1] >= 12 && !(json.inheritsFrom === '1.12.2' && (json.id.split('.')[json.id.split('.').length - 1]) === '2847') 327 | } 328 | 329 | async getForgedWrapped () { 330 | let json = null 331 | let installerJson = null 332 | const versionPath = path.join(this.options.root, 'forge', `${this.version.id}`, 'version.json') 333 | // Since we're building a proper "custom" JSON that will work nativly with MCLC, the version JSON will not 334 | // be re-generated on the next run. 335 | if (fs.existsSync(versionPath)) { 336 | try { 337 | json = JSON.parse(fs.readFileSync(versionPath)) 338 | if (!json.forgeWrapperVersion || !(json.forgeWrapperVersion === this.options.overrides.fw.version)) { 339 | this.client.emit('debug', '[MCLC]: Old ForgeWrapper has generated this version JSON, re-generating') 340 | } else { 341 | // If forge is modern, add ForgeWrappers launch arguments and set forge to null so MCLC treats it as a custom json. 342 | if (this.isModernForge(json)) { 343 | this.fwAddArgs() 344 | this.options.forge = null 345 | } 346 | return json 347 | } 348 | } catch (e) { 349 | console.warn(e) 350 | this.client.emit('debug', '[MCLC]: Failed to parse Forge version JSON, re-generating') 351 | } 352 | } 353 | 354 | this.client.emit('debug', '[MCLC]: Generating Forge version json, this might take a bit') 355 | const zipFile = new Zip(this.options.forge) 356 | json = zipFile.readAsText('version.json') 357 | if (zipFile.getEntry('install_profile.json')) installerJson = zipFile.readAsText('install_profile.json') 358 | 359 | try { 360 | json = JSON.parse(json) 361 | if (installerJson) installerJson = JSON.parse(installerJson) 362 | } catch (e) { 363 | this.client.emit('debug', '[MCLC]: Failed to load json files for ForgeWrapper, using Vanilla instead') 364 | return null 365 | } 366 | // Adding the installer libraries as mavenFiles so MCLC downloads them but doesn't add them to the class paths. 367 | if (installerJson) { 368 | json.mavenFiles 369 | ? json.mavenFiles = json.mavenFiles.concat(installerJson.libraries) 370 | : json.mavenFiles = installerJson.libraries 371 | } 372 | 373 | // Holder for the specifc jar ending which depends on the specifc forge version. 374 | let jarEnding = 'universal' 375 | // We need to handle modern forge differently than legacy. 376 | if (this.isModernForge(json)) { 377 | // If forge is modern and above 1.12.2, we add ForgeWrapper to the libraries so MCLC includes it in the classpaths. 378 | if (json.inheritsFrom !== '1.12.2') { 379 | this.fwAddArgs() 380 | const fwName = `ForgeWrapper-${this.options.overrides.fw.version}.jar` 381 | const fwPathArr = ['io', 'github', 'zekerzhayard', 'ForgeWrapper', this.options.overrides.fw.version] 382 | json.libraries.push({ 383 | name: fwPathArr.join(':'), 384 | downloads: { 385 | artifact: { 386 | path: [...fwPathArr, fwName].join('/'), 387 | url: `${this.options.overrides.fw.baseUrl}${this.options.overrides.fw.version}/${fwName}`, 388 | sha1: this.options.overrides.fw.sh1, 389 | size: this.options.overrides.fw.size 390 | } 391 | } 392 | }) 393 | json.mainClass = 'io.github.zekerzhayard.forgewrapper.installer.Main' 394 | jarEnding = 'launcher' 395 | 396 | // Providing a download URL to the universal jar mavenFile so it can be downloaded properly. 397 | for (const library of json.mavenFiles) { 398 | const lib = library.name.split(':') 399 | if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { 400 | library.downloads.artifact.url = this.options.overrides.url.mavenForge + library.downloads.artifact.path 401 | break 402 | } 403 | } 404 | } else { 405 | // Remove the forge dependent since we're going to overwrite the first entry anyways. 406 | for (const library in json.mavenFiles) { 407 | const lib = json.mavenFiles[library].name.split(':') 408 | if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) { 409 | delete json.mavenFiles[library] 410 | break 411 | } 412 | } 413 | } 414 | } else { 415 | // Modifying legacy library format to play nice with MCLC's downloadToDirectory function. 416 | await Promise.all(json.libraries.map(async library => { 417 | const lib = library.name.split(':') 418 | if (lib[0] === 'net.minecraftforge' && lib[1].includes('forge')) return 419 | 420 | let url = this.options.overrides.url.mavenForge 421 | const name = `${lib[1]}-${lib[2]}.jar` 422 | 423 | if (!library.url) { 424 | if (library.serverreq || library.clientreq) { 425 | url = this.options.overrides.url.defaultRepoForge 426 | } else { 427 | return 428 | } 429 | } 430 | library.url = url 431 | const downloadLink = `${url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}` 432 | // Checking if the file still exists on Forge's server, if not, replace it with the fallback. 433 | // Not checking for sucess, only if it 404s. 434 | this.baseRequest(downloadLink, (error, response, body) => { 435 | if (error) { 436 | this.client.emit('debug', `[MCLC]: Failed checking request for ${downloadLink}`) 437 | } else { 438 | if (response.statusCode === 404) library.url = this.options.overrides.url.fallbackMaven 439 | } 440 | }) 441 | })) 442 | } 443 | // If a downloads property exists, we modify the inital forge entry to include ${jarEnding} so ForgeWrapper can work properly. 444 | // If it doesn't, we simply remove it since we're already providing the universal jar. 445 | if (json.libraries[0].downloads) { 446 | const name = json.libraries[0].name 447 | if (name.includes('minecraftforge:forge') && !name.includes('universal')) { 448 | json.libraries[0].name = name + `:${jarEnding}` 449 | json.libraries[0].downloads.artifact.path = json.libraries[0].downloads.artifact.path.replace('.jar', `-${jarEnding}.jar`) 450 | json.libraries[0].downloads.artifact.url = this.options.overrides.url.mavenForge + json.libraries[0].downloads.artifact.path 451 | } 452 | } else { 453 | delete json.libraries[0] 454 | } 455 | 456 | // Removing duplicates and null types 457 | json.libraries = this.cleanUp(json.libraries) 458 | if (json.mavenFiles) json.mavenFiles = this.cleanUp(json.mavenFiles) 459 | 460 | json.forgeWrapperVersion = this.options.overrides.fw.version 461 | 462 | // Saving file for next run! 463 | if (!fs.existsSync(path.join(this.options.root, 'forge', this.version.id))) { 464 | fs.mkdirSync(path.join(this.options.root, 'forge', this.version.id), { recursive: true }) 465 | } 466 | fs.writeFileSync(versionPath, JSON.stringify(json, null, 4)) 467 | 468 | // Make MCLC treat modern forge as a custom version json rather then legacy forge. 469 | if (this.isModernForge(json)) this.options.forge = null 470 | 471 | return json 472 | } 473 | 474 | async downloadToDirectory (directory, libraries, eventName) { 475 | const libs = [] 476 | 477 | await Promise.all(libraries.map(async library => { 478 | if (!library) return 479 | if (this.parseRule(library)) return 480 | const lib = library.name.split(':') 481 | 482 | let jarPath 483 | let name 484 | if (library.downloads && library.downloads.artifact && library.downloads.artifact.path) { 485 | name = library.downloads.artifact.path.split('/')[library.downloads.artifact.path.split('/').length - 1] 486 | jarPath = path.join(directory, this.popString(library.downloads.artifact.path)) 487 | } else { 488 | name = `${lib[1]}-${lib[2]}${lib[3] ? '-' + lib[3] : ''}.jar` 489 | jarPath = path.join(directory, `${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}`) 490 | } 491 | 492 | const downloadLibrary = async library => { 493 | if (library.url) { 494 | const url = `${library.url}${lib[0].replace(/\./g, '/')}/${lib[1]}/${lib[2]}/${name}` 495 | await this.downloadAsync(url, jarPath, name, true, eventName) 496 | } else if (library.downloads && library.downloads.artifact && library.downloads.artifact.url) { 497 | // Only download if there's a URL provided. If not, we're assuming it's going a generated dependency. 498 | await this.downloadAsync(library.downloads.artifact.url, jarPath, name, true, eventName) 499 | } 500 | } 501 | 502 | if (!fs.existsSync(path.join(jarPath, name))) await downloadLibrary(library) 503 | if (library.downloads && library.downloads.artifact) { 504 | if (!this.checkSum(library.downloads.artifact.sha1, path.join(jarPath, name))) await downloadLibrary(library) 505 | } 506 | 507 | counter++ 508 | this.client.emit('progress', { 509 | type: eventName, 510 | task: counter, 511 | total: libraries.length 512 | }) 513 | libs.push(`${jarPath}${path.sep}${name}`) 514 | })) 515 | counter = 0 516 | 517 | return libs 518 | } 519 | 520 | async getClasses (classJson) { 521 | let libs = [] 522 | 523 | const libraryDirectory = path.resolve(this.options.overrides.libraryRoot || path.join(this.options.root, 'libraries')) 524 | 525 | if (classJson) { 526 | if (classJson.mavenFiles) { 527 | await this.downloadToDirectory(libraryDirectory, classJson.mavenFiles, 'classes-maven-custom') 528 | } 529 | libs = await this.downloadToDirectory(libraryDirectory, classJson.libraries, 'classes-custom') 530 | } 531 | 532 | const parsed = this.version.libraries.filter(lib => { 533 | if (lib.downloads && lib.downloads.artifact && !this.parseRule(lib)) { 534 | if (!classJson || !classJson.libraries.some(l => l.name.split(':')[1] === lib.name.split(':')[1])) { 535 | return true 536 | } 537 | } 538 | return false 539 | }) 540 | 541 | libs = libs.concat((await this.downloadToDirectory(libraryDirectory, parsed, 'classes'))) 542 | counter = 0 543 | 544 | this.client.emit('debug', '[MCLC]: Collected class paths') 545 | return libs 546 | } 547 | 548 | popString (path) { 549 | return path.split('/').slice(0, -1).join('/') 550 | } 551 | 552 | cleanUp (array) { 553 | return [...new Set(Object.values(array).filter(value => value !== null))] 554 | } 555 | 556 | formatQuickPlay () { 557 | const types = { 558 | singleplayer: '--quickPlaySingleplayer', 559 | multiplayer: '--quickPlayMultiplayer', 560 | realms: '--quickPlayRealms', 561 | legacy: null 562 | } 563 | const { type, identifier, path } = this.options.quickPlay 564 | const keys = Object.keys(types) 565 | if (!keys.includes(type)) { 566 | this.client.emit('debug', `[MCLC]: quickPlay type is not valid. Valid types are: ${keys.join(', ')}`) 567 | return null 568 | } 569 | const returnArgs = type === 'legacy' 570 | ? ['--server', identifier.split(':')[0], '--port', identifier.split(':')[1] || '25565'] 571 | : [types[type], identifier] 572 | if (path) returnArgs.push('--quickPlayPath', path) 573 | return returnArgs 574 | } 575 | 576 | async getLaunchOptions (modification) { 577 | const type = Object.assign({}, this.version, modification) 578 | 579 | let args = type.minecraftArguments 580 | ? type.minecraftArguments.split(' ') 581 | : type.arguments.game 582 | const assetRoot = path.resolve(this.options.overrides.assetRoot || path.join(this.options.root, 'assets')) 583 | const assetPath = this.isLegacy() 584 | ? path.join(this.options.root, 'resources') 585 | : path.join(assetRoot) 586 | 587 | const minArgs = this.options.overrides.minArgs || this.isLegacy() ? 5 : 11 588 | if (args.length < minArgs) args = args.concat(this.version.minecraftArguments ? this.version.minecraftArguments.split(' ') : this.version.arguments.game) 589 | if (this.options.customLaunchArgs) args = args.concat(this.options.customLaunchArgs) 590 | 591 | this.options.authorization = await Promise.resolve(this.options.authorization) 592 | this.options.authorization.meta = this.options.authorization.meta ? this.options.authorization.meta : { type: 'mojang' } 593 | const fields = { 594 | '${auth_access_token}': this.options.authorization.access_token, 595 | '${auth_session}': this.options.authorization.access_token, 596 | '${auth_player_name}': this.options.authorization.name, 597 | '${auth_uuid}': this.options.authorization.uuid, 598 | '${auth_xuid}': this.options.authorization.meta.xuid || this.options.authorization.access_token, 599 | '${user_properties}': this.options.authorization.user_properties, 600 | '${user_type}': this.options.authorization.meta.type, 601 | '${version_name}': this.options.version.number || this.options.overrides.versionName, 602 | '${assets_index_name}': this.options.overrides.assetIndex || this.options.version.custom || this.options.version.number, 603 | '${game_directory}': this.options.overrides.gameDirectory || this.options.root, 604 | '${assets_root}': assetPath, 605 | '${game_assets}': assetPath, 606 | '${version_type}': this.options.version.type, 607 | '${clientid}': this.options.authorization.meta.clientId || (this.options.authorization.client_token || this.options.authorization.access_token), 608 | '${resolution_width}': this.options.window ? this.options.window.width : 856, 609 | '${resolution_height}': this.options.window ? this.options.window.height : 482 610 | } 611 | 612 | if (this.options.authorization.meta.demo && (this.options.features ? !this.options.features.includes('is_demo_user') : true)) { 613 | args.push('--demo') 614 | } 615 | 616 | const replaceArg = (obj, index) => { 617 | if (Array.isArray(obj.value)) { 618 | for (const arg of obj.value) { 619 | args.push(arg) 620 | } 621 | } else { 622 | args.push(obj.value) 623 | } 624 | delete args[index] 625 | } 626 | 627 | for (let index = 0; index < args.length; index++) { 628 | if (typeof args[index] === 'object') { 629 | if (args[index].rules) { 630 | if (!this.options.features) continue 631 | const featureFlags = [] 632 | for (const rule of args[index].rules) { 633 | featureFlags.push(...Object.keys(rule.features)) 634 | } 635 | let hasAllRules = true 636 | for (const feature of this.options.features) { 637 | if (!featureFlags.includes(feature)) { 638 | hasAllRules = false 639 | } 640 | } 641 | if (hasAllRules) replaceArg(args[index], index) 642 | } else { 643 | replaceArg(args[index], index) 644 | } 645 | } else { 646 | if (Object.keys(fields).includes(args[index])) { 647 | args[index] = fields[args[index]] 648 | } 649 | } 650 | } 651 | if (this.options.window) { 652 | if (this.options.window.fullscreen) { 653 | args.push('--fullscreen') 654 | } else { 655 | if (this.options.window.width) args.push('--width', this.options.window.width) 656 | if (this.options.window.height) args.push('--height', this.options.window.height) 657 | } 658 | } 659 | if (this.options.server) this.client.emit('debug', '[MCLC]: server and port are deprecated launch flags. Use the quickPlay field.') 660 | if (this.options.quickPlay) args = args.concat(this.formatQuickPlay()) 661 | if (this.options.proxy) { 662 | args.push( 663 | '--proxyHost', 664 | this.options.proxy.host, 665 | '--proxyPort', 666 | this.options.proxy.port || '8080', 667 | '--proxyUser', 668 | this.options.proxy.username, 669 | '--proxyPass', 670 | this.options.proxy.password 671 | ) 672 | } 673 | args = args.filter(value => typeof value === 'string' || typeof value === 'number') 674 | this.client.emit('debug', '[MCLC]: Set launch options') 675 | return args 676 | } 677 | 678 | async getJVM () { 679 | const opts = { 680 | windows: '-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump', 681 | osx: '-XstartOnFirstThread', 682 | linux: '-Xss1M' 683 | } 684 | return opts[this.getOS()] 685 | } 686 | 687 | isLegacy () { 688 | return this.version.assets === 'legacy' || this.version.assets === 'pre-1.6' 689 | } 690 | 691 | getOS () { 692 | if (this.options.os) { 693 | return this.options.os 694 | } else { 695 | switch (process.platform) { 696 | case 'win32': return 'windows' 697 | case 'darwin': return 'osx' 698 | default: return 'linux' 699 | } 700 | } 701 | } 702 | 703 | // To prevent launchers from breaking when they update. Will be reworked with rewrite. 704 | getMemory () { 705 | if (!this.options.memory) { 706 | this.client.emit('debug', '[MCLC]: Memory not set! Setting 1GB as MAX!') 707 | this.options.memory = { 708 | min: 512, 709 | max: 1023 710 | } 711 | } 712 | if (!isNaN(this.options.memory.max) && !isNaN(this.options.memory.min)) { 713 | if (this.options.memory.max < this.options.memory.min) { 714 | this.client.emit('debug', '[MCLC]: MIN memory is higher then MAX! Resetting!') 715 | this.options.memory.max = 1023 716 | this.options.memory.min = 512 717 | } 718 | return [`${this.options.memory.max}M`, `${this.options.memory.min}M`] 719 | } else { return [`${this.options.memory.max}`, `${this.options.memory.min}`] } 720 | } 721 | 722 | async extractPackage (options = this.options) { 723 | if (options.clientPackage.startsWith('http')) { 724 | await this.downloadAsync(options.clientPackage, options.root, 'clientPackage.zip', true, 'client-package') 725 | options.clientPackage = path.join(options.root, 'clientPackage.zip') 726 | } 727 | new Zip(options.clientPackage).extractAllTo(options.root, true) 728 | if (options.removePackage) fs.unlinkSync(options.clientPackage) 729 | 730 | return this.client.emit('package-extract', true) 731 | } 732 | } 733 | 734 | module.exports = Handler 735 | -------------------------------------------------------------------------------- /components/launcher.js: -------------------------------------------------------------------------------- 1 | const child = require('child_process') 2 | const path = require('path') 3 | const Handler = require('./handler') 4 | const fs = require('fs') 5 | const EventEmitter = require('events').EventEmitter 6 | 7 | class MCLCore extends EventEmitter { 8 | async launch (options) { 9 | try { 10 | this.options = { ...options } 11 | this.options.root = path.resolve(this.options.root) 12 | this.options.overrides = { 13 | detached: true, 14 | ...this.options.overrides, 15 | url: { 16 | meta: 'https://launchermeta.mojang.com', 17 | resource: 'https://resources.download.minecraft.net', 18 | mavenForge: 'https://files.minecraftforge.net/maven/', 19 | defaultRepoForge: 'https://libraries.minecraft.net/', 20 | fallbackMaven: 'https://search.maven.org/remotecontent?filepath=', 21 | ...this.options.overrides 22 | ? this.options.overrides.url 23 | : undefined 24 | }, 25 | fw: { 26 | baseUrl: 'https://github.com/ZekerZhayard/ForgeWrapper/releases/download/', 27 | version: '1.6.0', 28 | sh1: '035a51fe6439792a61507630d89382f621da0f1f', 29 | size: 28679, 30 | ...this.options.overrides 31 | ? this.options.overrides.fw 32 | : undefined 33 | } 34 | } 35 | 36 | this.handler = new Handler(this) 37 | 38 | this.printVersion() 39 | 40 | const java = await this.handler.checkJava(this.options.javaPath || 'java') 41 | if (!java.run) { 42 | this.emit('debug', `[MCLC]: Couldn't start Minecraft due to: ${java.message}`) 43 | this.emit('close', 1) 44 | return null 45 | } 46 | 47 | this.createRootDirectory() 48 | this.createGameDirectory() 49 | 50 | await this.extractPackage() 51 | 52 | const directory = this.options.overrides.directory || path.join(this.options.root, 'versions', this.options.version.custom ? this.options.version.custom : this.options.version.number) 53 | this.options.directory = directory 54 | 55 | const versionFile = await this.handler.getVersion() 56 | const mcPath = this.options.overrides.minecraftJar || (this.options.version.custom 57 | ? path.join(this.options.root, 'versions', this.options.version.custom, `${this.options.version.custom}.jar`) 58 | : path.join(directory, `${this.options.version.number}.jar`)) 59 | this.options.mcPath = mcPath 60 | const nativePath = await this.handler.getNatives() 61 | 62 | if (!fs.existsSync(mcPath)) { 63 | this.emit('debug', '[MCLC]: Attempting to download Minecraft version jar') 64 | await this.handler.getJar() 65 | } 66 | 67 | const modifyJson = await this.getModifyJson() 68 | 69 | const args = [] 70 | 71 | let jvm = [ 72 | '-XX:-UseAdaptiveSizePolicy', 73 | '-XX:-OmitStackTraceInFastThrow', 74 | '-Dfml.ignorePatchDiscrepancies=true', 75 | '-Dfml.ignoreInvalidMinecraftCertificates=true', 76 | `-Djava.library.path=${nativePath}`, 77 | `-Xmx${this.handler.getMemory()[0]}`, 78 | `-Xms${this.handler.getMemory()[1]}` 79 | ] 80 | if (this.handler.getOS() === 'osx') { 81 | if (parseInt(versionFile.id.split('.')[1]) > 12) jvm.push(await this.handler.getJVM()) 82 | } else jvm.push(await this.handler.getJVM()) 83 | 84 | if (this.options.customArgs) jvm = jvm.concat(this.options.customArgs) 85 | if (this.options.overrides.logj4ConfigurationFile) { 86 | jvm.push(`-Dlog4j.configurationFile=${path.resolve(this.options.overrides.logj4ConfigurationFile)}`) 87 | } 88 | // https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition 89 | if (parseInt(versionFile.id.split('.')[1]) === 18 && !parseInt(versionFile.id.split('.')[2])) jvm.push('-Dlog4j2.formatMsgNoLookups=true') 90 | if (parseInt(versionFile.id.split('.')[1]) === 17) jvm.push('-Dlog4j2.formatMsgNoLookups=true') 91 | if (parseInt(versionFile.id.split('.')[1]) < 17) { 92 | if (!jvm.find(arg => arg.includes('Dlog4j.configurationFile'))) { 93 | const configPath = path.resolve(this.options.overrides.cwd || this.options.root) 94 | const intVersion = parseInt(versionFile.id.split('.')[1]) 95 | if (intVersion >= 12) { 96 | await this.handler.downloadAsync('https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml', 97 | configPath, 'log4j2_112-116.xml', true, 'log4j') 98 | jvm.push('-Dlog4j.configurationFile=log4j2_112-116.xml') 99 | } else if (intVersion >= 7) { 100 | await this.handler.downloadAsync('https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml', 101 | configPath, 'log4j2_17-111.xml', true, 'log4j') 102 | jvm.push('-Dlog4j.configurationFile=log4j2_17-111.xml') 103 | } 104 | } 105 | } 106 | 107 | const classes = this.options.overrides.classes || this.handler.cleanUp(await this.handler.getClasses(modifyJson)) 108 | const classPaths = ['-cp'] 109 | const separator = this.handler.getOS() === 'windows' ? ';' : ':' 110 | this.emit('debug', `[MCLC]: Using ${separator} to separate class paths`) 111 | // Handling launch arguments. 112 | const file = modifyJson || versionFile 113 | // So mods like fabric work. 114 | const jar = fs.existsSync(mcPath) 115 | ? `${separator}${mcPath}` 116 | : `${separator}${path.join(directory, `${this.options.version.number}.jar`)}` 117 | classPaths.push(`${this.options.forge ? this.options.forge + separator : ''}${classes.join(separator)}${jar}`) 118 | classPaths.push(file.mainClass) 119 | 120 | this.emit('debug', '[MCLC]: Attempting to download assets') 121 | await this.handler.getAssets() 122 | 123 | // Forge -> Custom -> Vanilla 124 | const launchOptions = await this.handler.getLaunchOptions(modifyJson) 125 | 126 | const launchArguments = args.concat(jvm, classPaths, launchOptions) 127 | this.emit('arguments', launchArguments) 128 | this.emit('debug', `[MCLC]: Launching with arguments ${launchArguments.join(' ')}`) 129 | 130 | return this.startMinecraft(launchArguments) 131 | } catch (e) { 132 | this.emit('debug', `[MCLC]: Failed to start due to ${e}, closing...`) 133 | return null 134 | } 135 | } 136 | 137 | printVersion () { 138 | if (fs.existsSync(path.join(__dirname, '..', 'package.json'))) { 139 | const { version } = require('../package.json') 140 | this.emit('debug', `[MCLC]: MCLC version ${version}`) 141 | } else { this.emit('debug', '[MCLC]: Package JSON not found, skipping MCLC version check.') } 142 | } 143 | 144 | createRootDirectory () { 145 | if (!fs.existsSync(this.options.root)) { 146 | this.emit('debug', '[MCLC]: Attempting to create root folder') 147 | fs.mkdirSync(this.options.root) 148 | } 149 | } 150 | 151 | createGameDirectory () { 152 | if (this.options.overrides.gameDirectory) { 153 | this.options.overrides.gameDirectory = path.resolve(this.options.overrides.gameDirectory) 154 | if (!fs.existsSync(this.options.overrides.gameDirectory)) { 155 | fs.mkdirSync(this.options.overrides.gameDirectory, { recursive: true }) 156 | } 157 | } 158 | } 159 | 160 | async extractPackage () { 161 | if (this.options.clientPackage) { 162 | this.emit('debug', `[MCLC]: Extracting client package to ${this.options.root}`) 163 | await this.handler.extractPackage() 164 | } 165 | } 166 | 167 | async getModifyJson () { 168 | let modifyJson = null 169 | 170 | if (this.options.forge) { 171 | this.options.forge = path.resolve(this.options.forge) 172 | this.emit('debug', '[MCLC]: Detected Forge in options, getting dependencies') 173 | modifyJson = await this.handler.getForgedWrapped() 174 | } else if (this.options.version.custom) { 175 | this.emit('debug', '[MCLC]: Detected custom in options, setting custom version file') 176 | modifyJson = modifyJson || JSON.parse(fs.readFileSync(path.join(this.options.root, 'versions', this.options.version.custom, `${this.options.version.custom}.json`), { encoding: 'utf8' })) 177 | } 178 | 179 | return modifyJson 180 | } 181 | 182 | startMinecraft (launchArguments) { 183 | const minecraft = child.spawn(this.options.javaPath ? this.options.javaPath : 'java', launchArguments, 184 | { cwd: this.options.overrides.cwd || this.options.root, detached: this.options.overrides.detached }) 185 | minecraft.stdout.on('data', (data) => this.emit('data', data.toString('utf-8'))) 186 | minecraft.stderr.on('data', (data) => this.emit('data', data.toString('utf-8'))) 187 | minecraft.on('close', (code) => this.emit('close', code)) 188 | return minecraft 189 | } 190 | } 191 | 192 | module.exports = MCLCore 193 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module "minecraft-launcher-core" { 4 | type OS = "windows" | "osx" | "linux"; 5 | 6 | interface IOverrides { 7 | /** 8 | * The amount of launch arguments specified in the version file before it adds the default again 9 | */ 10 | minArgs?: number; 11 | minecraftJar?: string; 12 | versionJson?: string; 13 | versionName?: string; 14 | /** 15 | * Folder, where the game process generates folders like saves and resource packs. 16 | */ 17 | gameDirectory?: string; 18 | /** 19 | * Folder, where the Minecraft jar and version json are located. 20 | */ 21 | directory?: string; 22 | natives?: string; 23 | assetRoot?: string; 24 | assetIndex?: string; 25 | libraryRoot?: string; 26 | /** 27 | * Working directory of the java process. 28 | */ 29 | cwd?: string; 30 | /** 31 | * Whether or not the client is detached from the parent / launcher. 32 | */ 33 | detached?: boolean; 34 | /** 35 | * List of classes. 36 | * All class paths are required if you use this. 37 | */ 38 | classes?: Array; 39 | /** 40 | * Max sockets for downloadAsync. 41 | */ 42 | maxSockets?: number; 43 | /** 44 | * Urls to the Minecraft and Forge resource servers 45 | * 46 | * This is for launcher developers located in countries that have the Minecraft and Forge resource servers 47 | * blocked for what ever reason. They obviously need to mirror the formatting of the original JSONs / file structures. 48 | */ 49 | url?: { 50 | /** 51 | * List of versions. 52 | */ 53 | meta?: string; 54 | /** 55 | * Minecraft resources. 56 | */ 57 | resource?: string; 58 | /** 59 | * Forge resources. 60 | */ 61 | mavenForge?: string; 62 | /** 63 | * for Forge only, you need to redefine the library url in the version json. 64 | */ 65 | defaultRepoForge?: string; 66 | /** 67 | * 68 | */ 69 | fallbackMaven?: string; 70 | }; 71 | /** 72 | * Version of the ForgeWrapper which MCLC uses. This allows us to launch modern Forge. 73 | */ 74 | fw?: { 75 | baseUrl?: string; 76 | version?: string; 77 | sh1?: string; 78 | size?: number; 79 | }; 80 | logj4ConfigurationFile?: string; 81 | } 82 | 83 | interface ILauncherOptions { 84 | /** 85 | * Path or URL to the client package zip file. 86 | */ 87 | clientPackage?: string; 88 | /** 89 | * if true MCLC will remove the client package zip file after its finished extracting. 90 | */ 91 | removePackage?: boolean; 92 | /** 93 | * Path where you want the launcher to work in. 94 | * This will usually be your .minecraft folder 95 | */ 96 | root: string; 97 | /** 98 | * OS override for minecraft natives 99 | * 100 | * @default will autodetect 101 | */ 102 | os?: OS; 103 | /** 104 | * Array of custom Minecraft arguments. 105 | */ 106 | customLaunchArgs?: Array; 107 | /** 108 | * Array of custom Java arguments 109 | */ 110 | customArgs?: Array; 111 | /** 112 | * Array of game argument feature flags 113 | */ 114 | features?: Array; 115 | /** 116 | * minecraft version info 117 | */ 118 | version: { 119 | /** 120 | * Actual version. 121 | * 122 | * @example '1.16.4' 123 | */ 124 | number: string; 125 | /** 126 | * type of release, usually `release` or `snapshot` 127 | */ 128 | type: 'release' | 'snapshot' | string; 129 | /** 130 | * The name of the folder, jar file, and version json in the version folder. 131 | * 132 | * ` MCLC will look in the `versions` folder for this name 133 | * @example '1.16.4-fabric' 134 | */ 135 | custom?: string; 136 | }; 137 | memory: { 138 | /** 139 | * Min amount of memory being used by Minecraft. 140 | */ 141 | max: string | number; 142 | /** 143 | * Max amount of memory being used by Minecraft. 144 | */ 145 | min: string | number; 146 | }; 147 | /** 148 | * Path to Forge Jar. 149 | * 150 | * Versions below 1.13 should be the "universal" jar while versions above 1.13+ should be the "installer" jar 151 | */ 152 | forge?: string; 153 | /** 154 | * Path to the JRE executable file, will default to java if not entered. 155 | */ 156 | javaPath?: string; 157 | proxy?: { 158 | /** 159 | * Host url to the proxy, don't include the port. 160 | */ 161 | host: string; 162 | /** 163 | * Username for the proxy. 164 | * 165 | * @default 8080 166 | */ 167 | port?: string; 168 | /** 169 | * Username for the proxy. 170 | */ 171 | username?: string; 172 | /** 173 | * Password for the proxy. 174 | */ 175 | password?: string; 176 | }; 177 | /** 178 | * Timeout on download requests. 179 | */ 180 | timeout?: number; 181 | window?: { 182 | 183 | /** 184 | * Width of the Minecraft Client 185 | */ 186 | width?: number; 187 | /** 188 | * Height of the Minecraft Client 189 | */ 190 | height?: number; 191 | /** 192 | * Fullscreen the Minecraft Client. 193 | */ 194 | fullscreen?: boolean; 195 | }; 196 | 197 | 198 | /** 199 | * Allows the game to be launched directly into a world 200 | */ 201 | quickPlay?: { 202 | /** 203 | * The type of world you want to join. 204 | * Note, that versions prior to 1.20 only support "legacy" 205 | */ 206 | type: 'singleplayer' | 'multiplayer' | 'realms' | 'legacy'; 207 | /** 208 | * Represents the world you want to join 209 | * 210 | * For singleplayer this should be the folder name of the world 211 | * For multiplayer this should be the IP address of the server 212 | * For realms this should be the Realms ID 213 | * legacy follows multiplayer format 214 | */ 215 | identifier: string; 216 | /** 217 | * The specified path for logging (relative to the run directory) 218 | */ 219 | path?: string; 220 | }; 221 | /** 222 | * Json object redefining paths for better customization 223 | */ 224 | overrides?: IOverrides; 225 | 226 | authorization: Promise | IUser; 227 | /** 228 | * Path of json cache. 229 | */ 230 | cache?: string; 231 | } 232 | 233 | interface IUser { 234 | access_token: string; 235 | client_token: string; 236 | uuid: string; 237 | name: string; 238 | user_properties: Partial; 239 | meta?: { 240 | type: "mojang" | "msa", 241 | demo?: boolean 242 | }; 243 | } 244 | 245 | interface IProfile { 246 | id: number; 247 | name: string; 248 | } 249 | 250 | interface IAuthenticator { 251 | /** 252 | * @param username email if using a password, else the username 253 | * @param password password for mojang account 254 | */ 255 | getAuth(username: string, password?: string): Promise; 256 | /** 257 | * 258 | * @param access_token Token being checked if it can be used to login with (online mode) 259 | * @param client_token Client token being checked to see if there was a change of client (online mode) 260 | */ 261 | validate( 262 | access_token: string, 263 | client_token: string 264 | ): Promise>; 265 | /** 266 | * 267 | * @param access_token Token being checked if it can be used to login with (online mode) 268 | * @param client_token Client token being checked to see if there was a change of client (online mode) 269 | */ 270 | refreshAuth( 271 | access_token: string, 272 | client_token: string, 273 | ): Promise; 274 | /** 275 | * 276 | * @param access_token Token being checked if it can be used to login with (online mode) 277 | * @param client_token Client token being checked to see if there was a change of client (online mode) 278 | */ 279 | invalidate( 280 | access_token: string, 281 | client_token: string 282 | ): Promise>; 283 | /** 284 | * @param username email if using a password, else the username 285 | * @param password password for mojang account 286 | */ 287 | signOut( 288 | username: string, 289 | password: string 290 | ): Promise>; 291 | changeApiUrl(url: string): void; 292 | } 293 | 294 | import { EventEmitter } from 'events' 295 | import { ChildProcessWithoutNullStreams } from 'child_process' 296 | 297 | export class Client extends EventEmitter { 298 | launch(options: ILauncherOptions): Promise; 299 | protected printVersion(): void; 300 | protected createRootDirectory(): void; 301 | protected createGameDirectory(): void; 302 | protected extractPackage(): Promise; 303 | protected getModifyJson(): Promise; 304 | protected startMinecraft(launchArguments: string[]): ChildProcessWithoutNullStreams; 305 | } 306 | 307 | export const Authenticator: IAuthenticator; 308 | } 309 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | Client: require('./components/launcher'), 3 | Authenticator: require('./components/authenticator') 4 | } 5 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "minecraft-launcher-core", 3 | "version": "3.18.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "minecraft-launcher-core", 9 | "version": "3.18.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "adm-zip": "^0.4.13", 13 | "checksum": "^0.1.1", 14 | "request": "^2.88.2", 15 | "uuid": "^8.3.2" 16 | }, 17 | "devDependencies": { 18 | "@types/checksum": "^0.1.35", 19 | "@types/node": "^14.0.27", 20 | "eslint": "^6.8.0", 21 | "eslint-config-standard": "^14.1.1", 22 | "eslint-plugin-import": "^2.20.2", 23 | "eslint-plugin-node": "^11.1.0", 24 | "eslint-plugin-promise": "^4.2.1", 25 | "eslint-plugin-standard": "^4.0.1" 26 | } 27 | }, 28 | "node_modules/@babel/code-frame": { 29 | "version": "7.8.3", 30 | "dev": true, 31 | "license": "MIT", 32 | "dependencies": { 33 | "@babel/highlight": "^7.8.3" 34 | } 35 | }, 36 | "node_modules/@babel/helper-validator-identifier": { 37 | "version": "7.9.5", 38 | "dev": true, 39 | "license": "MIT" 40 | }, 41 | "node_modules/@babel/highlight": { 42 | "version": "7.9.0", 43 | "dev": true, 44 | "license": "MIT", 45 | "dependencies": { 46 | "@babel/helper-validator-identifier": "^7.9.0", 47 | "chalk": "^2.0.0", 48 | "js-tokens": "^4.0.0" 49 | } 50 | }, 51 | "node_modules/@types/checksum": { 52 | "version": "0.1.35", 53 | "resolved": "https://registry.npmjs.org/@types/checksum/-/checksum-0.1.35.tgz", 54 | "integrity": "sha512-Tm3eaZOW4viqdSPa1Y3HFJBqzmTqgChTfeFqBV8Xyevvf3IIG5Uo8WOHFRLhdUTADnz5waK7KC11V+tBfXnqkw==", 55 | "dev": true 56 | }, 57 | "node_modules/@types/color-name": { 58 | "version": "1.1.1", 59 | "dev": true, 60 | "license": "MIT" 61 | }, 62 | "node_modules/@types/node": { 63 | "version": "14.0.27", 64 | "dev": true, 65 | "license": "MIT" 66 | }, 67 | "node_modules/acorn": { 68 | "version": "7.1.1", 69 | "dev": true, 70 | "license": "MIT", 71 | "bin": { 72 | "acorn": "bin/acorn" 73 | }, 74 | "engines": { 75 | "node": ">=0.4.0" 76 | } 77 | }, 78 | "node_modules/acorn-jsx": { 79 | "version": "5.2.0", 80 | "dev": true, 81 | "license": "MIT", 82 | "peerDependencies": { 83 | "acorn": "^6.0.0 || ^7.0.0" 84 | } 85 | }, 86 | "node_modules/adm-zip": { 87 | "version": "0.4.13", 88 | "license": "MIT", 89 | "engines": { 90 | "node": ">=0.3.0" 91 | } 92 | }, 93 | "node_modules/ajv": { 94 | "version": "6.12.6", 95 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 96 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 97 | "dependencies": { 98 | "fast-deep-equal": "^3.1.1", 99 | "fast-json-stable-stringify": "^2.0.0", 100 | "json-schema-traverse": "^0.4.1", 101 | "uri-js": "^4.2.2" 102 | }, 103 | "funding": { 104 | "type": "github", 105 | "url": "https://github.com/sponsors/epoberezkin" 106 | } 107 | }, 108 | "node_modules/ansi-escapes": { 109 | "version": "4.3.1", 110 | "dev": true, 111 | "license": "MIT", 112 | "dependencies": { 113 | "type-fest": "^0.11.0" 114 | }, 115 | "engines": { 116 | "node": ">=8" 117 | }, 118 | "funding": { 119 | "url": "https://github.com/sponsors/sindresorhus" 120 | } 121 | }, 122 | "node_modules/ansi-escapes/node_modules/type-fest": { 123 | "version": "0.11.0", 124 | "dev": true, 125 | "license": "(MIT OR CC0-1.0)", 126 | "engines": { 127 | "node": ">=8" 128 | }, 129 | "funding": { 130 | "url": "https://github.com/sponsors/sindresorhus" 131 | } 132 | }, 133 | "node_modules/ansi-regex": { 134 | "version": "5.0.1", 135 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 136 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 137 | "dev": true, 138 | "engines": { 139 | "node": ">=8" 140 | } 141 | }, 142 | "node_modules/ansi-styles": { 143 | "version": "3.2.1", 144 | "dev": true, 145 | "license": "MIT", 146 | "dependencies": { 147 | "color-convert": "^1.9.0" 148 | }, 149 | "engines": { 150 | "node": ">=4" 151 | } 152 | }, 153 | "node_modules/argparse": { 154 | "version": "1.0.10", 155 | "dev": true, 156 | "license": "MIT", 157 | "dependencies": { 158 | "sprintf-js": "~1.0.2" 159 | } 160 | }, 161 | "node_modules/array-includes": { 162 | "version": "3.1.1", 163 | "dev": true, 164 | "license": "MIT", 165 | "dependencies": { 166 | "define-properties": "^1.1.3", 167 | "es-abstract": "^1.17.0", 168 | "is-string": "^1.0.5" 169 | }, 170 | "engines": { 171 | "node": ">= 0.4" 172 | }, 173 | "funding": { 174 | "url": "https://github.com/sponsors/ljharb" 175 | } 176 | }, 177 | "node_modules/array.prototype.flat": { 178 | "version": "1.2.3", 179 | "dev": true, 180 | "license": "MIT", 181 | "dependencies": { 182 | "define-properties": "^1.1.3", 183 | "es-abstract": "^1.17.0-next.1" 184 | }, 185 | "engines": { 186 | "node": ">= 0.4" 187 | }, 188 | "funding": { 189 | "url": "https://github.com/sponsors/ljharb" 190 | } 191 | }, 192 | "node_modules/asn1": { 193 | "version": "0.2.6", 194 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", 195 | "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", 196 | "dependencies": { 197 | "safer-buffer": "~2.1.0" 198 | } 199 | }, 200 | "node_modules/assert-plus": { 201 | "version": "1.0.0", 202 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 203 | "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", 204 | "engines": { 205 | "node": ">=0.8" 206 | } 207 | }, 208 | "node_modules/astral-regex": { 209 | "version": "1.0.0", 210 | "dev": true, 211 | "license": "MIT", 212 | "engines": { 213 | "node": ">=4" 214 | } 215 | }, 216 | "node_modules/asynckit": { 217 | "version": "0.4.0", 218 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 219 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 220 | }, 221 | "node_modules/aws-sign2": { 222 | "version": "0.7.0", 223 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 224 | "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", 225 | "engines": { 226 | "node": "*" 227 | } 228 | }, 229 | "node_modules/aws4": { 230 | "version": "1.12.0", 231 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", 232 | "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" 233 | }, 234 | "node_modules/balanced-match": { 235 | "version": "1.0.0", 236 | "dev": true, 237 | "license": "MIT" 238 | }, 239 | "node_modules/bcrypt-pbkdf": { 240 | "version": "1.0.2", 241 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 242 | "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", 243 | "dependencies": { 244 | "tweetnacl": "^0.14.3" 245 | } 246 | }, 247 | "node_modules/brace-expansion": { 248 | "version": "1.1.11", 249 | "dev": true, 250 | "license": "MIT", 251 | "dependencies": { 252 | "balanced-match": "^1.0.0", 253 | "concat-map": "0.0.1" 254 | } 255 | }, 256 | "node_modules/callsites": { 257 | "version": "3.1.0", 258 | "dev": true, 259 | "license": "MIT", 260 | "engines": { 261 | "node": ">=6" 262 | } 263 | }, 264 | "node_modules/caseless": { 265 | "version": "0.12.0", 266 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 267 | "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" 268 | }, 269 | "node_modules/chalk": { 270 | "version": "2.4.2", 271 | "dev": true, 272 | "license": "MIT", 273 | "dependencies": { 274 | "ansi-styles": "^3.2.1", 275 | "escape-string-regexp": "^1.0.5", 276 | "supports-color": "^5.3.0" 277 | }, 278 | "engines": { 279 | "node": ">=4" 280 | } 281 | }, 282 | "node_modules/chardet": { 283 | "version": "0.7.0", 284 | "dev": true, 285 | "license": "MIT" 286 | }, 287 | "node_modules/checksum": { 288 | "version": "0.1.1", 289 | "license": "MIT", 290 | "dependencies": { 291 | "optimist": "~0.3.5" 292 | }, 293 | "bin": { 294 | "checksum": "bin/checksum-cli.js" 295 | } 296 | }, 297 | "node_modules/cli-cursor": { 298 | "version": "3.1.0", 299 | "dev": true, 300 | "license": "MIT", 301 | "dependencies": { 302 | "restore-cursor": "^3.1.0" 303 | }, 304 | "engines": { 305 | "node": ">=8" 306 | } 307 | }, 308 | "node_modules/cli-width": { 309 | "version": "2.2.1", 310 | "dev": true, 311 | "license": "ISC" 312 | }, 313 | "node_modules/color-convert": { 314 | "version": "1.9.3", 315 | "dev": true, 316 | "license": "MIT", 317 | "dependencies": { 318 | "color-name": "1.1.3" 319 | } 320 | }, 321 | "node_modules/color-name": { 322 | "version": "1.1.3", 323 | "dev": true, 324 | "license": "MIT" 325 | }, 326 | "node_modules/combined-stream": { 327 | "version": "1.0.8", 328 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 329 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 330 | "dependencies": { 331 | "delayed-stream": "~1.0.0" 332 | }, 333 | "engines": { 334 | "node": ">= 0.8" 335 | } 336 | }, 337 | "node_modules/concat-map": { 338 | "version": "0.0.1", 339 | "dev": true, 340 | "license": "MIT" 341 | }, 342 | "node_modules/contains-path": { 343 | "version": "0.1.0", 344 | "dev": true, 345 | "license": "MIT", 346 | "engines": { 347 | "node": ">=0.10.0" 348 | } 349 | }, 350 | "node_modules/core-util-is": { 351 | "version": "1.0.2", 352 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 353 | "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" 354 | }, 355 | "node_modules/cross-spawn": { 356 | "version": "6.0.5", 357 | "dev": true, 358 | "license": "MIT", 359 | "dependencies": { 360 | "nice-try": "^1.0.4", 361 | "path-key": "^2.0.1", 362 | "semver": "^5.5.0", 363 | "shebang-command": "^1.2.0", 364 | "which": "^1.2.9" 365 | }, 366 | "engines": { 367 | "node": ">=4.8" 368 | } 369 | }, 370 | "node_modules/cross-spawn/node_modules/semver": { 371 | "version": "5.7.2", 372 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", 373 | "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", 374 | "dev": true, 375 | "bin": { 376 | "semver": "bin/semver" 377 | } 378 | }, 379 | "node_modules/dashdash": { 380 | "version": "1.14.1", 381 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 382 | "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", 383 | "dependencies": { 384 | "assert-plus": "^1.0.0" 385 | }, 386 | "engines": { 387 | "node": ">=0.10" 388 | } 389 | }, 390 | "node_modules/debug": { 391 | "version": "4.3.4", 392 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 393 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 394 | "dev": true, 395 | "dependencies": { 396 | "ms": "2.1.2" 397 | }, 398 | "engines": { 399 | "node": ">=6.0" 400 | }, 401 | "peerDependenciesMeta": { 402 | "supports-color": { 403 | "optional": true 404 | } 405 | } 406 | }, 407 | "node_modules/deep-is": { 408 | "version": "0.1.3", 409 | "dev": true, 410 | "license": "MIT" 411 | }, 412 | "node_modules/define-properties": { 413 | "version": "1.1.3", 414 | "dev": true, 415 | "license": "MIT", 416 | "dependencies": { 417 | "object-keys": "^1.0.12" 418 | }, 419 | "engines": { 420 | "node": ">= 0.4" 421 | } 422 | }, 423 | "node_modules/delayed-stream": { 424 | "version": "1.0.0", 425 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 426 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 427 | "engines": { 428 | "node": ">=0.4.0" 429 | } 430 | }, 431 | "node_modules/doctrine": { 432 | "version": "3.0.0", 433 | "dev": true, 434 | "license": "Apache-2.0", 435 | "dependencies": { 436 | "esutils": "^2.0.2" 437 | }, 438 | "engines": { 439 | "node": ">=6.0.0" 440 | } 441 | }, 442 | "node_modules/ecc-jsbn": { 443 | "version": "0.1.2", 444 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 445 | "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", 446 | "dependencies": { 447 | "jsbn": "~0.1.0", 448 | "safer-buffer": "^2.1.0" 449 | } 450 | }, 451 | "node_modules/emoji-regex": { 452 | "version": "8.0.0", 453 | "dev": true, 454 | "license": "MIT" 455 | }, 456 | "node_modules/error-ex": { 457 | "version": "1.3.2", 458 | "dev": true, 459 | "license": "MIT", 460 | "dependencies": { 461 | "is-arrayish": "^0.2.1" 462 | } 463 | }, 464 | "node_modules/es-abstract": { 465 | "version": "1.17.5", 466 | "dev": true, 467 | "license": "MIT", 468 | "dependencies": { 469 | "es-to-primitive": "^1.2.1", 470 | "function-bind": "^1.1.1", 471 | "has": "^1.0.3", 472 | "has-symbols": "^1.0.1", 473 | "is-callable": "^1.1.5", 474 | "is-regex": "^1.0.5", 475 | "object-inspect": "^1.7.0", 476 | "object-keys": "^1.1.1", 477 | "object.assign": "^4.1.0", 478 | "string.prototype.trimleft": "^2.1.1", 479 | "string.prototype.trimright": "^2.1.1" 480 | }, 481 | "engines": { 482 | "node": ">= 0.4" 483 | }, 484 | "funding": { 485 | "url": "https://github.com/sponsors/ljharb" 486 | } 487 | }, 488 | "node_modules/es-to-primitive": { 489 | "version": "1.2.1", 490 | "dev": true, 491 | "license": "MIT", 492 | "dependencies": { 493 | "is-callable": "^1.1.4", 494 | "is-date-object": "^1.0.1", 495 | "is-symbol": "^1.0.2" 496 | }, 497 | "engines": { 498 | "node": ">= 0.4" 499 | }, 500 | "funding": { 501 | "url": "https://github.com/sponsors/ljharb" 502 | } 503 | }, 504 | "node_modules/escape-string-regexp": { 505 | "version": "1.0.5", 506 | "dev": true, 507 | "license": "MIT", 508 | "engines": { 509 | "node": ">=0.8.0" 510 | } 511 | }, 512 | "node_modules/eslint": { 513 | "version": "6.8.0", 514 | "dev": true, 515 | "license": "MIT", 516 | "dependencies": { 517 | "@babel/code-frame": "^7.0.0", 518 | "ajv": "^6.10.0", 519 | "chalk": "^2.1.0", 520 | "cross-spawn": "^6.0.5", 521 | "debug": "^4.0.1", 522 | "doctrine": "^3.0.0", 523 | "eslint-scope": "^5.0.0", 524 | "eslint-utils": "^1.4.3", 525 | "eslint-visitor-keys": "^1.1.0", 526 | "espree": "^6.1.2", 527 | "esquery": "^1.0.1", 528 | "esutils": "^2.0.2", 529 | "file-entry-cache": "^5.0.1", 530 | "functional-red-black-tree": "^1.0.1", 531 | "glob-parent": "^5.0.0", 532 | "globals": "^12.1.0", 533 | "ignore": "^4.0.6", 534 | "import-fresh": "^3.0.0", 535 | "imurmurhash": "^0.1.4", 536 | "inquirer": "^7.0.0", 537 | "is-glob": "^4.0.0", 538 | "js-yaml": "^3.13.1", 539 | "json-stable-stringify-without-jsonify": "^1.0.1", 540 | "levn": "^0.3.0", 541 | "lodash": "^4.17.14", 542 | "minimatch": "^3.0.4", 543 | "mkdirp": "^0.5.1", 544 | "natural-compare": "^1.4.0", 545 | "optionator": "^0.8.3", 546 | "progress": "^2.0.0", 547 | "regexpp": "^2.0.1", 548 | "semver": "^6.1.2", 549 | "strip-ansi": "^5.2.0", 550 | "strip-json-comments": "^3.0.1", 551 | "table": "^5.2.3", 552 | "text-table": "^0.2.0", 553 | "v8-compile-cache": "^2.0.3" 554 | }, 555 | "bin": { 556 | "eslint": "bin/eslint.js" 557 | }, 558 | "engines": { 559 | "node": "^8.10.0 || ^10.13.0 || >=11.10.1" 560 | }, 561 | "funding": { 562 | "url": "https://opencollective.com/eslint" 563 | } 564 | }, 565 | "node_modules/eslint-config-standard": { 566 | "version": "14.1.1", 567 | "dev": true, 568 | "license": "MIT", 569 | "peerDependencies": { 570 | "eslint": ">=6.2.2", 571 | "eslint-plugin-import": ">=2.18.0", 572 | "eslint-plugin-node": ">=9.1.0", 573 | "eslint-plugin-promise": ">=4.2.1", 574 | "eslint-plugin-standard": ">=4.0.0" 575 | } 576 | }, 577 | "node_modules/eslint-import-resolver-node": { 578 | "version": "0.3.3", 579 | "dev": true, 580 | "license": "MIT", 581 | "dependencies": { 582 | "debug": "^2.6.9", 583 | "resolve": "^1.13.1" 584 | } 585 | }, 586 | "node_modules/eslint-import-resolver-node/node_modules/debug": { 587 | "version": "2.6.9", 588 | "dev": true, 589 | "license": "MIT", 590 | "dependencies": { 591 | "ms": "2.0.0" 592 | } 593 | }, 594 | "node_modules/eslint-import-resolver-node/node_modules/ms": { 595 | "version": "2.0.0", 596 | "dev": true, 597 | "license": "MIT" 598 | }, 599 | "node_modules/eslint-import-resolver-node/node_modules/resolve": { 600 | "version": "1.17.0", 601 | "dev": true, 602 | "license": "MIT", 603 | "dependencies": { 604 | "path-parse": "^1.0.6" 605 | }, 606 | "funding": { 607 | "url": "https://github.com/sponsors/ljharb" 608 | } 609 | }, 610 | "node_modules/eslint-module-utils": { 611 | "version": "2.6.0", 612 | "dev": true, 613 | "license": "MIT", 614 | "dependencies": { 615 | "debug": "^2.6.9", 616 | "pkg-dir": "^2.0.0" 617 | }, 618 | "engines": { 619 | "node": ">=4" 620 | } 621 | }, 622 | "node_modules/eslint-module-utils/node_modules/debug": { 623 | "version": "2.6.9", 624 | "dev": true, 625 | "license": "MIT", 626 | "dependencies": { 627 | "ms": "2.0.0" 628 | } 629 | }, 630 | "node_modules/eslint-module-utils/node_modules/ms": { 631 | "version": "2.0.0", 632 | "dev": true, 633 | "license": "MIT" 634 | }, 635 | "node_modules/eslint-plugin-es": { 636 | "version": "3.0.0", 637 | "dev": true, 638 | "license": "MIT", 639 | "dependencies": { 640 | "eslint-utils": "^2.0.0", 641 | "regexpp": "^3.0.0" 642 | }, 643 | "engines": { 644 | "node": ">=8.10.0" 645 | }, 646 | "peerDependencies": { 647 | "eslint": ">=4.19.1" 648 | } 649 | }, 650 | "node_modules/eslint-plugin-es/node_modules/eslint-utils": { 651 | "version": "2.0.0", 652 | "dev": true, 653 | "license": "MIT", 654 | "dependencies": { 655 | "eslint-visitor-keys": "^1.1.0" 656 | }, 657 | "engines": { 658 | "node": ">=6" 659 | } 660 | }, 661 | "node_modules/eslint-plugin-es/node_modules/regexpp": { 662 | "version": "3.1.0", 663 | "dev": true, 664 | "license": "MIT", 665 | "engines": { 666 | "node": ">=8" 667 | }, 668 | "funding": { 669 | "url": "https://github.com/sponsors/mysticatea" 670 | } 671 | }, 672 | "node_modules/eslint-plugin-import": { 673 | "version": "2.20.2", 674 | "dev": true, 675 | "license": "MIT", 676 | "dependencies": { 677 | "array-includes": "^3.0.3", 678 | "array.prototype.flat": "^1.2.1", 679 | "contains-path": "^0.1.0", 680 | "debug": "^2.6.9", 681 | "doctrine": "1.5.0", 682 | "eslint-import-resolver-node": "^0.3.2", 683 | "eslint-module-utils": "^2.4.1", 684 | "has": "^1.0.3", 685 | "minimatch": "^3.0.4", 686 | "object.values": "^1.1.0", 687 | "read-pkg-up": "^2.0.0", 688 | "resolve": "^1.12.0" 689 | }, 690 | "engines": { 691 | "node": ">=4" 692 | }, 693 | "peerDependencies": { 694 | "eslint": "2.x - 6.x" 695 | } 696 | }, 697 | "node_modules/eslint-plugin-import/node_modules/debug": { 698 | "version": "2.6.9", 699 | "dev": true, 700 | "license": "MIT", 701 | "dependencies": { 702 | "ms": "2.0.0" 703 | } 704 | }, 705 | "node_modules/eslint-plugin-import/node_modules/doctrine": { 706 | "version": "1.5.0", 707 | "dev": true, 708 | "dependencies": { 709 | "esutils": "^2.0.2", 710 | "isarray": "^1.0.0" 711 | }, 712 | "engines": { 713 | "node": ">=0.10.0" 714 | } 715 | }, 716 | "node_modules/eslint-plugin-import/node_modules/ms": { 717 | "version": "2.0.0", 718 | "dev": true, 719 | "license": "MIT" 720 | }, 721 | "node_modules/eslint-plugin-import/node_modules/resolve": { 722 | "version": "1.17.0", 723 | "dev": true, 724 | "license": "MIT", 725 | "dependencies": { 726 | "path-parse": "^1.0.6" 727 | }, 728 | "funding": { 729 | "url": "https://github.com/sponsors/ljharb" 730 | } 731 | }, 732 | "node_modules/eslint-plugin-node": { 733 | "version": "11.1.0", 734 | "dev": true, 735 | "license": "MIT", 736 | "dependencies": { 737 | "eslint-plugin-es": "^3.0.0", 738 | "eslint-utils": "^2.0.0", 739 | "ignore": "^5.1.1", 740 | "minimatch": "^3.0.4", 741 | "resolve": "^1.10.1", 742 | "semver": "^6.1.0" 743 | }, 744 | "engines": { 745 | "node": ">=8.10.0" 746 | }, 747 | "peerDependencies": { 748 | "eslint": ">=5.16.0" 749 | } 750 | }, 751 | "node_modules/eslint-plugin-node/node_modules/eslint-utils": { 752 | "version": "2.0.0", 753 | "dev": true, 754 | "license": "MIT", 755 | "dependencies": { 756 | "eslint-visitor-keys": "^1.1.0" 757 | }, 758 | "engines": { 759 | "node": ">=6" 760 | } 761 | }, 762 | "node_modules/eslint-plugin-node/node_modules/ignore": { 763 | "version": "5.1.4", 764 | "dev": true, 765 | "license": "MIT", 766 | "engines": { 767 | "node": ">= 4" 768 | } 769 | }, 770 | "node_modules/eslint-plugin-node/node_modules/resolve": { 771 | "version": "1.17.0", 772 | "dev": true, 773 | "license": "MIT", 774 | "dependencies": { 775 | "path-parse": "^1.0.6" 776 | }, 777 | "funding": { 778 | "url": "https://github.com/sponsors/ljharb" 779 | } 780 | }, 781 | "node_modules/eslint-plugin-promise": { 782 | "version": "4.2.1", 783 | "dev": true, 784 | "license": "ISC", 785 | "engines": { 786 | "node": ">=6" 787 | } 788 | }, 789 | "node_modules/eslint-plugin-standard": { 790 | "version": "4.0.1", 791 | "dev": true, 792 | "license": "MIT", 793 | "peerDependencies": { 794 | "eslint": ">=5.0.0" 795 | } 796 | }, 797 | "node_modules/eslint-scope": { 798 | "version": "5.0.0", 799 | "dev": true, 800 | "license": "BSD-2-Clause", 801 | "dependencies": { 802 | "esrecurse": "^4.1.0", 803 | "estraverse": "^4.1.1" 804 | }, 805 | "engines": { 806 | "node": ">=8.0.0" 807 | } 808 | }, 809 | "node_modules/eslint-utils": { 810 | "version": "1.4.3", 811 | "dev": true, 812 | "license": "MIT", 813 | "dependencies": { 814 | "eslint-visitor-keys": "^1.1.0" 815 | }, 816 | "engines": { 817 | "node": ">=6" 818 | } 819 | }, 820 | "node_modules/eslint-visitor-keys": { 821 | "version": "1.1.0", 822 | "dev": true, 823 | "license": "Apache-2.0", 824 | "engines": { 825 | "node": ">=4" 826 | } 827 | }, 828 | "node_modules/espree": { 829 | "version": "6.2.1", 830 | "dev": true, 831 | "license": "BSD-2-Clause", 832 | "dependencies": { 833 | "acorn": "^7.1.1", 834 | "acorn-jsx": "^5.2.0", 835 | "eslint-visitor-keys": "^1.1.0" 836 | }, 837 | "engines": { 838 | "node": ">=6.0.0" 839 | } 840 | }, 841 | "node_modules/esprima": { 842 | "version": "4.0.1", 843 | "dev": true, 844 | "license": "BSD-2-Clause", 845 | "bin": { 846 | "esparse": "bin/esparse.js", 847 | "esvalidate": "bin/esvalidate.js" 848 | }, 849 | "engines": { 850 | "node": ">=4" 851 | } 852 | }, 853 | "node_modules/esquery": { 854 | "version": "1.3.1", 855 | "dev": true, 856 | "license": "BSD-3-Clause", 857 | "dependencies": { 858 | "estraverse": "^5.1.0" 859 | }, 860 | "engines": { 861 | "node": ">=0.10" 862 | } 863 | }, 864 | "node_modules/esquery/node_modules/estraverse": { 865 | "version": "5.1.0", 866 | "dev": true, 867 | "license": "BSD-2-Clause", 868 | "engines": { 869 | "node": ">=4.0" 870 | } 871 | }, 872 | "node_modules/esrecurse": { 873 | "version": "4.2.1", 874 | "dev": true, 875 | "license": "BSD-2-Clause", 876 | "dependencies": { 877 | "estraverse": "^4.1.0" 878 | }, 879 | "engines": { 880 | "node": ">=4.0" 881 | } 882 | }, 883 | "node_modules/estraverse": { 884 | "version": "4.3.0", 885 | "dev": true, 886 | "license": "BSD-2-Clause", 887 | "engines": { 888 | "node": ">=4.0" 889 | } 890 | }, 891 | "node_modules/esutils": { 892 | "version": "2.0.3", 893 | "dev": true, 894 | "license": "BSD-2-Clause", 895 | "engines": { 896 | "node": ">=0.10.0" 897 | } 898 | }, 899 | "node_modules/extend": { 900 | "version": "3.0.2", 901 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 902 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 903 | }, 904 | "node_modules/external-editor": { 905 | "version": "3.1.0", 906 | "dev": true, 907 | "license": "MIT", 908 | "dependencies": { 909 | "chardet": "^0.7.0", 910 | "iconv-lite": "^0.4.24", 911 | "tmp": "^0.0.33" 912 | }, 913 | "engines": { 914 | "node": ">=4" 915 | } 916 | }, 917 | "node_modules/extsprintf": { 918 | "version": "1.3.0", 919 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 920 | "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", 921 | "engines": [ 922 | "node >=0.6.0" 923 | ] 924 | }, 925 | "node_modules/fast-deep-equal": { 926 | "version": "3.1.3", 927 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 928 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 929 | }, 930 | "node_modules/fast-json-stable-stringify": { 931 | "version": "2.0.0", 932 | "license": "MIT" 933 | }, 934 | "node_modules/fast-levenshtein": { 935 | "version": "2.0.6", 936 | "dev": true, 937 | "license": "MIT" 938 | }, 939 | "node_modules/figures": { 940 | "version": "3.2.0", 941 | "dev": true, 942 | "license": "MIT", 943 | "dependencies": { 944 | "escape-string-regexp": "^1.0.5" 945 | }, 946 | "engines": { 947 | "node": ">=8" 948 | }, 949 | "funding": { 950 | "url": "https://github.com/sponsors/sindresorhus" 951 | } 952 | }, 953 | "node_modules/file-entry-cache": { 954 | "version": "5.0.1", 955 | "dev": true, 956 | "license": "MIT", 957 | "dependencies": { 958 | "flat-cache": "^2.0.1" 959 | }, 960 | "engines": { 961 | "node": ">=4" 962 | } 963 | }, 964 | "node_modules/find-up": { 965 | "version": "2.1.0", 966 | "dev": true, 967 | "license": "MIT", 968 | "dependencies": { 969 | "locate-path": "^2.0.0" 970 | }, 971 | "engines": { 972 | "node": ">=4" 973 | } 974 | }, 975 | "node_modules/flat-cache": { 976 | "version": "2.0.1", 977 | "dev": true, 978 | "license": "MIT", 979 | "dependencies": { 980 | "flatted": "^2.0.0", 981 | "rimraf": "2.6.3", 982 | "write": "1.0.3" 983 | }, 984 | "engines": { 985 | "node": ">=4" 986 | } 987 | }, 988 | "node_modules/flatted": { 989 | "version": "2.0.2", 990 | "dev": true, 991 | "license": "ISC" 992 | }, 993 | "node_modules/forever-agent": { 994 | "version": "0.6.1", 995 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 996 | "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", 997 | "engines": { 998 | "node": "*" 999 | } 1000 | }, 1001 | "node_modules/form-data": { 1002 | "version": "2.3.3", 1003 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 1004 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 1005 | "dependencies": { 1006 | "asynckit": "^0.4.0", 1007 | "combined-stream": "^1.0.6", 1008 | "mime-types": "^2.1.12" 1009 | }, 1010 | "engines": { 1011 | "node": ">= 0.12" 1012 | } 1013 | }, 1014 | "node_modules/fs.realpath": { 1015 | "version": "1.0.0", 1016 | "dev": true, 1017 | "license": "ISC" 1018 | }, 1019 | "node_modules/function-bind": { 1020 | "version": "1.1.1", 1021 | "dev": true, 1022 | "license": "MIT" 1023 | }, 1024 | "node_modules/functional-red-black-tree": { 1025 | "version": "1.0.1", 1026 | "dev": true, 1027 | "license": "MIT" 1028 | }, 1029 | "node_modules/getpass": { 1030 | "version": "0.1.7", 1031 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 1032 | "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", 1033 | "dependencies": { 1034 | "assert-plus": "^1.0.0" 1035 | } 1036 | }, 1037 | "node_modules/glob": { 1038 | "version": "7.1.3", 1039 | "dev": true, 1040 | "license": "ISC", 1041 | "dependencies": { 1042 | "fs.realpath": "^1.0.0", 1043 | "inflight": "^1.0.4", 1044 | "inherits": "2", 1045 | "minimatch": "^3.0.4", 1046 | "once": "^1.3.0", 1047 | "path-is-absolute": "^1.0.0" 1048 | }, 1049 | "engines": { 1050 | "node": "*" 1051 | } 1052 | }, 1053 | "node_modules/glob-parent": { 1054 | "version": "5.1.2", 1055 | "dev": true, 1056 | "license": "ISC", 1057 | "dependencies": { 1058 | "is-glob": "^4.0.1" 1059 | }, 1060 | "engines": { 1061 | "node": ">= 6" 1062 | } 1063 | }, 1064 | "node_modules/globals": { 1065 | "version": "12.4.0", 1066 | "dev": true, 1067 | "license": "MIT", 1068 | "dependencies": { 1069 | "type-fest": "^0.8.1" 1070 | }, 1071 | "engines": { 1072 | "node": ">=8" 1073 | }, 1074 | "funding": { 1075 | "url": "https://github.com/sponsors/sindresorhus" 1076 | } 1077 | }, 1078 | "node_modules/graceful-fs": { 1079 | "version": "4.2.4", 1080 | "dev": true, 1081 | "license": "ISC" 1082 | }, 1083 | "node_modules/har-schema": { 1084 | "version": "2.0.0", 1085 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 1086 | "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", 1087 | "engines": { 1088 | "node": ">=4" 1089 | } 1090 | }, 1091 | "node_modules/har-validator": { 1092 | "version": "5.1.5", 1093 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", 1094 | "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", 1095 | "deprecated": "this library is no longer supported", 1096 | "dependencies": { 1097 | "ajv": "^6.12.3", 1098 | "har-schema": "^2.0.0" 1099 | }, 1100 | "engines": { 1101 | "node": ">=6" 1102 | } 1103 | }, 1104 | "node_modules/has": { 1105 | "version": "1.0.3", 1106 | "dev": true, 1107 | "license": "MIT", 1108 | "dependencies": { 1109 | "function-bind": "^1.1.1" 1110 | }, 1111 | "engines": { 1112 | "node": ">= 0.4.0" 1113 | } 1114 | }, 1115 | "node_modules/has-flag": { 1116 | "version": "3.0.0", 1117 | "dev": true, 1118 | "license": "MIT", 1119 | "engines": { 1120 | "node": ">=4" 1121 | } 1122 | }, 1123 | "node_modules/has-symbols": { 1124 | "version": "1.0.1", 1125 | "dev": true, 1126 | "license": "MIT", 1127 | "engines": { 1128 | "node": ">= 0.4" 1129 | }, 1130 | "funding": { 1131 | "url": "https://github.com/sponsors/ljharb" 1132 | } 1133 | }, 1134 | "node_modules/hosted-git-info": { 1135 | "version": "2.8.9", 1136 | "dev": true, 1137 | "license": "ISC" 1138 | }, 1139 | "node_modules/http-signature": { 1140 | "version": "1.2.0", 1141 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 1142 | "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", 1143 | "dependencies": { 1144 | "assert-plus": "^1.0.0", 1145 | "jsprim": "^1.2.2", 1146 | "sshpk": "^1.7.0" 1147 | }, 1148 | "engines": { 1149 | "node": ">=0.8", 1150 | "npm": ">=1.3.7" 1151 | } 1152 | }, 1153 | "node_modules/iconv-lite": { 1154 | "version": "0.4.24", 1155 | "dev": true, 1156 | "license": "MIT", 1157 | "dependencies": { 1158 | "safer-buffer": ">= 2.1.2 < 3" 1159 | }, 1160 | "engines": { 1161 | "node": ">=0.10.0" 1162 | } 1163 | }, 1164 | "node_modules/ignore": { 1165 | "version": "4.0.6", 1166 | "dev": true, 1167 | "license": "MIT", 1168 | "engines": { 1169 | "node": ">= 4" 1170 | } 1171 | }, 1172 | "node_modules/import-fresh": { 1173 | "version": "3.2.1", 1174 | "dev": true, 1175 | "license": "MIT", 1176 | "dependencies": { 1177 | "parent-module": "^1.0.0", 1178 | "resolve-from": "^4.0.0" 1179 | }, 1180 | "engines": { 1181 | "node": ">=6" 1182 | } 1183 | }, 1184 | "node_modules/imurmurhash": { 1185 | "version": "0.1.4", 1186 | "dev": true, 1187 | "license": "MIT", 1188 | "engines": { 1189 | "node": ">=0.8.19" 1190 | } 1191 | }, 1192 | "node_modules/inflight": { 1193 | "version": "1.0.6", 1194 | "dev": true, 1195 | "license": "ISC", 1196 | "dependencies": { 1197 | "once": "^1.3.0", 1198 | "wrappy": "1" 1199 | } 1200 | }, 1201 | "node_modules/inherits": { 1202 | "version": "2.0.3", 1203 | "dev": true, 1204 | "license": "ISC" 1205 | }, 1206 | "node_modules/inquirer": { 1207 | "version": "7.1.0", 1208 | "dev": true, 1209 | "license": "MIT", 1210 | "dependencies": { 1211 | "ansi-escapes": "^4.2.1", 1212 | "chalk": "^3.0.0", 1213 | "cli-cursor": "^3.1.0", 1214 | "cli-width": "^2.0.0", 1215 | "external-editor": "^3.0.3", 1216 | "figures": "^3.0.0", 1217 | "lodash": "^4.17.15", 1218 | "mute-stream": "0.0.8", 1219 | "run-async": "^2.4.0", 1220 | "rxjs": "^6.5.3", 1221 | "string-width": "^4.1.0", 1222 | "strip-ansi": "^6.0.0", 1223 | "through": "^2.3.6" 1224 | }, 1225 | "engines": { 1226 | "node": ">=6.0.0" 1227 | } 1228 | }, 1229 | "node_modules/inquirer/node_modules/ansi-styles": { 1230 | "version": "4.2.1", 1231 | "dev": true, 1232 | "license": "MIT", 1233 | "dependencies": { 1234 | "@types/color-name": "^1.1.1", 1235 | "color-convert": "^2.0.1" 1236 | }, 1237 | "engines": { 1238 | "node": ">=8" 1239 | }, 1240 | "funding": { 1241 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1242 | } 1243 | }, 1244 | "node_modules/inquirer/node_modules/chalk": { 1245 | "version": "3.0.0", 1246 | "dev": true, 1247 | "license": "MIT", 1248 | "dependencies": { 1249 | "ansi-styles": "^4.1.0", 1250 | "supports-color": "^7.1.0" 1251 | }, 1252 | "engines": { 1253 | "node": ">=8" 1254 | } 1255 | }, 1256 | "node_modules/inquirer/node_modules/color-convert": { 1257 | "version": "2.0.1", 1258 | "dev": true, 1259 | "license": "MIT", 1260 | "dependencies": { 1261 | "color-name": "~1.1.4" 1262 | }, 1263 | "engines": { 1264 | "node": ">=7.0.0" 1265 | } 1266 | }, 1267 | "node_modules/inquirer/node_modules/color-name": { 1268 | "version": "1.1.4", 1269 | "dev": true, 1270 | "license": "MIT" 1271 | }, 1272 | "node_modules/inquirer/node_modules/has-flag": { 1273 | "version": "4.0.0", 1274 | "dev": true, 1275 | "license": "MIT", 1276 | "engines": { 1277 | "node": ">=8" 1278 | } 1279 | }, 1280 | "node_modules/inquirer/node_modules/strip-ansi": { 1281 | "version": "6.0.0", 1282 | "dev": true, 1283 | "license": "MIT", 1284 | "dependencies": { 1285 | "ansi-regex": "^5.0.0" 1286 | }, 1287 | "engines": { 1288 | "node": ">=8" 1289 | } 1290 | }, 1291 | "node_modules/inquirer/node_modules/supports-color": { 1292 | "version": "7.1.0", 1293 | "dev": true, 1294 | "license": "MIT", 1295 | "dependencies": { 1296 | "has-flag": "^4.0.0" 1297 | }, 1298 | "engines": { 1299 | "node": ">=8" 1300 | } 1301 | }, 1302 | "node_modules/is-arrayish": { 1303 | "version": "0.2.1", 1304 | "dev": true, 1305 | "license": "MIT" 1306 | }, 1307 | "node_modules/is-callable": { 1308 | "version": "1.1.5", 1309 | "dev": true, 1310 | "license": "MIT", 1311 | "engines": { 1312 | "node": ">= 0.4" 1313 | }, 1314 | "funding": { 1315 | "url": "https://github.com/sponsors/ljharb" 1316 | } 1317 | }, 1318 | "node_modules/is-date-object": { 1319 | "version": "1.0.2", 1320 | "dev": true, 1321 | "license": "MIT", 1322 | "engines": { 1323 | "node": ">= 0.4" 1324 | }, 1325 | "funding": { 1326 | "url": "https://github.com/sponsors/ljharb" 1327 | } 1328 | }, 1329 | "node_modules/is-extglob": { 1330 | "version": "2.1.1", 1331 | "dev": true, 1332 | "license": "MIT", 1333 | "engines": { 1334 | "node": ">=0.10.0" 1335 | } 1336 | }, 1337 | "node_modules/is-fullwidth-code-point": { 1338 | "version": "3.0.0", 1339 | "dev": true, 1340 | "license": "MIT", 1341 | "engines": { 1342 | "node": ">=8" 1343 | } 1344 | }, 1345 | "node_modules/is-glob": { 1346 | "version": "4.0.1", 1347 | "dev": true, 1348 | "license": "MIT", 1349 | "dependencies": { 1350 | "is-extglob": "^2.1.1" 1351 | }, 1352 | "engines": { 1353 | "node": ">=0.10.0" 1354 | } 1355 | }, 1356 | "node_modules/is-regex": { 1357 | "version": "1.0.5", 1358 | "dev": true, 1359 | "license": "MIT", 1360 | "dependencies": { 1361 | "has": "^1.0.3" 1362 | }, 1363 | "engines": { 1364 | "node": ">= 0.4" 1365 | }, 1366 | "funding": { 1367 | "url": "https://github.com/sponsors/ljharb" 1368 | } 1369 | }, 1370 | "node_modules/is-string": { 1371 | "version": "1.0.5", 1372 | "dev": true, 1373 | "license": "MIT", 1374 | "engines": { 1375 | "node": ">= 0.4" 1376 | }, 1377 | "funding": { 1378 | "url": "https://github.com/sponsors/ljharb" 1379 | } 1380 | }, 1381 | "node_modules/is-symbol": { 1382 | "version": "1.0.3", 1383 | "dev": true, 1384 | "license": "MIT", 1385 | "dependencies": { 1386 | "has-symbols": "^1.0.1" 1387 | }, 1388 | "engines": { 1389 | "node": ">= 0.4" 1390 | }, 1391 | "funding": { 1392 | "url": "https://github.com/sponsors/ljharb" 1393 | } 1394 | }, 1395 | "node_modules/is-typedarray": { 1396 | "version": "1.0.0", 1397 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1398 | "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" 1399 | }, 1400 | "node_modules/isarray": { 1401 | "version": "1.0.0", 1402 | "dev": true, 1403 | "license": "MIT" 1404 | }, 1405 | "node_modules/isexe": { 1406 | "version": "2.0.0", 1407 | "dev": true, 1408 | "license": "ISC" 1409 | }, 1410 | "node_modules/isstream": { 1411 | "version": "0.1.2", 1412 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 1413 | "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" 1414 | }, 1415 | "node_modules/js-tokens": { 1416 | "version": "4.0.0", 1417 | "dev": true, 1418 | "license": "MIT" 1419 | }, 1420 | "node_modules/js-yaml": { 1421 | "version": "3.13.1", 1422 | "dev": true, 1423 | "license": "MIT", 1424 | "dependencies": { 1425 | "argparse": "^1.0.7", 1426 | "esprima": "^4.0.0" 1427 | }, 1428 | "bin": { 1429 | "js-yaml": "bin/js-yaml.js" 1430 | } 1431 | }, 1432 | "node_modules/jsbn": { 1433 | "version": "0.1.1", 1434 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 1435 | "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" 1436 | }, 1437 | "node_modules/json-schema": { 1438 | "version": "0.4.0", 1439 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", 1440 | "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" 1441 | }, 1442 | "node_modules/json-schema-traverse": { 1443 | "version": "0.4.1", 1444 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1445 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" 1446 | }, 1447 | "node_modules/json-stable-stringify-without-jsonify": { 1448 | "version": "1.0.1", 1449 | "dev": true, 1450 | "license": "MIT" 1451 | }, 1452 | "node_modules/json-stringify-safe": { 1453 | "version": "5.0.1", 1454 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 1455 | "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" 1456 | }, 1457 | "node_modules/jsprim": { 1458 | "version": "1.4.2", 1459 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", 1460 | "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", 1461 | "dependencies": { 1462 | "assert-plus": "1.0.0", 1463 | "extsprintf": "1.3.0", 1464 | "json-schema": "0.4.0", 1465 | "verror": "1.10.0" 1466 | }, 1467 | "engines": { 1468 | "node": ">=0.6.0" 1469 | } 1470 | }, 1471 | "node_modules/levn": { 1472 | "version": "0.3.0", 1473 | "dev": true, 1474 | "license": "MIT", 1475 | "dependencies": { 1476 | "prelude-ls": "~1.1.2", 1477 | "type-check": "~0.3.2" 1478 | }, 1479 | "engines": { 1480 | "node": ">= 0.8.0" 1481 | } 1482 | }, 1483 | "node_modules/load-json-file": { 1484 | "version": "2.0.0", 1485 | "dev": true, 1486 | "license": "MIT", 1487 | "dependencies": { 1488 | "graceful-fs": "^4.1.2", 1489 | "parse-json": "^2.2.0", 1490 | "pify": "^2.0.0", 1491 | "strip-bom": "^3.0.0" 1492 | }, 1493 | "engines": { 1494 | "node": ">=4" 1495 | } 1496 | }, 1497 | "node_modules/locate-path": { 1498 | "version": "2.0.0", 1499 | "dev": true, 1500 | "license": "MIT", 1501 | "dependencies": { 1502 | "p-locate": "^2.0.0", 1503 | "path-exists": "^3.0.0" 1504 | }, 1505 | "engines": { 1506 | "node": ">=4" 1507 | } 1508 | }, 1509 | "node_modules/lodash": { 1510 | "version": "4.17.21", 1511 | "dev": true, 1512 | "license": "MIT" 1513 | }, 1514 | "node_modules/mime-db": { 1515 | "version": "1.52.0", 1516 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1517 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 1518 | "engines": { 1519 | "node": ">= 0.6" 1520 | } 1521 | }, 1522 | "node_modules/mime-types": { 1523 | "version": "2.1.35", 1524 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1525 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1526 | "dependencies": { 1527 | "mime-db": "1.52.0" 1528 | }, 1529 | "engines": { 1530 | "node": ">= 0.6" 1531 | } 1532 | }, 1533 | "node_modules/mimic-fn": { 1534 | "version": "2.1.0", 1535 | "dev": true, 1536 | "license": "MIT", 1537 | "engines": { 1538 | "node": ">=6" 1539 | } 1540 | }, 1541 | "node_modules/minimatch": { 1542 | "version": "3.1.2", 1543 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1544 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1545 | "dev": true, 1546 | "dependencies": { 1547 | "brace-expansion": "^1.1.7" 1548 | }, 1549 | "engines": { 1550 | "node": "*" 1551 | } 1552 | }, 1553 | "node_modules/minimist": { 1554 | "version": "1.2.8", 1555 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1556 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1557 | "dev": true, 1558 | "funding": { 1559 | "url": "https://github.com/sponsors/ljharb" 1560 | } 1561 | }, 1562 | "node_modules/mkdirp": { 1563 | "version": "0.5.5", 1564 | "dev": true, 1565 | "license": "MIT", 1566 | "dependencies": { 1567 | "minimist": "^1.2.5" 1568 | }, 1569 | "bin": { 1570 | "mkdirp": "bin/cmd.js" 1571 | } 1572 | }, 1573 | "node_modules/ms": { 1574 | "version": "2.1.2", 1575 | "dev": true, 1576 | "license": "MIT" 1577 | }, 1578 | "node_modules/mute-stream": { 1579 | "version": "0.0.8", 1580 | "dev": true, 1581 | "license": "ISC" 1582 | }, 1583 | "node_modules/natural-compare": { 1584 | "version": "1.4.0", 1585 | "dev": true, 1586 | "license": "MIT" 1587 | }, 1588 | "node_modules/nice-try": { 1589 | "version": "1.0.5", 1590 | "dev": true, 1591 | "license": "MIT" 1592 | }, 1593 | "node_modules/normalize-package-data": { 1594 | "version": "2.5.0", 1595 | "dev": true, 1596 | "license": "BSD-2-Clause", 1597 | "dependencies": { 1598 | "hosted-git-info": "^2.1.4", 1599 | "resolve": "^1.10.0", 1600 | "semver": "2 || 3 || 4 || 5", 1601 | "validate-npm-package-license": "^3.0.1" 1602 | } 1603 | }, 1604 | "node_modules/normalize-package-data/node_modules/resolve": { 1605 | "version": "1.17.0", 1606 | "dev": true, 1607 | "license": "MIT", 1608 | "dependencies": { 1609 | "path-parse": "^1.0.6" 1610 | }, 1611 | "funding": { 1612 | "url": "https://github.com/sponsors/ljharb" 1613 | } 1614 | }, 1615 | "node_modules/normalize-package-data/node_modules/semver": { 1616 | "version": "5.7.2", 1617 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", 1618 | "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", 1619 | "dev": true, 1620 | "bin": { 1621 | "semver": "bin/semver" 1622 | } 1623 | }, 1624 | "node_modules/oauth-sign": { 1625 | "version": "0.9.0", 1626 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 1627 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", 1628 | "engines": { 1629 | "node": "*" 1630 | } 1631 | }, 1632 | "node_modules/object-inspect": { 1633 | "version": "1.7.0", 1634 | "dev": true, 1635 | "license": "MIT", 1636 | "funding": { 1637 | "url": "https://github.com/sponsors/ljharb" 1638 | } 1639 | }, 1640 | "node_modules/object-keys": { 1641 | "version": "1.1.1", 1642 | "dev": true, 1643 | "license": "MIT", 1644 | "engines": { 1645 | "node": ">= 0.4" 1646 | } 1647 | }, 1648 | "node_modules/object.assign": { 1649 | "version": "4.1.0", 1650 | "dev": true, 1651 | "license": "MIT", 1652 | "dependencies": { 1653 | "define-properties": "^1.1.2", 1654 | "function-bind": "^1.1.1", 1655 | "has-symbols": "^1.0.0", 1656 | "object-keys": "^1.0.11" 1657 | }, 1658 | "engines": { 1659 | "node": ">= 0.4" 1660 | } 1661 | }, 1662 | "node_modules/object.values": { 1663 | "version": "1.1.1", 1664 | "dev": true, 1665 | "license": "MIT", 1666 | "dependencies": { 1667 | "define-properties": "^1.1.3", 1668 | "es-abstract": "^1.17.0-next.1", 1669 | "function-bind": "^1.1.1", 1670 | "has": "^1.0.3" 1671 | }, 1672 | "engines": { 1673 | "node": ">= 0.4" 1674 | }, 1675 | "funding": { 1676 | "url": "https://github.com/sponsors/ljharb" 1677 | } 1678 | }, 1679 | "node_modules/once": { 1680 | "version": "1.4.0", 1681 | "dev": true, 1682 | "license": "ISC", 1683 | "dependencies": { 1684 | "wrappy": "1" 1685 | } 1686 | }, 1687 | "node_modules/onetime": { 1688 | "version": "5.1.0", 1689 | "dev": true, 1690 | "license": "MIT", 1691 | "dependencies": { 1692 | "mimic-fn": "^2.1.0" 1693 | }, 1694 | "engines": { 1695 | "node": ">=6" 1696 | } 1697 | }, 1698 | "node_modules/optimist": { 1699 | "version": "0.3.7", 1700 | "license": "MIT/X11", 1701 | "dependencies": { 1702 | "wordwrap": "~0.0.2" 1703 | } 1704 | }, 1705 | "node_modules/optionator": { 1706 | "version": "0.8.3", 1707 | "dev": true, 1708 | "license": "MIT", 1709 | "dependencies": { 1710 | "deep-is": "~0.1.3", 1711 | "fast-levenshtein": "~2.0.6", 1712 | "levn": "~0.3.0", 1713 | "prelude-ls": "~1.1.2", 1714 | "type-check": "~0.3.2", 1715 | "word-wrap": "~1.2.3" 1716 | }, 1717 | "engines": { 1718 | "node": ">= 0.8.0" 1719 | } 1720 | }, 1721 | "node_modules/os-tmpdir": { 1722 | "version": "1.0.2", 1723 | "dev": true, 1724 | "license": "MIT", 1725 | "engines": { 1726 | "node": ">=0.10.0" 1727 | } 1728 | }, 1729 | "node_modules/p-limit": { 1730 | "version": "1.3.0", 1731 | "dev": true, 1732 | "license": "MIT", 1733 | "dependencies": { 1734 | "p-try": "^1.0.0" 1735 | }, 1736 | "engines": { 1737 | "node": ">=4" 1738 | } 1739 | }, 1740 | "node_modules/p-locate": { 1741 | "version": "2.0.0", 1742 | "dev": true, 1743 | "license": "MIT", 1744 | "dependencies": { 1745 | "p-limit": "^1.1.0" 1746 | }, 1747 | "engines": { 1748 | "node": ">=4" 1749 | } 1750 | }, 1751 | "node_modules/p-try": { 1752 | "version": "1.0.0", 1753 | "dev": true, 1754 | "license": "MIT", 1755 | "engines": { 1756 | "node": ">=4" 1757 | } 1758 | }, 1759 | "node_modules/parent-module": { 1760 | "version": "1.0.1", 1761 | "dev": true, 1762 | "license": "MIT", 1763 | "dependencies": { 1764 | "callsites": "^3.0.0" 1765 | }, 1766 | "engines": { 1767 | "node": ">=6" 1768 | } 1769 | }, 1770 | "node_modules/parse-json": { 1771 | "version": "2.2.0", 1772 | "dev": true, 1773 | "license": "MIT", 1774 | "dependencies": { 1775 | "error-ex": "^1.2.0" 1776 | }, 1777 | "engines": { 1778 | "node": ">=0.10.0" 1779 | } 1780 | }, 1781 | "node_modules/path-exists": { 1782 | "version": "3.0.0", 1783 | "dev": true, 1784 | "license": "MIT", 1785 | "engines": { 1786 | "node": ">=4" 1787 | } 1788 | }, 1789 | "node_modules/path-is-absolute": { 1790 | "version": "1.0.1", 1791 | "dev": true, 1792 | "license": "MIT", 1793 | "engines": { 1794 | "node": ">=0.10.0" 1795 | } 1796 | }, 1797 | "node_modules/path-key": { 1798 | "version": "2.0.1", 1799 | "dev": true, 1800 | "license": "MIT", 1801 | "engines": { 1802 | "node": ">=4" 1803 | } 1804 | }, 1805 | "node_modules/path-parse": { 1806 | "version": "1.0.7", 1807 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1808 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1809 | "dev": true 1810 | }, 1811 | "node_modules/path-type": { 1812 | "version": "2.0.0", 1813 | "dev": true, 1814 | "license": "MIT", 1815 | "dependencies": { 1816 | "pify": "^2.0.0" 1817 | }, 1818 | "engines": { 1819 | "node": ">=4" 1820 | } 1821 | }, 1822 | "node_modules/performance-now": { 1823 | "version": "2.1.0", 1824 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 1825 | "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" 1826 | }, 1827 | "node_modules/pify": { 1828 | "version": "2.3.0", 1829 | "dev": true, 1830 | "license": "MIT", 1831 | "engines": { 1832 | "node": ">=0.10.0" 1833 | } 1834 | }, 1835 | "node_modules/pkg-dir": { 1836 | "version": "2.0.0", 1837 | "dev": true, 1838 | "license": "MIT", 1839 | "dependencies": { 1840 | "find-up": "^2.1.0" 1841 | }, 1842 | "engines": { 1843 | "node": ">=4" 1844 | } 1845 | }, 1846 | "node_modules/prelude-ls": { 1847 | "version": "1.1.2", 1848 | "dev": true, 1849 | "engines": { 1850 | "node": ">= 0.8.0" 1851 | } 1852 | }, 1853 | "node_modules/progress": { 1854 | "version": "2.0.3", 1855 | "dev": true, 1856 | "license": "MIT", 1857 | "engines": { 1858 | "node": ">=0.4.0" 1859 | } 1860 | }, 1861 | "node_modules/psl": { 1862 | "version": "1.9.0", 1863 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", 1864 | "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" 1865 | }, 1866 | "node_modules/punycode": { 1867 | "version": "2.3.1", 1868 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", 1869 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", 1870 | "engines": { 1871 | "node": ">=6" 1872 | } 1873 | }, 1874 | "node_modules/qs": { 1875 | "version": "6.5.3", 1876 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", 1877 | "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", 1878 | "engines": { 1879 | "node": ">=0.6" 1880 | } 1881 | }, 1882 | "node_modules/read-pkg": { 1883 | "version": "2.0.0", 1884 | "dev": true, 1885 | "license": "MIT", 1886 | "dependencies": { 1887 | "load-json-file": "^2.0.0", 1888 | "normalize-package-data": "^2.3.2", 1889 | "path-type": "^2.0.0" 1890 | }, 1891 | "engines": { 1892 | "node": ">=4" 1893 | } 1894 | }, 1895 | "node_modules/read-pkg-up": { 1896 | "version": "2.0.0", 1897 | "dev": true, 1898 | "license": "MIT", 1899 | "dependencies": { 1900 | "find-up": "^2.0.0", 1901 | "read-pkg": "^2.0.0" 1902 | }, 1903 | "engines": { 1904 | "node": ">=4" 1905 | } 1906 | }, 1907 | "node_modules/regexpp": { 1908 | "version": "2.0.1", 1909 | "dev": true, 1910 | "license": "MIT", 1911 | "engines": { 1912 | "node": ">=6.5.0" 1913 | } 1914 | }, 1915 | "node_modules/request": { 1916 | "version": "2.88.2", 1917 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", 1918 | "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", 1919 | "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", 1920 | "dependencies": { 1921 | "aws-sign2": "~0.7.0", 1922 | "aws4": "^1.8.0", 1923 | "caseless": "~0.12.0", 1924 | "combined-stream": "~1.0.6", 1925 | "extend": "~3.0.2", 1926 | "forever-agent": "~0.6.1", 1927 | "form-data": "~2.3.2", 1928 | "har-validator": "~5.1.3", 1929 | "http-signature": "~1.2.0", 1930 | "is-typedarray": "~1.0.0", 1931 | "isstream": "~0.1.2", 1932 | "json-stringify-safe": "~5.0.1", 1933 | "mime-types": "~2.1.19", 1934 | "oauth-sign": "~0.9.0", 1935 | "performance-now": "^2.1.0", 1936 | "qs": "~6.5.2", 1937 | "safe-buffer": "^5.1.2", 1938 | "tough-cookie": "~2.5.0", 1939 | "tunnel-agent": "^0.6.0", 1940 | "uuid": "^3.3.2" 1941 | }, 1942 | "engines": { 1943 | "node": ">= 6" 1944 | } 1945 | }, 1946 | "node_modules/request/node_modules/uuid": { 1947 | "version": "3.4.0", 1948 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 1949 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 1950 | "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.", 1951 | "bin": { 1952 | "uuid": "bin/uuid" 1953 | } 1954 | }, 1955 | "node_modules/resolve-from": { 1956 | "version": "4.0.0", 1957 | "dev": true, 1958 | "license": "MIT", 1959 | "engines": { 1960 | "node": ">=4" 1961 | } 1962 | }, 1963 | "node_modules/restore-cursor": { 1964 | "version": "3.1.0", 1965 | "dev": true, 1966 | "license": "MIT", 1967 | "dependencies": { 1968 | "onetime": "^5.1.0", 1969 | "signal-exit": "^3.0.2" 1970 | }, 1971 | "engines": { 1972 | "node": ">=8" 1973 | } 1974 | }, 1975 | "node_modules/rimraf": { 1976 | "version": "2.6.3", 1977 | "dev": true, 1978 | "license": "ISC", 1979 | "dependencies": { 1980 | "glob": "^7.1.3" 1981 | }, 1982 | "bin": { 1983 | "rimraf": "bin.js" 1984 | } 1985 | }, 1986 | "node_modules/run-async": { 1987 | "version": "2.4.1", 1988 | "dev": true, 1989 | "license": "MIT", 1990 | "engines": { 1991 | "node": ">=0.12.0" 1992 | } 1993 | }, 1994 | "node_modules/rxjs": { 1995 | "version": "6.5.5", 1996 | "dev": true, 1997 | "license": "Apache-2.0", 1998 | "dependencies": { 1999 | "tslib": "^1.9.0" 2000 | }, 2001 | "engines": { 2002 | "npm": ">=2.0.0" 2003 | } 2004 | }, 2005 | "node_modules/safe-buffer": { 2006 | "version": "5.2.1", 2007 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2008 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2009 | "funding": [ 2010 | { 2011 | "type": "github", 2012 | "url": "https://github.com/sponsors/feross" 2013 | }, 2014 | { 2015 | "type": "patreon", 2016 | "url": "https://www.patreon.com/feross" 2017 | }, 2018 | { 2019 | "type": "consulting", 2020 | "url": "https://feross.org/support" 2021 | } 2022 | ] 2023 | }, 2024 | "node_modules/safer-buffer": { 2025 | "version": "2.1.2", 2026 | "license": "MIT" 2027 | }, 2028 | "node_modules/semver": { 2029 | "version": "6.3.1", 2030 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", 2031 | "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", 2032 | "dev": true, 2033 | "bin": { 2034 | "semver": "bin/semver.js" 2035 | } 2036 | }, 2037 | "node_modules/shebang-command": { 2038 | "version": "1.2.0", 2039 | "dev": true, 2040 | "license": "MIT", 2041 | "dependencies": { 2042 | "shebang-regex": "^1.0.0" 2043 | }, 2044 | "engines": { 2045 | "node": ">=0.10.0" 2046 | } 2047 | }, 2048 | "node_modules/shebang-regex": { 2049 | "version": "1.0.0", 2050 | "dev": true, 2051 | "license": "MIT", 2052 | "engines": { 2053 | "node": ">=0.10.0" 2054 | } 2055 | }, 2056 | "node_modules/signal-exit": { 2057 | "version": "3.0.3", 2058 | "dev": true, 2059 | "license": "ISC" 2060 | }, 2061 | "node_modules/slice-ansi": { 2062 | "version": "2.1.0", 2063 | "dev": true, 2064 | "license": "MIT", 2065 | "dependencies": { 2066 | "ansi-styles": "^3.2.0", 2067 | "astral-regex": "^1.0.0", 2068 | "is-fullwidth-code-point": "^2.0.0" 2069 | }, 2070 | "engines": { 2071 | "node": ">=6" 2072 | } 2073 | }, 2074 | "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { 2075 | "version": "2.0.0", 2076 | "dev": true, 2077 | "license": "MIT", 2078 | "engines": { 2079 | "node": ">=4" 2080 | } 2081 | }, 2082 | "node_modules/spdx-correct": { 2083 | "version": "3.1.0", 2084 | "dev": true, 2085 | "license": "Apache-2.0", 2086 | "dependencies": { 2087 | "spdx-expression-parse": "^3.0.0", 2088 | "spdx-license-ids": "^3.0.0" 2089 | } 2090 | }, 2091 | "node_modules/spdx-exceptions": { 2092 | "version": "2.3.0", 2093 | "dev": true, 2094 | "license": "CC-BY-3.0" 2095 | }, 2096 | "node_modules/spdx-expression-parse": { 2097 | "version": "3.0.0", 2098 | "dev": true, 2099 | "license": "MIT", 2100 | "dependencies": { 2101 | "spdx-exceptions": "^2.1.0", 2102 | "spdx-license-ids": "^3.0.0" 2103 | } 2104 | }, 2105 | "node_modules/spdx-license-ids": { 2106 | "version": "3.0.5", 2107 | "dev": true, 2108 | "license": "CC0-1.0" 2109 | }, 2110 | "node_modules/sprintf-js": { 2111 | "version": "1.0.3", 2112 | "dev": true, 2113 | "license": "BSD-3-Clause" 2114 | }, 2115 | "node_modules/sshpk": { 2116 | "version": "1.18.0", 2117 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", 2118 | "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", 2119 | "dependencies": { 2120 | "asn1": "~0.2.3", 2121 | "assert-plus": "^1.0.0", 2122 | "bcrypt-pbkdf": "^1.0.0", 2123 | "dashdash": "^1.12.0", 2124 | "ecc-jsbn": "~0.1.1", 2125 | "getpass": "^0.1.1", 2126 | "jsbn": "~0.1.0", 2127 | "safer-buffer": "^2.0.2", 2128 | "tweetnacl": "~0.14.0" 2129 | }, 2130 | "bin": { 2131 | "sshpk-conv": "bin/sshpk-conv", 2132 | "sshpk-sign": "bin/sshpk-sign", 2133 | "sshpk-verify": "bin/sshpk-verify" 2134 | }, 2135 | "engines": { 2136 | "node": ">=0.10.0" 2137 | } 2138 | }, 2139 | "node_modules/string-width": { 2140 | "version": "4.2.0", 2141 | "dev": true, 2142 | "license": "MIT", 2143 | "dependencies": { 2144 | "emoji-regex": "^8.0.0", 2145 | "is-fullwidth-code-point": "^3.0.0", 2146 | "strip-ansi": "^6.0.0" 2147 | }, 2148 | "engines": { 2149 | "node": ">=8" 2150 | } 2151 | }, 2152 | "node_modules/string-width/node_modules/strip-ansi": { 2153 | "version": "6.0.0", 2154 | "dev": true, 2155 | "license": "MIT", 2156 | "dependencies": { 2157 | "ansi-regex": "^5.0.0" 2158 | }, 2159 | "engines": { 2160 | "node": ">=8" 2161 | } 2162 | }, 2163 | "node_modules/string.prototype.trimend": { 2164 | "version": "1.0.1", 2165 | "dev": true, 2166 | "license": "MIT", 2167 | "dependencies": { 2168 | "define-properties": "^1.1.3", 2169 | "es-abstract": "^1.17.5" 2170 | }, 2171 | "funding": { 2172 | "url": "https://github.com/sponsors/ljharb" 2173 | } 2174 | }, 2175 | "node_modules/string.prototype.trimleft": { 2176 | "version": "2.1.2", 2177 | "dev": true, 2178 | "license": "MIT", 2179 | "dependencies": { 2180 | "define-properties": "^1.1.3", 2181 | "es-abstract": "^1.17.5", 2182 | "string.prototype.trimstart": "^1.0.0" 2183 | }, 2184 | "engines": { 2185 | "node": ">= 0.4" 2186 | }, 2187 | "funding": { 2188 | "url": "https://github.com/sponsors/ljharb" 2189 | } 2190 | }, 2191 | "node_modules/string.prototype.trimright": { 2192 | "version": "2.1.2", 2193 | "dev": true, 2194 | "license": "MIT", 2195 | "dependencies": { 2196 | "define-properties": "^1.1.3", 2197 | "es-abstract": "^1.17.5", 2198 | "string.prototype.trimend": "^1.0.0" 2199 | }, 2200 | "engines": { 2201 | "node": ">= 0.4" 2202 | }, 2203 | "funding": { 2204 | "url": "https://github.com/sponsors/ljharb" 2205 | } 2206 | }, 2207 | "node_modules/string.prototype.trimstart": { 2208 | "version": "1.0.1", 2209 | "dev": true, 2210 | "license": "MIT", 2211 | "dependencies": { 2212 | "define-properties": "^1.1.3", 2213 | "es-abstract": "^1.17.5" 2214 | }, 2215 | "funding": { 2216 | "url": "https://github.com/sponsors/ljharb" 2217 | } 2218 | }, 2219 | "node_modules/strip-ansi": { 2220 | "version": "5.2.0", 2221 | "dev": true, 2222 | "license": "MIT", 2223 | "dependencies": { 2224 | "ansi-regex": "^4.1.0" 2225 | }, 2226 | "engines": { 2227 | "node": ">=6" 2228 | } 2229 | }, 2230 | "node_modules/strip-ansi/node_modules/ansi-regex": { 2231 | "version": "4.1.1", 2232 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", 2233 | "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", 2234 | "dev": true, 2235 | "engines": { 2236 | "node": ">=6" 2237 | } 2238 | }, 2239 | "node_modules/strip-bom": { 2240 | "version": "3.0.0", 2241 | "dev": true, 2242 | "license": "MIT", 2243 | "engines": { 2244 | "node": ">=4" 2245 | } 2246 | }, 2247 | "node_modules/strip-json-comments": { 2248 | "version": "3.1.0", 2249 | "dev": true, 2250 | "license": "MIT", 2251 | "engines": { 2252 | "node": ">=8" 2253 | } 2254 | }, 2255 | "node_modules/supports-color": { 2256 | "version": "5.5.0", 2257 | "dev": true, 2258 | "license": "MIT", 2259 | "dependencies": { 2260 | "has-flag": "^3.0.0" 2261 | }, 2262 | "engines": { 2263 | "node": ">=4" 2264 | } 2265 | }, 2266 | "node_modules/table": { 2267 | "version": "5.4.6", 2268 | "dev": true, 2269 | "license": "BSD-3-Clause", 2270 | "dependencies": { 2271 | "ajv": "^6.10.2", 2272 | "lodash": "^4.17.14", 2273 | "slice-ansi": "^2.1.0", 2274 | "string-width": "^3.0.0" 2275 | }, 2276 | "engines": { 2277 | "node": ">=6.0.0" 2278 | } 2279 | }, 2280 | "node_modules/table/node_modules/emoji-regex": { 2281 | "version": "7.0.3", 2282 | "dev": true, 2283 | "license": "MIT" 2284 | }, 2285 | "node_modules/table/node_modules/is-fullwidth-code-point": { 2286 | "version": "2.0.0", 2287 | "dev": true, 2288 | "license": "MIT", 2289 | "engines": { 2290 | "node": ">=4" 2291 | } 2292 | }, 2293 | "node_modules/table/node_modules/string-width": { 2294 | "version": "3.1.0", 2295 | "dev": true, 2296 | "license": "MIT", 2297 | "dependencies": { 2298 | "emoji-regex": "^7.0.1", 2299 | "is-fullwidth-code-point": "^2.0.0", 2300 | "strip-ansi": "^5.1.0" 2301 | }, 2302 | "engines": { 2303 | "node": ">=6" 2304 | } 2305 | }, 2306 | "node_modules/text-table": { 2307 | "version": "0.2.0", 2308 | "dev": true, 2309 | "license": "MIT" 2310 | }, 2311 | "node_modules/through": { 2312 | "version": "2.3.8", 2313 | "dev": true, 2314 | "license": "MIT" 2315 | }, 2316 | "node_modules/tmp": { 2317 | "version": "0.0.33", 2318 | "dev": true, 2319 | "license": "MIT", 2320 | "dependencies": { 2321 | "os-tmpdir": "~1.0.2" 2322 | }, 2323 | "engines": { 2324 | "node": ">=0.6.0" 2325 | } 2326 | }, 2327 | "node_modules/tough-cookie": { 2328 | "version": "2.5.0", 2329 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", 2330 | "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", 2331 | "dependencies": { 2332 | "psl": "^1.1.28", 2333 | "punycode": "^2.1.1" 2334 | }, 2335 | "engines": { 2336 | "node": ">=0.8" 2337 | } 2338 | }, 2339 | "node_modules/tslib": { 2340 | "version": "1.11.2", 2341 | "dev": true, 2342 | "license": "0BSD" 2343 | }, 2344 | "node_modules/tunnel-agent": { 2345 | "version": "0.6.0", 2346 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 2347 | "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", 2348 | "dependencies": { 2349 | "safe-buffer": "^5.0.1" 2350 | }, 2351 | "engines": { 2352 | "node": "*" 2353 | } 2354 | }, 2355 | "node_modules/tweetnacl": { 2356 | "version": "0.14.5", 2357 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 2358 | "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" 2359 | }, 2360 | "node_modules/type-check": { 2361 | "version": "0.3.2", 2362 | "dev": true, 2363 | "license": "MIT", 2364 | "dependencies": { 2365 | "prelude-ls": "~1.1.2" 2366 | }, 2367 | "engines": { 2368 | "node": ">= 0.8.0" 2369 | } 2370 | }, 2371 | "node_modules/type-fest": { 2372 | "version": "0.8.1", 2373 | "dev": true, 2374 | "license": "(MIT OR CC0-1.0)", 2375 | "engines": { 2376 | "node": ">=8" 2377 | } 2378 | }, 2379 | "node_modules/uri-js": { 2380 | "version": "4.2.2", 2381 | "license": "BSD-2-Clause", 2382 | "dependencies": { 2383 | "punycode": "^2.1.0" 2384 | } 2385 | }, 2386 | "node_modules/uuid": { 2387 | "version": "8.3.2", 2388 | "license": "MIT", 2389 | "bin": { 2390 | "uuid": "dist/bin/uuid" 2391 | } 2392 | }, 2393 | "node_modules/v8-compile-cache": { 2394 | "version": "2.1.0", 2395 | "dev": true, 2396 | "license": "MIT" 2397 | }, 2398 | "node_modules/validate-npm-package-license": { 2399 | "version": "3.0.4", 2400 | "dev": true, 2401 | "license": "Apache-2.0", 2402 | "dependencies": { 2403 | "spdx-correct": "^3.0.0", 2404 | "spdx-expression-parse": "^3.0.0" 2405 | } 2406 | }, 2407 | "node_modules/verror": { 2408 | "version": "1.10.0", 2409 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 2410 | "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", 2411 | "engines": [ 2412 | "node >=0.6.0" 2413 | ], 2414 | "dependencies": { 2415 | "assert-plus": "^1.0.0", 2416 | "core-util-is": "1.0.2", 2417 | "extsprintf": "^1.2.0" 2418 | } 2419 | }, 2420 | "node_modules/which": { 2421 | "version": "1.3.1", 2422 | "dev": true, 2423 | "license": "ISC", 2424 | "dependencies": { 2425 | "isexe": "^2.0.0" 2426 | }, 2427 | "bin": { 2428 | "which": "bin/which" 2429 | } 2430 | }, 2431 | "node_modules/word-wrap": { 2432 | "version": "1.2.5", 2433 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", 2434 | "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", 2435 | "dev": true, 2436 | "engines": { 2437 | "node": ">=0.10.0" 2438 | } 2439 | }, 2440 | "node_modules/wordwrap": { 2441 | "version": "0.0.3", 2442 | "license": "MIT", 2443 | "engines": { 2444 | "node": ">=0.4.0" 2445 | } 2446 | }, 2447 | "node_modules/wrappy": { 2448 | "version": "1.0.2", 2449 | "dev": true, 2450 | "license": "ISC" 2451 | }, 2452 | "node_modules/write": { 2453 | "version": "1.0.3", 2454 | "dev": true, 2455 | "license": "MIT", 2456 | "dependencies": { 2457 | "mkdirp": "^0.5.1" 2458 | }, 2459 | "engines": { 2460 | "node": ">=4" 2461 | } 2462 | } 2463 | } 2464 | } 2465 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "minecraft-launcher-core", 3 | "version": "3.18.2", 4 | "description": "Lightweight module that downloads and runs Minecraft using javascript / NodeJS", 5 | "main": "index.js", 6 | "dependencies": { 7 | "adm-zip": "^0.4.13", 8 | "checksum": "^0.1.1", 9 | "request": "^2.88.2", 10 | "uuid": "^8.3.2" 11 | }, 12 | "devDependencies": { 13 | "@types/checksum": "^0.1.35", 14 | "@types/node": "^14.0.27", 15 | "eslint": "^6.8.0", 16 | "eslint-config-standard": "^14.1.1", 17 | "eslint-plugin-import": "^2.20.2", 18 | "eslint-plugin-node": "^11.1.0", 19 | "eslint-plugin-promise": "^4.2.1", 20 | "eslint-plugin-standard": "^4.0.1" 21 | }, 22 | "scripts": { 23 | "test": "eslint ." 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "git+https://github.com/Pierce01/MinecraftLauncher-core.git" 28 | }, 29 | "keywords": [ 30 | "minecraft", 31 | "minecraft-launcher-node", 32 | "minecraft-launcher", 33 | "launcher", 34 | "minecraft-forge" 35 | ], 36 | "author": "Pierce Harriz", 37 | "license": "MIT", 38 | "bugs": { 39 | "url": "https://github.com/Pierce01/MinecraftLauncher-core/issues" 40 | }, 41 | "homepage": "https://github.com/Pierce01/MinecraftLauncher-core#readme" 42 | } 43 | --------------------------------------------------------------------------------