├── .github └── workflows │ └── npm-publish.yml ├── .gitignore ├── .npmignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── bin └── cli.js ├── package-lock.json ├── package.json ├── src ├── from │ ├── asdf.ts │ ├── envs.ts │ ├── gradle.ts │ ├── homebrew.ts │ ├── jabba.ts │ ├── jbang.ts │ ├── jenv.ts │ ├── linux.ts │ ├── macOS.ts │ ├── sdkman.ts │ └── windows.ts ├── index.ts ├── logger.ts └── utils.ts ├── test └── test.js └── tsconfig.json /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created 2 | # For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages 3 | 4 | name: Node.js Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 16 18 | - run: npm ci 19 | - run: npm test 20 | 21 | publish-npm: 22 | needs: build 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v3 26 | - uses: actions/setup-node@v3 27 | with: 28 | node-version: 16 29 | registry-url: https://registry.npmjs.org/ 30 | - run: npm ci 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.tgz 2 | src 3 | test 4 | tsconfig.json 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | This is changelog of node-jdk-utils project. 2 | 3 | ## 0.5.1 4 | - Fixed: `/usr` detected as a wrong Java home on macOS. [#15](https://github.com/Eskibear/node-jdk-utils/issues/15) 5 | 6 | ## 0.5.0 7 | - Scan default installation directory for Zulu on Windows.[#12](https://github.com/Eskibear/node-jdk-utils/pull/12) 8 | - Traverse entires in env.PATH to cover all possible locations. Note, this increases disk I/O which will affect the performance depending on number of entries of env.PATH. [#13](https://github.com/Eskibear/node-jdk-utils/pull/13) 9 | - Add `skipFrom` option which allow you to skip scanning from specific source to improve overall performance. [#14](https://github.com/Eskibear/node-jdk-utils/pull/14) 10 | 11 | ## 0.4.6 12 | - Fix gradle toolchains Windows path structure. [#11](https://github.com/Eskibear/node-jdk-utils/pull/11) 13 | 14 | ## 0.4.5 15 | - Support to detect JDKs installed by Gradle. [#9](https://github.com/Eskibear/node-jdk-utils/issues/9)] 16 | 17 | ## 0.4.4 18 | - Better support for ASDF, searching `env.ASDF_DATA_DIR` instead of `env.ASDF_DIR`. [#8](https://github.com/Eskibear/node-jdk-utils/pull/8) 19 | 20 | ## 0.4.3 21 | - Support to detect JDKs installed by ASDF. [#7](https://github.com/Eskibear/node-jdk-utils/pull/7) 22 | 23 | ## 0.4.2 24 | ### Added 25 | - Support to detect JDKs installed by Homebrew, covering macOS Apple Silicon and Linux. 26 | 27 | ## 0.4.1 28 | ### Added 29 | - Add CLI to list all detected runtimes, which is convenient for testing coverage. 30 | 31 | ## 0.4.0 32 | ### Added 33 | - Support to detect JDKs installed by Homebrew (macOS only). 34 | 35 | ### Fixed 36 | - For candidates from envs like `PATH`, resolve symbolic links of `bin/java` to get real path of the installation. 37 | 38 | ## 0.3.1 39 | ### Changed 40 | - Simplify APIs. 41 | 42 | ## 0.3.0 43 | ### Added 44 | - Support to detect JDKs installed by jabba. 45 | - New API **getSources(runtime)** to list sources where a Java Runtime is found. 46 | 47 | ## 0.2.1 48 | ### Fixed 49 | - For macOS, add below sources to detect runtimes: 50 | - `~/Library/Java/JavaVirtualMachines` 51 | - Output of `java_home -V` 52 | 53 | ## 0.2.0 54 | ### Added 55 | - New API **getRuntime(homedir, options)**: verify if given directory is a valid runtime, and provide more information if it is. 56 | - Export type defitions for better usablity. 57 | 58 | ## 0.1.0 59 | ### Added 60 | - New API **findRuntimes(options)**: list all Java runtimes installed on local machine. It searches locations deducted from environment variables (PATH/JAVA_HOME/JDK_HOME), SDKMAN installation directory, jEnv configurations, and default installation locations of popular distributions. 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Yan Zhang 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. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-jdk-utils 2 | 3 | NPM version 4 | NPM downloads 5 | 6 | A collection of Java related utils. 7 | 8 | ## Installation 9 | ```bash 10 | npm i jdk-utils 11 | ``` 12 | 13 | ## Usage 14 | 15 | ### findJavaRuntime 16 | 17 | Find Java runtime from all possible locations on your machine. 18 | Covering: 19 | * `JAVA_HOME`. 20 | * JDK-like paths from `PATH`. 21 | * SDKMAN installation location. 22 | * jabba installation location, i.e. `~/.jabba/jdk` 23 | * [JBang](https://jbang.dev/) installation location, i.e. `~/.jbang/cache/jdks` 24 | * ASDF installation location. 25 | * JDK installations managed by [Gradle](https://docs.gradle.org/8.1/userguide/toolchains.html), e.g. `~/.gradle/jdk` 26 | * Links specified in jEnv. 27 | * Homebrew installation: 28 | * macOS Intel: `/usr/local` 29 | * macOS Apple Silicon: `/opt/homebrew` 30 | * Linux: `/home/linuxbrew/.linuxbrew` 31 | * Platform-specific conventional installation location: 32 | * Linux: `/usr/lib/jvm` 33 | * macOS: `/Library/Java/JavaVirtualMachines`, `~/Library/Java/JavaVirtualMachines`, output of `java_home -V`. 34 | * Windows: JDK-like folders under `%ProgramFiles%` and `%LocalAppData%`, 35 | 36 | Note: If you want to skip scanning a certain source for better performance, you can specify `skipFrom` options when calling the API. 37 | 38 | #### CLI 39 | 40 | Below command lists all detected JDKs with details. 41 | ```bash 42 | npx jdk-utils 43 | ``` 44 | 45 | 46 | #### callback-style 47 | 48 | ```ts 49 | require("jdk-utils").findRuntimes().then(console.log) 50 | /* 51 | [{ 52 | homedir: '/home/username/.sdkman/candidates/java/17.0.1-ms', 53 | }, { 54 | homedir: '/usr/lib/jvm/java-11-openjdk-amd64', 55 | }, 56 | ... 57 | ] 58 | */ 59 | ``` 60 | 61 | #### promise-style 62 | ```ts 63 | import { findRuntimes } from "jdk-utils"; 64 | await findRuntimes({checkJavac: true, withVersion: true, withTags: true}); 65 | /* 66 | [{ 67 | homedir: '/home/yanzh/.sdkman/candidates/java/17.0.1-ms', 68 | hasJavac: true, 69 | isFromSDKMAN: true, 70 | version: { java_version: '17.0.1', major: 17 } 71 | }, { 72 | homedir: '/usr/lib/jvm/java-11-openjdk-amd64', 73 | hasJavac: true, 74 | version: { java_version: '11.0.7', major: 11 } 75 | }, 76 | ... 77 | ] 78 | */ 79 | ``` 80 | 81 | -------------------------------------------------------------------------------- /bin/cli.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | async function listAll() { 4 | const utils = require("../dist/index"); 5 | const label = "Listing JDKs"; 6 | console.time(label); 7 | const jdks = await utils.findRuntimes({ withTags: true, withVersion: true, checkJavac: true }); 8 | console.timeEnd(label); 9 | console.log("Found: ", jdks.length); 10 | console.log(jdks); 11 | } 12 | 13 | listAll(); 14 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jdk-utils", 3 | "version": "0.5.1", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "jdk-utils", 9 | "version": "0.5.1", 10 | "license": "MIT", 11 | "bin": { 12 | "jdk-utils": "bin/cli.js" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "^16.11.8", 16 | "chai": "^4.3.4", 17 | "mocha": "^9.2.2", 18 | "typescript": "^4.5.2" 19 | } 20 | }, 21 | "node_modules/@types/node": { 22 | "version": "16.11.8", 23 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.8.tgz", 24 | "integrity": "sha512-hmT5gfpRkkHr7DZZHMf3jBe/zNcVGN+jXSL2f8nAsYfBPxQFToKwQlS/zES4Sjp488Bi73i+p6bvrNRRGU0x9Q==", 25 | "dev": true 26 | }, 27 | "node_modules/@ungap/promise-all-settled": { 28 | "version": "1.1.2", 29 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 30 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 31 | "dev": true 32 | }, 33 | "node_modules/ansi-colors": { 34 | "version": "4.1.1", 35 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 36 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 37 | "dev": true, 38 | "engines": { 39 | "node": ">=6" 40 | } 41 | }, 42 | "node_modules/ansi-regex": { 43 | "version": "5.0.1", 44 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 45 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 46 | "dev": true, 47 | "engines": { 48 | "node": ">=8" 49 | } 50 | }, 51 | "node_modules/ansi-styles": { 52 | "version": "4.3.0", 53 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 54 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 55 | "dev": true, 56 | "dependencies": { 57 | "color-convert": "^2.0.1" 58 | }, 59 | "engines": { 60 | "node": ">=8" 61 | }, 62 | "funding": { 63 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 64 | } 65 | }, 66 | "node_modules/anymatch": { 67 | "version": "3.1.2", 68 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 69 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 70 | "dev": true, 71 | "dependencies": { 72 | "normalize-path": "^3.0.0", 73 | "picomatch": "^2.0.4" 74 | }, 75 | "engines": { 76 | "node": ">= 8" 77 | } 78 | }, 79 | "node_modules/argparse": { 80 | "version": "2.0.1", 81 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 82 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 83 | "dev": true 84 | }, 85 | "node_modules/assertion-error": { 86 | "version": "1.1.0", 87 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 88 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 89 | "dev": true, 90 | "engines": { 91 | "node": "*" 92 | } 93 | }, 94 | "node_modules/balanced-match": { 95 | "version": "1.0.2", 96 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 97 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 98 | "dev": true 99 | }, 100 | "node_modules/binary-extensions": { 101 | "version": "2.2.0", 102 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 103 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 104 | "dev": true, 105 | "engines": { 106 | "node": ">=8" 107 | } 108 | }, 109 | "node_modules/brace-expansion": { 110 | "version": "1.1.11", 111 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 112 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 113 | "dev": true, 114 | "dependencies": { 115 | "balanced-match": "^1.0.0", 116 | "concat-map": "0.0.1" 117 | } 118 | }, 119 | "node_modules/braces": { 120 | "version": "3.0.2", 121 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 122 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 123 | "dev": true, 124 | "dependencies": { 125 | "fill-range": "^7.0.1" 126 | }, 127 | "engines": { 128 | "node": ">=8" 129 | } 130 | }, 131 | "node_modules/browser-stdout": { 132 | "version": "1.3.1", 133 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 134 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 135 | "dev": true 136 | }, 137 | "node_modules/camelcase": { 138 | "version": "6.3.0", 139 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 140 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 141 | "dev": true, 142 | "engines": { 143 | "node": ">=10" 144 | }, 145 | "funding": { 146 | "url": "https://github.com/sponsors/sindresorhus" 147 | } 148 | }, 149 | "node_modules/chai": { 150 | "version": "4.3.4", 151 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", 152 | "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", 153 | "dev": true, 154 | "dependencies": { 155 | "assertion-error": "^1.1.0", 156 | "check-error": "^1.0.2", 157 | "deep-eql": "^3.0.1", 158 | "get-func-name": "^2.0.0", 159 | "pathval": "^1.1.1", 160 | "type-detect": "^4.0.5" 161 | }, 162 | "engines": { 163 | "node": ">=4" 164 | } 165 | }, 166 | "node_modules/chalk": { 167 | "version": "4.1.2", 168 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 169 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 170 | "dev": true, 171 | "dependencies": { 172 | "ansi-styles": "^4.1.0", 173 | "supports-color": "^7.1.0" 174 | }, 175 | "engines": { 176 | "node": ">=10" 177 | }, 178 | "funding": { 179 | "url": "https://github.com/chalk/chalk?sponsor=1" 180 | } 181 | }, 182 | "node_modules/chalk/node_modules/supports-color": { 183 | "version": "7.2.0", 184 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 185 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 186 | "dev": true, 187 | "dependencies": { 188 | "has-flag": "^4.0.0" 189 | }, 190 | "engines": { 191 | "node": ">=8" 192 | } 193 | }, 194 | "node_modules/check-error": { 195 | "version": "1.0.2", 196 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 197 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 198 | "dev": true, 199 | "engines": { 200 | "node": "*" 201 | } 202 | }, 203 | "node_modules/chokidar": { 204 | "version": "3.5.3", 205 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 206 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 207 | "dev": true, 208 | "funding": [ 209 | { 210 | "type": "individual", 211 | "url": "https://paulmillr.com/funding/" 212 | } 213 | ], 214 | "dependencies": { 215 | "anymatch": "~3.1.2", 216 | "braces": "~3.0.2", 217 | "glob-parent": "~5.1.2", 218 | "is-binary-path": "~2.1.0", 219 | "is-glob": "~4.0.1", 220 | "normalize-path": "~3.0.0", 221 | "readdirp": "~3.6.0" 222 | }, 223 | "engines": { 224 | "node": ">= 8.10.0" 225 | }, 226 | "optionalDependencies": { 227 | "fsevents": "~2.3.2" 228 | } 229 | }, 230 | "node_modules/cliui": { 231 | "version": "7.0.4", 232 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 233 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 234 | "dev": true, 235 | "dependencies": { 236 | "string-width": "^4.2.0", 237 | "strip-ansi": "^6.0.0", 238 | "wrap-ansi": "^7.0.0" 239 | } 240 | }, 241 | "node_modules/color-convert": { 242 | "version": "2.0.1", 243 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 244 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 245 | "dev": true, 246 | "dependencies": { 247 | "color-name": "~1.1.4" 248 | }, 249 | "engines": { 250 | "node": ">=7.0.0" 251 | } 252 | }, 253 | "node_modules/color-name": { 254 | "version": "1.1.4", 255 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 256 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 257 | "dev": true 258 | }, 259 | "node_modules/concat-map": { 260 | "version": "0.0.1", 261 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 262 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 263 | "dev": true 264 | }, 265 | "node_modules/debug": { 266 | "version": "4.3.3", 267 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 268 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 269 | "dev": true, 270 | "dependencies": { 271 | "ms": "2.1.2" 272 | }, 273 | "engines": { 274 | "node": ">=6.0" 275 | }, 276 | "peerDependenciesMeta": { 277 | "supports-color": { 278 | "optional": true 279 | } 280 | } 281 | }, 282 | "node_modules/debug/node_modules/ms": { 283 | "version": "2.1.2", 284 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 285 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 286 | "dev": true 287 | }, 288 | "node_modules/decamelize": { 289 | "version": "4.0.0", 290 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 291 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 292 | "dev": true, 293 | "engines": { 294 | "node": ">=10" 295 | }, 296 | "funding": { 297 | "url": "https://github.com/sponsors/sindresorhus" 298 | } 299 | }, 300 | "node_modules/deep-eql": { 301 | "version": "3.0.1", 302 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 303 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 304 | "dev": true, 305 | "dependencies": { 306 | "type-detect": "^4.0.0" 307 | }, 308 | "engines": { 309 | "node": ">=0.12" 310 | } 311 | }, 312 | "node_modules/diff": { 313 | "version": "5.0.0", 314 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 315 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 316 | "dev": true, 317 | "engines": { 318 | "node": ">=0.3.1" 319 | } 320 | }, 321 | "node_modules/emoji-regex": { 322 | "version": "8.0.0", 323 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 324 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 325 | "dev": true 326 | }, 327 | "node_modules/escalade": { 328 | "version": "3.1.1", 329 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 330 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 331 | "dev": true, 332 | "engines": { 333 | "node": ">=6" 334 | } 335 | }, 336 | "node_modules/escape-string-regexp": { 337 | "version": "4.0.0", 338 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 339 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 340 | "dev": true, 341 | "engines": { 342 | "node": ">=10" 343 | }, 344 | "funding": { 345 | "url": "https://github.com/sponsors/sindresorhus" 346 | } 347 | }, 348 | "node_modules/fill-range": { 349 | "version": "7.0.1", 350 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 351 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 352 | "dev": true, 353 | "dependencies": { 354 | "to-regex-range": "^5.0.1" 355 | }, 356 | "engines": { 357 | "node": ">=8" 358 | } 359 | }, 360 | "node_modules/find-up": { 361 | "version": "5.0.0", 362 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 363 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 364 | "dev": true, 365 | "dependencies": { 366 | "locate-path": "^6.0.0", 367 | "path-exists": "^4.0.0" 368 | }, 369 | "engines": { 370 | "node": ">=10" 371 | }, 372 | "funding": { 373 | "url": "https://github.com/sponsors/sindresorhus" 374 | } 375 | }, 376 | "node_modules/flat": { 377 | "version": "5.0.2", 378 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 379 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 380 | "dev": true, 381 | "bin": { 382 | "flat": "cli.js" 383 | } 384 | }, 385 | "node_modules/fs.realpath": { 386 | "version": "1.0.0", 387 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 388 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 389 | "dev": true 390 | }, 391 | "node_modules/fsevents": { 392 | "version": "2.3.2", 393 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 394 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 395 | "dev": true, 396 | "hasInstallScript": true, 397 | "optional": true, 398 | "os": [ 399 | "darwin" 400 | ], 401 | "engines": { 402 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 403 | } 404 | }, 405 | "node_modules/get-caller-file": { 406 | "version": "2.0.5", 407 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 408 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 409 | "dev": true, 410 | "engines": { 411 | "node": "6.* || 8.* || >= 10.*" 412 | } 413 | }, 414 | "node_modules/get-func-name": { 415 | "version": "2.0.0", 416 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 417 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 418 | "dev": true, 419 | "engines": { 420 | "node": "*" 421 | } 422 | }, 423 | "node_modules/glob": { 424 | "version": "7.2.0", 425 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 426 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 427 | "dev": true, 428 | "dependencies": { 429 | "fs.realpath": "^1.0.0", 430 | "inflight": "^1.0.4", 431 | "inherits": "2", 432 | "minimatch": "^3.0.4", 433 | "once": "^1.3.0", 434 | "path-is-absolute": "^1.0.0" 435 | }, 436 | "engines": { 437 | "node": "*" 438 | }, 439 | "funding": { 440 | "url": "https://github.com/sponsors/isaacs" 441 | } 442 | }, 443 | "node_modules/glob-parent": { 444 | "version": "5.1.2", 445 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 446 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 447 | "dev": true, 448 | "dependencies": { 449 | "is-glob": "^4.0.1" 450 | }, 451 | "engines": { 452 | "node": ">= 6" 453 | } 454 | }, 455 | "node_modules/glob/node_modules/minimatch": { 456 | "version": "3.1.2", 457 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 458 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 459 | "dev": true, 460 | "dependencies": { 461 | "brace-expansion": "^1.1.7" 462 | }, 463 | "engines": { 464 | "node": "*" 465 | } 466 | }, 467 | "node_modules/growl": { 468 | "version": "1.10.5", 469 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 470 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 471 | "dev": true, 472 | "engines": { 473 | "node": ">=4.x" 474 | } 475 | }, 476 | "node_modules/has-flag": { 477 | "version": "4.0.0", 478 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 479 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 480 | "dev": true, 481 | "engines": { 482 | "node": ">=8" 483 | } 484 | }, 485 | "node_modules/he": { 486 | "version": "1.2.0", 487 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 488 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 489 | "dev": true, 490 | "bin": { 491 | "he": "bin/he" 492 | } 493 | }, 494 | "node_modules/inflight": { 495 | "version": "1.0.6", 496 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 497 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 498 | "dev": true, 499 | "dependencies": { 500 | "once": "^1.3.0", 501 | "wrappy": "1" 502 | } 503 | }, 504 | "node_modules/inherits": { 505 | "version": "2.0.4", 506 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 507 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 508 | "dev": true 509 | }, 510 | "node_modules/is-binary-path": { 511 | "version": "2.1.0", 512 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 513 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 514 | "dev": true, 515 | "dependencies": { 516 | "binary-extensions": "^2.0.0" 517 | }, 518 | "engines": { 519 | "node": ">=8" 520 | } 521 | }, 522 | "node_modules/is-extglob": { 523 | "version": "2.1.1", 524 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 525 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 526 | "dev": true, 527 | "engines": { 528 | "node": ">=0.10.0" 529 | } 530 | }, 531 | "node_modules/is-fullwidth-code-point": { 532 | "version": "3.0.0", 533 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 534 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 535 | "dev": true, 536 | "engines": { 537 | "node": ">=8" 538 | } 539 | }, 540 | "node_modules/is-glob": { 541 | "version": "4.0.3", 542 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 543 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 544 | "dev": true, 545 | "dependencies": { 546 | "is-extglob": "^2.1.1" 547 | }, 548 | "engines": { 549 | "node": ">=0.10.0" 550 | } 551 | }, 552 | "node_modules/is-number": { 553 | "version": "7.0.0", 554 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 555 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 556 | "dev": true, 557 | "engines": { 558 | "node": ">=0.12.0" 559 | } 560 | }, 561 | "node_modules/is-plain-obj": { 562 | "version": "2.1.0", 563 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 564 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 565 | "dev": true, 566 | "engines": { 567 | "node": ">=8" 568 | } 569 | }, 570 | "node_modules/is-unicode-supported": { 571 | "version": "0.1.0", 572 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 573 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 574 | "dev": true, 575 | "engines": { 576 | "node": ">=10" 577 | }, 578 | "funding": { 579 | "url": "https://github.com/sponsors/sindresorhus" 580 | } 581 | }, 582 | "node_modules/isexe": { 583 | "version": "2.0.0", 584 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 585 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 586 | "dev": true 587 | }, 588 | "node_modules/js-yaml": { 589 | "version": "4.1.0", 590 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 591 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 592 | "dev": true, 593 | "dependencies": { 594 | "argparse": "^2.0.1" 595 | }, 596 | "bin": { 597 | "js-yaml": "bin/js-yaml.js" 598 | } 599 | }, 600 | "node_modules/locate-path": { 601 | "version": "6.0.0", 602 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 603 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 604 | "dev": true, 605 | "dependencies": { 606 | "p-locate": "^5.0.0" 607 | }, 608 | "engines": { 609 | "node": ">=10" 610 | }, 611 | "funding": { 612 | "url": "https://github.com/sponsors/sindresorhus" 613 | } 614 | }, 615 | "node_modules/log-symbols": { 616 | "version": "4.1.0", 617 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 618 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 619 | "dev": true, 620 | "dependencies": { 621 | "chalk": "^4.1.0", 622 | "is-unicode-supported": "^0.1.0" 623 | }, 624 | "engines": { 625 | "node": ">=10" 626 | }, 627 | "funding": { 628 | "url": "https://github.com/sponsors/sindresorhus" 629 | } 630 | }, 631 | "node_modules/minimatch": { 632 | "version": "4.2.1", 633 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", 634 | "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", 635 | "dev": true, 636 | "dependencies": { 637 | "brace-expansion": "^1.1.7" 638 | }, 639 | "engines": { 640 | "node": ">=10" 641 | } 642 | }, 643 | "node_modules/mocha": { 644 | "version": "9.2.2", 645 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", 646 | "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", 647 | "dev": true, 648 | "dependencies": { 649 | "@ungap/promise-all-settled": "1.1.2", 650 | "ansi-colors": "4.1.1", 651 | "browser-stdout": "1.3.1", 652 | "chokidar": "3.5.3", 653 | "debug": "4.3.3", 654 | "diff": "5.0.0", 655 | "escape-string-regexp": "4.0.0", 656 | "find-up": "5.0.0", 657 | "glob": "7.2.0", 658 | "growl": "1.10.5", 659 | "he": "1.2.0", 660 | "js-yaml": "4.1.0", 661 | "log-symbols": "4.1.0", 662 | "minimatch": "4.2.1", 663 | "ms": "2.1.3", 664 | "nanoid": "3.3.1", 665 | "serialize-javascript": "6.0.0", 666 | "strip-json-comments": "3.1.1", 667 | "supports-color": "8.1.1", 668 | "which": "2.0.2", 669 | "workerpool": "6.2.0", 670 | "yargs": "16.2.0", 671 | "yargs-parser": "20.2.4", 672 | "yargs-unparser": "2.0.0" 673 | }, 674 | "bin": { 675 | "_mocha": "bin/_mocha", 676 | "mocha": "bin/mocha" 677 | }, 678 | "engines": { 679 | "node": ">= 12.0.0" 680 | }, 681 | "funding": { 682 | "type": "opencollective", 683 | "url": "https://opencollective.com/mochajs" 684 | } 685 | }, 686 | "node_modules/ms": { 687 | "version": "2.1.3", 688 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 689 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 690 | "dev": true 691 | }, 692 | "node_modules/nanoid": { 693 | "version": "3.3.1", 694 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", 695 | "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", 696 | "dev": true, 697 | "bin": { 698 | "nanoid": "bin/nanoid.cjs" 699 | }, 700 | "engines": { 701 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 702 | } 703 | }, 704 | "node_modules/normalize-path": { 705 | "version": "3.0.0", 706 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 707 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 708 | "dev": true, 709 | "engines": { 710 | "node": ">=0.10.0" 711 | } 712 | }, 713 | "node_modules/once": { 714 | "version": "1.4.0", 715 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 716 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 717 | "dev": true, 718 | "dependencies": { 719 | "wrappy": "1" 720 | } 721 | }, 722 | "node_modules/p-limit": { 723 | "version": "3.1.0", 724 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 725 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 726 | "dev": true, 727 | "dependencies": { 728 | "yocto-queue": "^0.1.0" 729 | }, 730 | "engines": { 731 | "node": ">=10" 732 | }, 733 | "funding": { 734 | "url": "https://github.com/sponsors/sindresorhus" 735 | } 736 | }, 737 | "node_modules/p-locate": { 738 | "version": "5.0.0", 739 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 740 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 741 | "dev": true, 742 | "dependencies": { 743 | "p-limit": "^3.0.2" 744 | }, 745 | "engines": { 746 | "node": ">=10" 747 | }, 748 | "funding": { 749 | "url": "https://github.com/sponsors/sindresorhus" 750 | } 751 | }, 752 | "node_modules/path-exists": { 753 | "version": "4.0.0", 754 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 755 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 756 | "dev": true, 757 | "engines": { 758 | "node": ">=8" 759 | } 760 | }, 761 | "node_modules/path-is-absolute": { 762 | "version": "1.0.1", 763 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 764 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 765 | "dev": true, 766 | "engines": { 767 | "node": ">=0.10.0" 768 | } 769 | }, 770 | "node_modules/pathval": { 771 | "version": "1.1.1", 772 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 773 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 774 | "dev": true, 775 | "engines": { 776 | "node": "*" 777 | } 778 | }, 779 | "node_modules/picomatch": { 780 | "version": "2.3.1", 781 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 782 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 783 | "dev": true, 784 | "engines": { 785 | "node": ">=8.6" 786 | }, 787 | "funding": { 788 | "url": "https://github.com/sponsors/jonschlinkert" 789 | } 790 | }, 791 | "node_modules/randombytes": { 792 | "version": "2.1.0", 793 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 794 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 795 | "dev": true, 796 | "dependencies": { 797 | "safe-buffer": "^5.1.0" 798 | } 799 | }, 800 | "node_modules/readdirp": { 801 | "version": "3.6.0", 802 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 803 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 804 | "dev": true, 805 | "dependencies": { 806 | "picomatch": "^2.2.1" 807 | }, 808 | "engines": { 809 | "node": ">=8.10.0" 810 | } 811 | }, 812 | "node_modules/require-directory": { 813 | "version": "2.1.1", 814 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 815 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 816 | "dev": true, 817 | "engines": { 818 | "node": ">=0.10.0" 819 | } 820 | }, 821 | "node_modules/safe-buffer": { 822 | "version": "5.2.1", 823 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 824 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 825 | "dev": true, 826 | "funding": [ 827 | { 828 | "type": "github", 829 | "url": "https://github.com/sponsors/feross" 830 | }, 831 | { 832 | "type": "patreon", 833 | "url": "https://www.patreon.com/feross" 834 | }, 835 | { 836 | "type": "consulting", 837 | "url": "https://feross.org/support" 838 | } 839 | ] 840 | }, 841 | "node_modules/serialize-javascript": { 842 | "version": "6.0.0", 843 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 844 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 845 | "dev": true, 846 | "dependencies": { 847 | "randombytes": "^2.1.0" 848 | } 849 | }, 850 | "node_modules/string-width": { 851 | "version": "4.2.3", 852 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 853 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 854 | "dev": true, 855 | "dependencies": { 856 | "emoji-regex": "^8.0.0", 857 | "is-fullwidth-code-point": "^3.0.0", 858 | "strip-ansi": "^6.0.1" 859 | }, 860 | "engines": { 861 | "node": ">=8" 862 | } 863 | }, 864 | "node_modules/strip-ansi": { 865 | "version": "6.0.1", 866 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 867 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 868 | "dev": true, 869 | "dependencies": { 870 | "ansi-regex": "^5.0.1" 871 | }, 872 | "engines": { 873 | "node": ">=8" 874 | } 875 | }, 876 | "node_modules/strip-json-comments": { 877 | "version": "3.1.1", 878 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 879 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 880 | "dev": true, 881 | "engines": { 882 | "node": ">=8" 883 | }, 884 | "funding": { 885 | "url": "https://github.com/sponsors/sindresorhus" 886 | } 887 | }, 888 | "node_modules/supports-color": { 889 | "version": "8.1.1", 890 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 891 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 892 | "dev": true, 893 | "dependencies": { 894 | "has-flag": "^4.0.0" 895 | }, 896 | "engines": { 897 | "node": ">=10" 898 | }, 899 | "funding": { 900 | "url": "https://github.com/chalk/supports-color?sponsor=1" 901 | } 902 | }, 903 | "node_modules/to-regex-range": { 904 | "version": "5.0.1", 905 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 906 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 907 | "dev": true, 908 | "dependencies": { 909 | "is-number": "^7.0.0" 910 | }, 911 | "engines": { 912 | "node": ">=8.0" 913 | } 914 | }, 915 | "node_modules/type-detect": { 916 | "version": "4.0.8", 917 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 918 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 919 | "dev": true, 920 | "engines": { 921 | "node": ">=4" 922 | } 923 | }, 924 | "node_modules/typescript": { 925 | "version": "4.5.2", 926 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", 927 | "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", 928 | "dev": true, 929 | "bin": { 930 | "tsc": "bin/tsc", 931 | "tsserver": "bin/tsserver" 932 | }, 933 | "engines": { 934 | "node": ">=4.2.0" 935 | } 936 | }, 937 | "node_modules/which": { 938 | "version": "2.0.2", 939 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 940 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 941 | "dev": true, 942 | "dependencies": { 943 | "isexe": "^2.0.0" 944 | }, 945 | "bin": { 946 | "node-which": "bin/node-which" 947 | }, 948 | "engines": { 949 | "node": ">= 8" 950 | } 951 | }, 952 | "node_modules/workerpool": { 953 | "version": "6.2.0", 954 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", 955 | "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", 956 | "dev": true 957 | }, 958 | "node_modules/wrap-ansi": { 959 | "version": "7.0.0", 960 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 961 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 962 | "dev": true, 963 | "dependencies": { 964 | "ansi-styles": "^4.0.0", 965 | "string-width": "^4.1.0", 966 | "strip-ansi": "^6.0.0" 967 | }, 968 | "engines": { 969 | "node": ">=10" 970 | }, 971 | "funding": { 972 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 973 | } 974 | }, 975 | "node_modules/wrappy": { 976 | "version": "1.0.2", 977 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 978 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 979 | "dev": true 980 | }, 981 | "node_modules/y18n": { 982 | "version": "5.0.8", 983 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 984 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 985 | "dev": true, 986 | "engines": { 987 | "node": ">=10" 988 | } 989 | }, 990 | "node_modules/yargs": { 991 | "version": "16.2.0", 992 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 993 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 994 | "dev": true, 995 | "dependencies": { 996 | "cliui": "^7.0.2", 997 | "escalade": "^3.1.1", 998 | "get-caller-file": "^2.0.5", 999 | "require-directory": "^2.1.1", 1000 | "string-width": "^4.2.0", 1001 | "y18n": "^5.0.5", 1002 | "yargs-parser": "^20.2.2" 1003 | }, 1004 | "engines": { 1005 | "node": ">=10" 1006 | } 1007 | }, 1008 | "node_modules/yargs-parser": { 1009 | "version": "20.2.4", 1010 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 1011 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 1012 | "dev": true, 1013 | "engines": { 1014 | "node": ">=10" 1015 | } 1016 | }, 1017 | "node_modules/yargs-unparser": { 1018 | "version": "2.0.0", 1019 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 1020 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 1021 | "dev": true, 1022 | "dependencies": { 1023 | "camelcase": "^6.0.0", 1024 | "decamelize": "^4.0.0", 1025 | "flat": "^5.0.2", 1026 | "is-plain-obj": "^2.1.0" 1027 | }, 1028 | "engines": { 1029 | "node": ">=10" 1030 | } 1031 | }, 1032 | "node_modules/yocto-queue": { 1033 | "version": "0.1.0", 1034 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1035 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1036 | "dev": true, 1037 | "engines": { 1038 | "node": ">=10" 1039 | }, 1040 | "funding": { 1041 | "url": "https://github.com/sponsors/sindresorhus" 1042 | } 1043 | } 1044 | }, 1045 | "dependencies": { 1046 | "@types/node": { 1047 | "version": "16.11.8", 1048 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.8.tgz", 1049 | "integrity": "sha512-hmT5gfpRkkHr7DZZHMf3jBe/zNcVGN+jXSL2f8nAsYfBPxQFToKwQlS/zES4Sjp488Bi73i+p6bvrNRRGU0x9Q==", 1050 | "dev": true 1051 | }, 1052 | "@ungap/promise-all-settled": { 1053 | "version": "1.1.2", 1054 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 1055 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 1056 | "dev": true 1057 | }, 1058 | "ansi-colors": { 1059 | "version": "4.1.1", 1060 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 1061 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 1062 | "dev": true 1063 | }, 1064 | "ansi-regex": { 1065 | "version": "5.0.1", 1066 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1067 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1068 | "dev": true 1069 | }, 1070 | "ansi-styles": { 1071 | "version": "4.3.0", 1072 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1073 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1074 | "dev": true, 1075 | "requires": { 1076 | "color-convert": "^2.0.1" 1077 | } 1078 | }, 1079 | "anymatch": { 1080 | "version": "3.1.2", 1081 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", 1082 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", 1083 | "dev": true, 1084 | "requires": { 1085 | "normalize-path": "^3.0.0", 1086 | "picomatch": "^2.0.4" 1087 | } 1088 | }, 1089 | "argparse": { 1090 | "version": "2.0.1", 1091 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 1092 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 1093 | "dev": true 1094 | }, 1095 | "assertion-error": { 1096 | "version": "1.1.0", 1097 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 1098 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 1099 | "dev": true 1100 | }, 1101 | "balanced-match": { 1102 | "version": "1.0.2", 1103 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1104 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1105 | "dev": true 1106 | }, 1107 | "binary-extensions": { 1108 | "version": "2.2.0", 1109 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 1110 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 1111 | "dev": true 1112 | }, 1113 | "brace-expansion": { 1114 | "version": "1.1.11", 1115 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 1116 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 1117 | "dev": true, 1118 | "requires": { 1119 | "balanced-match": "^1.0.0", 1120 | "concat-map": "0.0.1" 1121 | } 1122 | }, 1123 | "braces": { 1124 | "version": "3.0.2", 1125 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 1126 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 1127 | "dev": true, 1128 | "requires": { 1129 | "fill-range": "^7.0.1" 1130 | } 1131 | }, 1132 | "browser-stdout": { 1133 | "version": "1.3.1", 1134 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 1135 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 1136 | "dev": true 1137 | }, 1138 | "camelcase": { 1139 | "version": "6.3.0", 1140 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 1141 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 1142 | "dev": true 1143 | }, 1144 | "chai": { 1145 | "version": "4.3.4", 1146 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.4.tgz", 1147 | "integrity": "sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==", 1148 | "dev": true, 1149 | "requires": { 1150 | "assertion-error": "^1.1.0", 1151 | "check-error": "^1.0.2", 1152 | "deep-eql": "^3.0.1", 1153 | "get-func-name": "^2.0.0", 1154 | "pathval": "^1.1.1", 1155 | "type-detect": "^4.0.5" 1156 | } 1157 | }, 1158 | "chalk": { 1159 | "version": "4.1.2", 1160 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1161 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1162 | "dev": true, 1163 | "requires": { 1164 | "ansi-styles": "^4.1.0", 1165 | "supports-color": "^7.1.0" 1166 | }, 1167 | "dependencies": { 1168 | "supports-color": { 1169 | "version": "7.2.0", 1170 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1171 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1172 | "dev": true, 1173 | "requires": { 1174 | "has-flag": "^4.0.0" 1175 | } 1176 | } 1177 | } 1178 | }, 1179 | "check-error": { 1180 | "version": "1.0.2", 1181 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 1182 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 1183 | "dev": true 1184 | }, 1185 | "chokidar": { 1186 | "version": "3.5.3", 1187 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 1188 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 1189 | "dev": true, 1190 | "requires": { 1191 | "anymatch": "~3.1.2", 1192 | "braces": "~3.0.2", 1193 | "fsevents": "~2.3.2", 1194 | "glob-parent": "~5.1.2", 1195 | "is-binary-path": "~2.1.0", 1196 | "is-glob": "~4.0.1", 1197 | "normalize-path": "~3.0.0", 1198 | "readdirp": "~3.6.0" 1199 | } 1200 | }, 1201 | "cliui": { 1202 | "version": "7.0.4", 1203 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 1204 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 1205 | "dev": true, 1206 | "requires": { 1207 | "string-width": "^4.2.0", 1208 | "strip-ansi": "^6.0.0", 1209 | "wrap-ansi": "^7.0.0" 1210 | } 1211 | }, 1212 | "color-convert": { 1213 | "version": "2.0.1", 1214 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1215 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1216 | "dev": true, 1217 | "requires": { 1218 | "color-name": "~1.1.4" 1219 | } 1220 | }, 1221 | "color-name": { 1222 | "version": "1.1.4", 1223 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1224 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1225 | "dev": true 1226 | }, 1227 | "concat-map": { 1228 | "version": "0.0.1", 1229 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 1230 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 1231 | "dev": true 1232 | }, 1233 | "debug": { 1234 | "version": "4.3.3", 1235 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 1236 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 1237 | "dev": true, 1238 | "requires": { 1239 | "ms": "2.1.2" 1240 | }, 1241 | "dependencies": { 1242 | "ms": { 1243 | "version": "2.1.2", 1244 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1245 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1246 | "dev": true 1247 | } 1248 | } 1249 | }, 1250 | "decamelize": { 1251 | "version": "4.0.0", 1252 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 1253 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 1254 | "dev": true 1255 | }, 1256 | "deep-eql": { 1257 | "version": "3.0.1", 1258 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 1259 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 1260 | "dev": true, 1261 | "requires": { 1262 | "type-detect": "^4.0.0" 1263 | } 1264 | }, 1265 | "diff": { 1266 | "version": "5.0.0", 1267 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 1268 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 1269 | "dev": true 1270 | }, 1271 | "emoji-regex": { 1272 | "version": "8.0.0", 1273 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1274 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1275 | "dev": true 1276 | }, 1277 | "escalade": { 1278 | "version": "3.1.1", 1279 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 1280 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 1281 | "dev": true 1282 | }, 1283 | "escape-string-regexp": { 1284 | "version": "4.0.0", 1285 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1286 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1287 | "dev": true 1288 | }, 1289 | "fill-range": { 1290 | "version": "7.0.1", 1291 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1292 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1293 | "dev": true, 1294 | "requires": { 1295 | "to-regex-range": "^5.0.1" 1296 | } 1297 | }, 1298 | "find-up": { 1299 | "version": "5.0.0", 1300 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1301 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1302 | "dev": true, 1303 | "requires": { 1304 | "locate-path": "^6.0.0", 1305 | "path-exists": "^4.0.0" 1306 | } 1307 | }, 1308 | "flat": { 1309 | "version": "5.0.2", 1310 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 1311 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 1312 | "dev": true 1313 | }, 1314 | "fs.realpath": { 1315 | "version": "1.0.0", 1316 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1317 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1318 | "dev": true 1319 | }, 1320 | "fsevents": { 1321 | "version": "2.3.2", 1322 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 1323 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 1324 | "dev": true, 1325 | "optional": true 1326 | }, 1327 | "get-caller-file": { 1328 | "version": "2.0.5", 1329 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1330 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1331 | "dev": true 1332 | }, 1333 | "get-func-name": { 1334 | "version": "2.0.0", 1335 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 1336 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 1337 | "dev": true 1338 | }, 1339 | "glob": { 1340 | "version": "7.2.0", 1341 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 1342 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 1343 | "dev": true, 1344 | "requires": { 1345 | "fs.realpath": "^1.0.0", 1346 | "inflight": "^1.0.4", 1347 | "inherits": "2", 1348 | "minimatch": "^3.0.4", 1349 | "once": "^1.3.0", 1350 | "path-is-absolute": "^1.0.0" 1351 | }, 1352 | "dependencies": { 1353 | "minimatch": { 1354 | "version": "3.1.2", 1355 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1356 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1357 | "dev": true, 1358 | "requires": { 1359 | "brace-expansion": "^1.1.7" 1360 | } 1361 | } 1362 | } 1363 | }, 1364 | "glob-parent": { 1365 | "version": "5.1.2", 1366 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1367 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1368 | "dev": true, 1369 | "requires": { 1370 | "is-glob": "^4.0.1" 1371 | } 1372 | }, 1373 | "growl": { 1374 | "version": "1.10.5", 1375 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 1376 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 1377 | "dev": true 1378 | }, 1379 | "has-flag": { 1380 | "version": "4.0.0", 1381 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1382 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1383 | "dev": true 1384 | }, 1385 | "he": { 1386 | "version": "1.2.0", 1387 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 1388 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 1389 | "dev": true 1390 | }, 1391 | "inflight": { 1392 | "version": "1.0.6", 1393 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1394 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1395 | "dev": true, 1396 | "requires": { 1397 | "once": "^1.3.0", 1398 | "wrappy": "1" 1399 | } 1400 | }, 1401 | "inherits": { 1402 | "version": "2.0.4", 1403 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1404 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1405 | "dev": true 1406 | }, 1407 | "is-binary-path": { 1408 | "version": "2.1.0", 1409 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1410 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1411 | "dev": true, 1412 | "requires": { 1413 | "binary-extensions": "^2.0.0" 1414 | } 1415 | }, 1416 | "is-extglob": { 1417 | "version": "2.1.1", 1418 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1419 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1420 | "dev": true 1421 | }, 1422 | "is-fullwidth-code-point": { 1423 | "version": "3.0.0", 1424 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1425 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1426 | "dev": true 1427 | }, 1428 | "is-glob": { 1429 | "version": "4.0.3", 1430 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1431 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1432 | "dev": true, 1433 | "requires": { 1434 | "is-extglob": "^2.1.1" 1435 | } 1436 | }, 1437 | "is-number": { 1438 | "version": "7.0.0", 1439 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1440 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1441 | "dev": true 1442 | }, 1443 | "is-plain-obj": { 1444 | "version": "2.1.0", 1445 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 1446 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 1447 | "dev": true 1448 | }, 1449 | "is-unicode-supported": { 1450 | "version": "0.1.0", 1451 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 1452 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 1453 | "dev": true 1454 | }, 1455 | "isexe": { 1456 | "version": "2.0.0", 1457 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1458 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1459 | "dev": true 1460 | }, 1461 | "js-yaml": { 1462 | "version": "4.1.0", 1463 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1464 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1465 | "dev": true, 1466 | "requires": { 1467 | "argparse": "^2.0.1" 1468 | } 1469 | }, 1470 | "locate-path": { 1471 | "version": "6.0.0", 1472 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1473 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1474 | "dev": true, 1475 | "requires": { 1476 | "p-locate": "^5.0.0" 1477 | } 1478 | }, 1479 | "log-symbols": { 1480 | "version": "4.1.0", 1481 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 1482 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 1483 | "dev": true, 1484 | "requires": { 1485 | "chalk": "^4.1.0", 1486 | "is-unicode-supported": "^0.1.0" 1487 | } 1488 | }, 1489 | "minimatch": { 1490 | "version": "4.2.1", 1491 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", 1492 | "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", 1493 | "dev": true, 1494 | "requires": { 1495 | "brace-expansion": "^1.1.7" 1496 | } 1497 | }, 1498 | "mocha": { 1499 | "version": "9.2.2", 1500 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", 1501 | "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", 1502 | "dev": true, 1503 | "requires": { 1504 | "@ungap/promise-all-settled": "1.1.2", 1505 | "ansi-colors": "4.1.1", 1506 | "browser-stdout": "1.3.1", 1507 | "chokidar": "3.5.3", 1508 | "debug": "4.3.3", 1509 | "diff": "5.0.0", 1510 | "escape-string-regexp": "4.0.0", 1511 | "find-up": "5.0.0", 1512 | "glob": "7.2.0", 1513 | "growl": "1.10.5", 1514 | "he": "1.2.0", 1515 | "js-yaml": "4.1.0", 1516 | "log-symbols": "4.1.0", 1517 | "minimatch": "4.2.1", 1518 | "ms": "2.1.3", 1519 | "nanoid": "3.3.1", 1520 | "serialize-javascript": "6.0.0", 1521 | "strip-json-comments": "3.1.1", 1522 | "supports-color": "8.1.1", 1523 | "which": "2.0.2", 1524 | "workerpool": "6.2.0", 1525 | "yargs": "16.2.0", 1526 | "yargs-parser": "20.2.4", 1527 | "yargs-unparser": "2.0.0" 1528 | } 1529 | }, 1530 | "ms": { 1531 | "version": "2.1.3", 1532 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1533 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1534 | "dev": true 1535 | }, 1536 | "nanoid": { 1537 | "version": "3.3.1", 1538 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", 1539 | "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", 1540 | "dev": true 1541 | }, 1542 | "normalize-path": { 1543 | "version": "3.0.0", 1544 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1545 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1546 | "dev": true 1547 | }, 1548 | "once": { 1549 | "version": "1.4.0", 1550 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1551 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1552 | "dev": true, 1553 | "requires": { 1554 | "wrappy": "1" 1555 | } 1556 | }, 1557 | "p-limit": { 1558 | "version": "3.1.0", 1559 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1560 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1561 | "dev": true, 1562 | "requires": { 1563 | "yocto-queue": "^0.1.0" 1564 | } 1565 | }, 1566 | "p-locate": { 1567 | "version": "5.0.0", 1568 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1569 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1570 | "dev": true, 1571 | "requires": { 1572 | "p-limit": "^3.0.2" 1573 | } 1574 | }, 1575 | "path-exists": { 1576 | "version": "4.0.0", 1577 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1578 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1579 | "dev": true 1580 | }, 1581 | "path-is-absolute": { 1582 | "version": "1.0.1", 1583 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1584 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1585 | "dev": true 1586 | }, 1587 | "pathval": { 1588 | "version": "1.1.1", 1589 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 1590 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 1591 | "dev": true 1592 | }, 1593 | "picomatch": { 1594 | "version": "2.3.1", 1595 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1596 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1597 | "dev": true 1598 | }, 1599 | "randombytes": { 1600 | "version": "2.1.0", 1601 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1602 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1603 | "dev": true, 1604 | "requires": { 1605 | "safe-buffer": "^5.1.0" 1606 | } 1607 | }, 1608 | "readdirp": { 1609 | "version": "3.6.0", 1610 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1611 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1612 | "dev": true, 1613 | "requires": { 1614 | "picomatch": "^2.2.1" 1615 | } 1616 | }, 1617 | "require-directory": { 1618 | "version": "2.1.1", 1619 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1620 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1621 | "dev": true 1622 | }, 1623 | "safe-buffer": { 1624 | "version": "5.2.1", 1625 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1626 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1627 | "dev": true 1628 | }, 1629 | "serialize-javascript": { 1630 | "version": "6.0.0", 1631 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 1632 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 1633 | "dev": true, 1634 | "requires": { 1635 | "randombytes": "^2.1.0" 1636 | } 1637 | }, 1638 | "string-width": { 1639 | "version": "4.2.3", 1640 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1641 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1642 | "dev": true, 1643 | "requires": { 1644 | "emoji-regex": "^8.0.0", 1645 | "is-fullwidth-code-point": "^3.0.0", 1646 | "strip-ansi": "^6.0.1" 1647 | } 1648 | }, 1649 | "strip-ansi": { 1650 | "version": "6.0.1", 1651 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1652 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1653 | "dev": true, 1654 | "requires": { 1655 | "ansi-regex": "^5.0.1" 1656 | } 1657 | }, 1658 | "strip-json-comments": { 1659 | "version": "3.1.1", 1660 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1661 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1662 | "dev": true 1663 | }, 1664 | "supports-color": { 1665 | "version": "8.1.1", 1666 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 1667 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 1668 | "dev": true, 1669 | "requires": { 1670 | "has-flag": "^4.0.0" 1671 | } 1672 | }, 1673 | "to-regex-range": { 1674 | "version": "5.0.1", 1675 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1676 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1677 | "dev": true, 1678 | "requires": { 1679 | "is-number": "^7.0.0" 1680 | } 1681 | }, 1682 | "type-detect": { 1683 | "version": "4.0.8", 1684 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 1685 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 1686 | "dev": true 1687 | }, 1688 | "typescript": { 1689 | "version": "4.5.2", 1690 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz", 1691 | "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==", 1692 | "dev": true 1693 | }, 1694 | "which": { 1695 | "version": "2.0.2", 1696 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1697 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1698 | "dev": true, 1699 | "requires": { 1700 | "isexe": "^2.0.0" 1701 | } 1702 | }, 1703 | "workerpool": { 1704 | "version": "6.2.0", 1705 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", 1706 | "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", 1707 | "dev": true 1708 | }, 1709 | "wrap-ansi": { 1710 | "version": "7.0.0", 1711 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1712 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1713 | "dev": true, 1714 | "requires": { 1715 | "ansi-styles": "^4.0.0", 1716 | "string-width": "^4.1.0", 1717 | "strip-ansi": "^6.0.0" 1718 | } 1719 | }, 1720 | "wrappy": { 1721 | "version": "1.0.2", 1722 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1723 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1724 | "dev": true 1725 | }, 1726 | "y18n": { 1727 | "version": "5.0.8", 1728 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1729 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1730 | "dev": true 1731 | }, 1732 | "yargs": { 1733 | "version": "16.2.0", 1734 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 1735 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 1736 | "dev": true, 1737 | "requires": { 1738 | "cliui": "^7.0.2", 1739 | "escalade": "^3.1.1", 1740 | "get-caller-file": "^2.0.5", 1741 | "require-directory": "^2.1.1", 1742 | "string-width": "^4.2.0", 1743 | "y18n": "^5.0.5", 1744 | "yargs-parser": "^20.2.2" 1745 | } 1746 | }, 1747 | "yargs-parser": { 1748 | "version": "20.2.4", 1749 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 1750 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 1751 | "dev": true 1752 | }, 1753 | "yargs-unparser": { 1754 | "version": "2.0.0", 1755 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 1756 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 1757 | "dev": true, 1758 | "requires": { 1759 | "camelcase": "^6.0.0", 1760 | "decamelize": "^4.0.0", 1761 | "flat": "^5.0.2", 1762 | "is-plain-obj": "^2.1.0" 1763 | } 1764 | }, 1765 | "yocto-queue": { 1766 | "version": "0.1.0", 1767 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1768 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1769 | "dev": true 1770 | } 1771 | } 1772 | } 1773 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jdk-utils", 3 | "version": "0.5.1", 4 | "description": "JDK related utils for Java related development.", 5 | "main": "dist/index.js", 6 | "bin": "bin/cli.js", 7 | "scripts": { 8 | "prepack": "npm run build", 9 | "build": "tsc", 10 | "test": "npm run build && mocha --reporter spec" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/Eskibear/node-jdk-utils.git" 15 | }, 16 | "author": "Eskibear", 17 | "license": "MIT", 18 | "bugs": { 19 | "url": "https://github.com/Eskibear/node-jdk-utils/issues" 20 | }, 21 | "homepage": "https://github.com/Eskibear/node-jdk-utils#readme", 22 | "devDependencies": { 23 | "@types/node": "^16.11.8", 24 | "chai": "^4.3.4", 25 | "mocha": "^9.2.2", 26 | "typescript": "^4.5.2" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/from/asdf.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as os from "os"; 3 | import * as path from "path"; 4 | import { log } from "../logger"; 5 | 6 | const ASDF_DATA_DIR = process.env.ASDF_DATA_DIR ?? path.join(os.homedir(), ".asdf"); 7 | const JDK_BASE_DIR = path.join(ASDF_DATA_DIR, "installs", "java"); 8 | 9 | export async function candidates(): Promise { 10 | const ret = []; 11 | try { 12 | const files = await fs.promises.readdir(JDK_BASE_DIR, { withFileTypes: true }); 13 | const homedirs = files.filter(file => file.isDirectory()).map(file => path.join(JDK_BASE_DIR, file.name)); 14 | ret.push(...homedirs); 15 | } catch (error) { 16 | log(error); 17 | } 18 | return ret; 19 | } -------------------------------------------------------------------------------- /src/from/envs.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as path from "path"; 3 | import { expandTilde, getRealHome, looksLikeJavaHome, JAVA_FILENAME, isMac } from "../utils"; 4 | 5 | const EXCLUSIONS_ON_MAC: Set = new Set([ 6 | "/usr", 7 | "/usr/" 8 | ]); 9 | export async function candidatesFromPath(): Promise { 10 | const ret = []; 11 | if (process.env.PATH) { 12 | const jdkBinFolderFromPath = process.env.PATH.split(path.delimiter) 13 | .filter(p => looksLikeJavaHome(p) || fs.existsSync(path.join(p, JAVA_FILENAME))) 14 | .map(expandTilde); // '~' can occur in envs in Unix-like systems 15 | 16 | /** 17 | * Fix for https://github.com/Eskibear/node-jdk-utils/issues/2 18 | * Homebrew creates symbolic links for each binary instead of folder. 19 | */ 20 | const homeDirs = (await Promise.all(jdkBinFolderFromPath.map(p => getRealHome(path.dirname(p))))).filter(homeDir => { 21 | /** 22 | * Fix for https://github.com/Eskibear/node-jdk-utils/issues/15 23 | * /usr/bin/java is a preserved shortcut program on macOS, which is not a real java home. 24 | */ 25 | return homeDir && !(isMac && EXCLUSIONS_ON_MAC.has(homeDir)); 26 | }); 27 | ret.push(...homeDirs); 28 | } 29 | return ret.filter(Boolean) as string[]; 30 | } 31 | 32 | export async function candidatesFromSpecificEnv(envkey: string): Promise { 33 | if (process.env[envkey]) { 34 | const rmSlash = process.env[envkey]!.replace(/[\\\/]$/, ""); // remove trailing slash if exists 35 | return getRealHome(rmSlash); 36 | } 37 | return undefined; 38 | } 39 | -------------------------------------------------------------------------------- /src/from/gradle.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as os from "os"; 3 | import * as path from "path"; 4 | import { log } from "../logger"; 5 | import { isMac } from "../utils"; 6 | 7 | /* 8 | * Gradle Toolchains JDKs path format 9 | * 10 | * Windows 11 | * >cd %HOMEPATH%\.gradle\jdks 12 | * >wsl find ./ -type f -name java.exe 13 | * ./adoptopenjdk-15-amd64-windows/jdk-15.0.2+7/bin/java.exe 14 | * ./amazon_com_inc_-18-amd64-windows/jdk18.0.2_9/bin/java.exe 15 | * ./eclipse_adoptium-18-amd64-windows/jdk-18.0.2.1+1/bin/java.exe 16 | * 17 | * macOS 18 | * $ cd ~/.gradle/jdks 19 | * $ find ./ -type f -name java 20 | * ./adoptopenjdk-15-x64-mac_hotspot/jdk-15.0.2+7/Contents/Home/bin/java 21 | * ./amazon_com_inc_-18-x64-mac_hotspot/jdk18.0.2_9/Contents/Home/bin/java 22 | * ./eclipse_adoptium-18-x64-mac_hotspot/jdk-18.0.2.1+1/Contents/Home/bin/java 23 | * 24 | * Linux 25 | * $ cd ~/.gradle/jdks 26 | * $ find ./ -type f -name java 27 | * ./adoptopenjdk-15-amd64-linux/jdk-15.0.2+7/bin/java 28 | * ./amazon_com_inc_-18-amd64-linux/18.0.2.9.1/bin/java 29 | * ./eclipse_adoptium-18-amd64-linux/jdk-18.0.2.1+1/bin/java 30 | * 31 | * See https://docs.gradle.org/8.1/userguide/toolchains.html 32 | */ 33 | const GRADLE_USER_HOME = process.env.GRADLE_USER_HOME ?? path.join(os.homedir(), ".gradle"); 34 | const JDK_BASE_DIR = path.join(GRADLE_USER_HOME, "jdks"); 35 | 36 | export async function candidates(): Promise { 37 | const ret = []; 38 | try { 39 | for (const distro of await fs.promises.readdir(JDK_BASE_DIR, { withFileTypes: true })) { 40 | if (distro.isDirectory()) { 41 | const distroDir = path.join(JDK_BASE_DIR, distro.name); 42 | const files = await fs.promises.readdir(distroDir, { withFileTypes: true }); 43 | const homedirs = files.filter(file => file.isDirectory()).map(file => { 44 | if (isMac) { 45 | return path.join(distroDir, file.name, "Contents", "Home"); 46 | } else { 47 | return path.join(distroDir, file.name); 48 | } 49 | }); 50 | ret.push(...homedirs); 51 | } 52 | } 53 | } catch (error) { 54 | log(error); 55 | } 56 | return ret; 57 | } -------------------------------------------------------------------------------- /src/from/homebrew.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as path from "path"; 3 | import { log } from "../logger"; 4 | import { deDup, getRealHome, looksLikeJavaHome } from "../utils"; 5 | 6 | /* 7 | $ ls -l /usr/local/opt 8 | openjdk -> ../Cellar/openjdk/15.0.1 9 | openjdk@11 -> ../Cellar/openjdk@11/11.0.12 10 | openjdk@15 -> ../Cellar/openjdk/15.0.1 11 | 12 | $ ls -l /usr/local/opt/openjdk/bin/java 13 | /usr/local/opt/openjdk/bin/java -> ../libexec/openjdk.jdk/Contents/Home/bin/java 14 | 15 | # Real path is: 16 | # /usr/local/Cellar/openjdk/15.0.1/libexec/openjdk.jdk/Contents/Home/bin/java 17 | 18 | */ 19 | 20 | /** 21 | * See: https://docs.brew.sh/Installation 22 | */ 23 | export const HOMEBREW_DIR_INTEL = "/usr/local/opt"; 24 | export const HOMEBREW_DIR_APPLE_SILLICON = "/opt/homebrew/opt"; 25 | export const HOMEBREW_DIR_LINUX = "/home/linuxbrew/.linuxbrew/opt"; 26 | 27 | export async function candidates(homebrewOptPath: string): Promise { 28 | const ret = []; 29 | try { 30 | const files = await fs.promises.readdir(homebrewOptPath, { withFileTypes: true }); 31 | const homeDirLinks = files.filter(file => file.isSymbolicLink() && looksLikeJavaHome(file.name)).map(file => path.join(homebrewOptPath, file.name)); 32 | 33 | const actualHomeDirs = await Promise.all(deDup(homeDirLinks).map(file => getRealHome(file))) 34 | ret.push(...actualHomeDirs); 35 | } catch (error) { 36 | log(error); 37 | } 38 | return ret.filter(Boolean) as string[]; 39 | } 40 | -------------------------------------------------------------------------------- /src/from/jabba.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as os from "os"; 3 | import * as path from "path"; 4 | import { log } from "../logger"; 5 | 6 | const JABBA_DIR = path.join(os.homedir(), ".jabba"); 7 | const JDK_BASE_DIR = path.join(JABBA_DIR, "jdk"); 8 | 9 | export async function candidates(): Promise { 10 | const ret = []; 11 | try { 12 | const files = await fs.promises.readdir(JDK_BASE_DIR, { withFileTypes: true }); 13 | const homedirs = files.filter(file => file.isDirectory()).map(file => path.join(JDK_BASE_DIR, file.name)); 14 | ret.push(...homedirs); 15 | } catch (error) { 16 | log(error); 17 | } 18 | return ret; 19 | } -------------------------------------------------------------------------------- /src/from/jbang.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as os from "os"; 3 | import * as path from "path"; 4 | import { log } from "../logger"; 5 | 6 | const JBANG_DIR = process.env.JBANG_DIR ?? path.join(os.homedir(), ".jbang"); 7 | const JDK_BASE_DIR = path.join(JBANG_DIR, "cache", "jdks"); 8 | 9 | export async function candidates(): Promise { 10 | const ret = []; 11 | try { 12 | const files = await fs.promises.readdir(JDK_BASE_DIR, { withFileTypes: true }); 13 | const homedirs = files.filter(file => file.isDirectory()).map(file => path.join(JDK_BASE_DIR, file.name)); 14 | ret.push(...homedirs); 15 | } catch (error) { 16 | log(error); 17 | } 18 | return ret; 19 | } -------------------------------------------------------------------------------- /src/from/jenv.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as os from "os"; 3 | import * as path from "path"; 4 | import { log } from "../logger"; 5 | import { deDup } from "../utils"; 6 | 7 | const JENV_DIR = path.join(os.homedir(), ".jenv"); 8 | const JDK_LINK_BASE_DIR = path.join(JENV_DIR, "versions"); 9 | 10 | export async function candidates(): Promise { 11 | const ret = []; 12 | try { 13 | const files = await fs.promises.readdir(JDK_LINK_BASE_DIR, { withFileTypes: true }); 14 | const homeDirLinks = files.filter(file => file.isSymbolicLink()).map(file => path.join(JDK_LINK_BASE_DIR, file.name)); 15 | const actualHomeDirs = await Promise.all(homeDirLinks.map(file => fs.promises.realpath(file))) 16 | const uniqHomes = deDup(actualHomeDirs); 17 | ret.push(...uniqHomes); 18 | } catch (error) { 19 | log(error); 20 | } 21 | return ret; 22 | } -------------------------------------------------------------------------------- /src/from/linux.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as path from "path"; 3 | import { log } from "../logger"; 4 | 5 | const JDK_BASE_DIRS = [ 6 | "/usr/lib/jvm", // Ubuntu 7 | "/usr/java", // Java 8 on CentOS? 8 | // ... add more if necessary 9 | ]; 10 | 11 | export async function candidates(): Promise { 12 | const ret = []; 13 | for (const baseDir of JDK_BASE_DIRS) { 14 | try { 15 | const files = await fs.promises.readdir(baseDir, { withFileTypes: true }); 16 | const homedirs = files.filter(file => file.isDirectory()).map(file => path.join(baseDir, file.name)); 17 | ret.push(...homedirs); 18 | } catch (error) { 19 | log(error); 20 | } 21 | } 22 | return ret; 23 | } -------------------------------------------------------------------------------- /src/from/macOS.ts: -------------------------------------------------------------------------------- 1 | import * as cp from "child_process"; 2 | import * as fs from "fs"; 3 | import * as os from "os"; 4 | import * as path from "path"; 5 | import { log } from "../logger"; 6 | import { deDup } from "../utils"; 7 | 8 | const JDK_BASE_DIRS = [ 9 | "/Library/Java/JavaVirtualMachines", 10 | path.join(os.homedir(), "Library/Java/JavaVirtualMachines") 11 | ]; 12 | 13 | export async function candidates(): Promise { 14 | const ret: string[] = []; 15 | ret.push(...await fromJavaHomeUtil()); 16 | ret.push(...await fromDefaultIntallationLocation()); 17 | return deDup(ret); 18 | } 19 | 20 | async function fromDefaultIntallationLocation(): Promise { 21 | const ret = []; 22 | for (const baseDir of JDK_BASE_DIRS) { 23 | try { 24 | const files = await fs.promises.readdir(baseDir, { withFileTypes: true }); 25 | const homedirs = files.filter(file => file.isDirectory()).map(file => path.join(baseDir, file.name, "Contents", "Home" /** macOS specific subfolder */)); 26 | ret.push(...homedirs); 27 | } catch (error) { 28 | log(error); 29 | } 30 | } 31 | return ret; 32 | } 33 | 34 | /** 35 | * from `/usr/libexec/java_home -V` 36 | * @returns list of jvm homes 37 | */ 38 | async function fromJavaHomeUtil(): Promise { 39 | const ret: string[] = []; 40 | const javaHomeUtility = "/usr/libexec/java_home"; 41 | try { 42 | await fs.promises.access(javaHomeUtility, fs.constants.F_OK); 43 | await new Promise((resolve, _reject) => { 44 | cp.execFile(javaHomeUtility, ["-V"], {}, (_error, _stdout, stderr) => { 45 | const regexp = /".*" - ".*" (.*)/g; 46 | let match; 47 | do{ 48 | match = regexp.exec(stderr); 49 | if (match) { 50 | ret.push(match[1]); 51 | } 52 | } while (match !== null); 53 | resolve(); 54 | }); 55 | }); 56 | } catch (e) { 57 | log(e); 58 | } 59 | return ret; 60 | } 61 | -------------------------------------------------------------------------------- /src/from/sdkman.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as os from "os"; 3 | import * as path from "path"; 4 | import { log } from "../logger"; 5 | 6 | const SDKMAN_DIR = process.env.SDKMAN_DIR ?? path.join(os.homedir(), ".sdkman"); 7 | const JDK_BASE_DIR = path.join(SDKMAN_DIR, "candidates", "java"); 8 | 9 | export async function candidates(): Promise { 10 | const ret = []; 11 | try { 12 | const files = await fs.promises.readdir(JDK_BASE_DIR, { withFileTypes: true }); 13 | const homedirs = files.filter(file => file.isDirectory()).map(file => path.join(JDK_BASE_DIR, file.name)); 14 | ret.push(...homedirs); 15 | } catch (error) { 16 | log(error); 17 | } 18 | return ret; 19 | } -------------------------------------------------------------------------------- /src/from/windows.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import * as os from "os"; 3 | import * as path from "path"; 4 | import { log } from "../logger"; 5 | import { looksLikeJavaHome } from "../utils"; 6 | 7 | const PROGRAM_DIRS = Array.from(new Set([ 8 | process.env.ProgramW6432, 9 | process.env.ProgramFiles, 10 | process.env.LOCALAPPDATA, 11 | path.join(os.homedir(), "AppData", "Local") 12 | ])).filter(Boolean) as string[]; 13 | 14 | const POPULAR_DISTRIBUTIONS = [ 15 | "Eclipse Foundation", // Adoptium 16 | "Eclipse Adoptium", // Eclipse Temurin 17 | "Java", // Oracle Java SE 18 | "Amazon Corretto", 19 | "Microsoft", // Microsoft OpenJDK 20 | path.join("SapMachine", "JDK"), // SAP Machine 21 | "Zulu", // Azul OpenJDK 22 | ]; 23 | 24 | export async function candidates(): Promise { 25 | const ret = []; 26 | for (const programDir of PROGRAM_DIRS) { 27 | for (const distro of POPULAR_DISTRIBUTIONS) { 28 | const baseDir = path.join(programDir, distro); 29 | try { 30 | const files = await fs.promises.readdir(baseDir, { withFileTypes: true }); 31 | const homedirs = files.filter(file => file.isDirectory()).map(file => path.join(baseDir, file.name)); 32 | ret.push(...homedirs); 33 | } catch (error) { 34 | log(error); 35 | } 36 | } 37 | } 38 | return ret.filter(looksLikeJavaHome); 39 | } -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as cp from "child_process"; 2 | import * as fs from "fs"; 3 | import * as path from "path"; 4 | import * as jbang from "./from/jbang"; 5 | import * as asdf from "./from/asdf"; 6 | import * as envs from "./from/envs"; 7 | import * as gradle from "./from/gradle"; 8 | import * as homebrew from "./from/homebrew"; 9 | import * as jabba from "./from/jabba"; 10 | import * as jenv from "./from/jenv"; 11 | import * as linux from "./from/linux"; 12 | import * as macOS from "./from/macOS"; 13 | import * as sdkman from "./from/sdkman"; 14 | import * as windows from "./from/windows"; 15 | import * as logger from "./logger"; 16 | import { deDup, isArm, isLinux, isMac, isWindows, JAVAC_FILENAME, JAVA_FILENAME } from "./utils"; 17 | 18 | export { JAVAC_FILENAME, JAVA_FILENAME } from "./utils"; 19 | 20 | export interface IOptions { 21 | /** 22 | * whether to parse version. 23 | */ 24 | withVersion?: boolean; 25 | /** 26 | * whether to check existence of javac or javac.exe 27 | */ 28 | checkJavac?: boolean; 29 | /** 30 | * whether to include tags for detailed information 31 | */ 32 | withTags?: boolean; 33 | 34 | /** 35 | * whether to skip resolving from a specific source 36 | */ 37 | skipFrom?: { 38 | /** 39 | * from env.JAVA_HOME 40 | */ 41 | javaHomeEnv?: boolean; 42 | /** 43 | * from env.JDK_HOME 44 | */ 45 | jdkHomeEnv?: boolean; 46 | /** 47 | * from env.PATH 48 | */ 49 | inPathEnv?: boolean; 50 | /** 51 | * from SDKMAN 52 | */ 53 | sdkman?: boolean; 54 | /** 55 | * from JENV 56 | */ 57 | jenv?: boolean; 58 | /** 59 | * from Jabba 60 | */ 61 | jabba?: boolean; 62 | /** 63 | * from ASDF 64 | */ 65 | asdf?: boolean; 66 | /** 67 | * from Gradle locations 68 | */ 69 | gradle?: boolean; 70 | /** 71 | * from JBang locations 72 | */ 73 | jbang?: boolean; 74 | }; 75 | } 76 | 77 | export interface IJavaVersion { 78 | java_version: string; 79 | major: number; 80 | } 81 | 82 | export interface IJavaRuntime { 83 | /** 84 | * Home directory of Java runtime. 85 | */ 86 | homedir: string; 87 | /** 88 | * Version information. 89 | */ 90 | version?: IJavaVersion; 91 | /** 92 | * Whether javac or javac.exe exists. 93 | */ 94 | hasJavac?: boolean; 95 | 96 | /** 97 | * whether is same as env.JAVA_HOME 98 | */ 99 | isJavaHomeEnv?: boolean; 100 | 101 | /** 102 | * whether is same as env.JDK_HOME 103 | */ 104 | isJdkHomeEnv?: boolean; 105 | 106 | /** 107 | * whether '/bin' is one of env.PATH entries 108 | */ 109 | isInPathEnv?: boolean; 110 | 111 | isFromSDKMAN?: boolean; 112 | isFromJENV?: boolean; 113 | isFromJabba?: boolean; 114 | isFromJBang?: boolean; 115 | isFromASDF?: boolean; 116 | isFromGradle?: boolean; 117 | } 118 | 119 | /** 120 | * Find Java runtime from all possible locations on your machine. 121 | * 122 | * @param options advanced options 123 | * @returns 124 | */ 125 | export async function findRuntimes(options?: IOptions): Promise { 126 | const store = new RuntimeStore(); 127 | const candidates: string[] = []; 128 | 129 | const updateCandidates = (homedirs: string[], updater?: (r: IJavaRuntime) => IJavaRuntime) => { 130 | if (options?.withTags) { 131 | store.updateRuntimes(homedirs, updater); 132 | } else { 133 | candidates.push(...homedirs); 134 | } 135 | } 136 | 137 | // SDKMAN 138 | if (!options?.skipFrom?.sdkman) { 139 | const fromSdkman = await sdkman.candidates(); 140 | updateCandidates(fromSdkman, (r) => ({ ...r, isFromSDKMAN: true })); 141 | } 142 | 143 | // platform-specific default location 144 | if (isLinux) { 145 | updateCandidates(await linux.candidates()); 146 | updateCandidates(await homebrew.candidates(homebrew.HOMEBREW_DIR_LINUX)); // Homebrew 147 | } 148 | if (isMac) { 149 | updateCandidates(await macOS.candidates()); 150 | const hbOptPath = isArm ? homebrew.HOMEBREW_DIR_APPLE_SILLICON : homebrew.HOMEBREW_DIR_INTEL; 151 | updateCandidates(await homebrew.candidates(hbOptPath)); // Homebrew 152 | } 153 | if (isWindows) { 154 | updateCandidates(await windows.candidates()); 155 | } 156 | 157 | // from env: JDK_HOME 158 | if (!options?.skipFrom?.jdkHomeEnv) { 159 | const fromJdkHome = await envs.candidatesFromSpecificEnv("JDK_HOME"); 160 | if (fromJdkHome) { 161 | updateCandidates([fromJdkHome], (r) => ({ ...r, isJdkHomeEnv: true })); 162 | } 163 | } 164 | 165 | // from env: JAVA_HOME 166 | if (!options?.skipFrom?.javaHomeEnv) { 167 | const fromJavaHome = await envs.candidatesFromSpecificEnv("JAVA_HOME"); 168 | if (fromJavaHome) { 169 | updateCandidates([fromJavaHome], (r) => ({ ...r, isJavaHomeEnv: true })); 170 | } 171 | } 172 | 173 | // from env: PATH 174 | if (!options?.skipFrom?.inPathEnv) { 175 | const fromPath = await envs.candidatesFromPath(); 176 | updateCandidates(fromPath, (r) => ({ ...r, isInPathEnv: true })); 177 | } 178 | 179 | // jEnv 180 | if (!options?.skipFrom?.jenv) { 181 | const fromJENV = await jenv.candidates(); 182 | updateCandidates(fromJENV, (r) => ({ ...r, isFromJENV: true })); 183 | } 184 | 185 | // jabba 186 | if (!options?.skipFrom?.jabba) { 187 | const fromJabba = await jabba.candidates(); 188 | updateCandidates(fromJabba, (r) => ({ ...r, isFromJabba: true })); 189 | } 190 | 191 | // jbang 192 | if (!options?.skipFrom?.jbang) { 193 | const fromJBang = await jbang.candidates(); 194 | updateCandidates(fromJBang, (r) => ({ ...r, isFromJBang: true })); 195 | } 196 | // asdf 197 | if (!options?.skipFrom?.asdf) { 198 | const fromASDF = await asdf.candidates(); 199 | updateCandidates(fromASDF, (r) => ({ ...r, isFromASDF: true })); 200 | } 201 | 202 | // Gradle 203 | if (!options?.skipFrom?.gradle) { 204 | const fromGradle = await gradle.candidates(); 205 | updateCandidates(fromGradle, (r) => ({ ...r, isFromGradle: true })); 206 | } 207 | 208 | // dedup and construct runtimes 209 | let runtimes: IJavaRuntime[] = options?.withTags ? store.allRuntimes() 210 | : deDup(candidates).map((homedir) => ({ homedir })); 211 | 212 | // verification 213 | if (true /* always check java binary */) { 214 | runtimes = await Promise.all(runtimes.map(checkJavaFile)); 215 | if (true /* java binary is required for a valid runtime */) { 216 | runtimes = (runtimes as Array).filter(r => r.isValid); 217 | } 218 | } 219 | 220 | if (options?.checkJavac) { 221 | runtimes = await Promise.all(runtimes.map(checkJavacFile)); 222 | } 223 | 224 | if (options?.withVersion) { 225 | runtimes = await Promise.all(runtimes.map(parseVersion)); 226 | } 227 | 228 | // clean up private fields by default 229 | for (const r of runtimes) { 230 | delete (r as CanValidate).isValid; 231 | } 232 | 233 | return runtimes; 234 | } 235 | 236 | /** 237 | * Verify if given directory contains a valid Java runtime, and provide details if it is. 238 | * 239 | * @param homedir home directory of a Java runtime 240 | * @param options 241 | * @returns 242 | */ 243 | export async function getRuntime(homedir: string, options?: IOptions): Promise { 244 | let runtime: IJavaRuntime = { homedir }; 245 | runtime = await checkJavaFile(runtime); 246 | if (!(runtime as CanValidate).isValid) { 247 | return undefined; 248 | } 249 | 250 | if (options?.checkJavac) { 251 | runtime = await checkJavacFile(runtime); 252 | } 253 | if (options?.withVersion) { 254 | runtime = await parseVersion(runtime); 255 | } 256 | 257 | if (options?.withTags) { 258 | const gList = await gradle.candidates(); 259 | if (gList.includes(homedir)) { 260 | runtime.isFromGradle = true; 261 | } 262 | const jbangList = await jbang.candidates(); 263 | if (jbangList.includes(homedir)) { 264 | runtime.isFromJBang = true; 265 | } 266 | const aList = await asdf.candidates(); 267 | if (aList.includes(homedir)) { 268 | runtime.isFromASDF = true; 269 | } 270 | const jList = await jenv.candidates(); 271 | if (jList.includes(homedir)) { 272 | runtime.isFromJENV = true; 273 | } 274 | const sList = await sdkman.candidates(); 275 | if (sList.includes(homedir)) { 276 | runtime.isFromSDKMAN = true; 277 | } 278 | const jbList = await jabba.candidates(); 279 | if (jbList.includes(homedir)) { 280 | runtime.isFromJabba = true; 281 | } 282 | const pList = await envs.candidatesFromPath(); 283 | if (pList.includes(homedir)) { 284 | runtime.isInPathEnv = true; 285 | } 286 | if (await envs.candidatesFromSpecificEnv("JAVA_HOME") === homedir) { 287 | runtime.isJavaHomeEnv = true; 288 | } 289 | if (await envs.candidatesFromSpecificEnv("JDK_HOME") === homedir) { 290 | runtime.isJdkHomeEnv = true; 291 | } 292 | } 293 | return runtime; 294 | } 295 | 296 | /** 297 | * A utility to list all sources where given Java runtime is found. 298 | * 299 | * @param r given IJavaRuntime 300 | * @returns list of sources where given runtime is found. 301 | */ 302 | export function getSources(r: IJavaRuntime): string[] { 303 | const sources: string[] = []; 304 | if (r.isJdkHomeEnv) { 305 | sources.push("JDK_HOME"); 306 | } 307 | if (r.isJavaHomeEnv) { 308 | sources.push("JAVA_HOME"); 309 | } 310 | if (r.isInPathEnv) { 311 | sources.push("PATH"); 312 | } 313 | if (r.isFromSDKMAN) { 314 | sources.push("SDKMAN"); 315 | } 316 | if (r.isFromJENV) { 317 | sources.push("jEnv"); 318 | } 319 | if (r.isFromJabba) { 320 | sources.push("jabba"); 321 | } 322 | if (r.isFromJBang) { 323 | sources.push("JBang"); 324 | } 325 | if (r.isFromASDF) { 326 | sources.push("asdf"); 327 | } 328 | if (r.isFromGradle) { 329 | sources.push("Gradle"); 330 | } 331 | return sources; 332 | } 333 | 334 | async function checkJavaFile(runtime: IJavaRuntime): Promise { 335 | const { homedir } = runtime; 336 | const binary = path.join(homedir, "bin", JAVA_FILENAME); 337 | try { 338 | await fs.promises.access(binary, fs.constants.F_OK); 339 | (runtime as IJavaRuntime & CanValidate).isValid = true; 340 | } catch (error) { 341 | (runtime as IJavaRuntime & CanValidate).isValid = false; 342 | } 343 | return runtime as IJavaRuntime & CanValidate; 344 | } 345 | 346 | async function checkJavacFile(runtime: IJavaRuntime): Promise { 347 | const { homedir } = runtime; 348 | const binary = path.join(homedir, "bin", JAVAC_FILENAME); 349 | try { 350 | await fs.promises.access(binary, fs.constants.F_OK); 351 | runtime.hasJavac = true; 352 | } catch (error) { 353 | runtime.hasJavac = false; 354 | } 355 | return runtime; 356 | } 357 | 358 | async function parseVersion(runtime: IJavaRuntime): Promise { 359 | const { homedir } = runtime; 360 | const releaseFile = path.join(homedir, "release"); 361 | try { 362 | const content = await fs.promises.readFile(releaseFile, { encoding: "utf-8" }); 363 | const regexp = /^JAVA_VERSION="(.*)"/gm; 364 | const match = regexp.exec(content.toString()); 365 | if (!match) { 366 | return runtime; 367 | } 368 | const java_version = match[1]; 369 | const major = parseMajorVersion(java_version); 370 | 371 | runtime.version = { 372 | java_version, 373 | major 374 | }; 375 | } catch (error) { 376 | logger.log(error); 377 | } 378 | 379 | if (runtime.version === undefined) { 380 | // fallback to check version by CLI 381 | try { 382 | runtime.version = await checkJavaVersionByCLI(homedir); 383 | } catch (error) { 384 | logger.log(error); 385 | } 386 | } 387 | 388 | return runtime; 389 | } 390 | 391 | /** 392 | * Get version by parsing `JAVA_HOME/bin/java -version`, make sure binary file exists. 393 | * @deprecated as a fallback when file "release" not found 394 | */ 395 | async function checkJavaVersionByCLI(javaHome: string): Promise { 396 | return new Promise((resolve, _reject) => { 397 | const javaBin = path.join(javaHome, "bin", JAVA_FILENAME); // assume java binary exists. 398 | cp.execFile(javaBin, ["-version"], {}, (_error, _stdout, stderr) => { 399 | const regexp = /version "(.*)"/g; 400 | const match = regexp.exec(stderr); 401 | if (!match) { 402 | return resolve(undefined); 403 | } 404 | const java_version = match[1]; 405 | const major = parseMajorVersion(java_version); 406 | resolve({ 407 | java_version, 408 | major 409 | }); 410 | }); 411 | }); 412 | } 413 | 414 | function parseMajorVersion(version: string): number { 415 | if (!version) { 416 | return 0; 417 | } 418 | // Ignore '1.' prefix for legacy Java versions 419 | if (version.startsWith("1.")) { 420 | version = version.substring(2); 421 | } 422 | // look into the interesting bits now 423 | const regexp = /\d+/g; 424 | const match = regexp.exec(version); 425 | let javaVersion = 0; 426 | if (match) { 427 | javaVersion = parseInt(match[0]); 428 | } 429 | return javaVersion; 430 | } 431 | 432 | class RuntimeStore { 433 | private map: Map = new Map(); 434 | constructor() { } 435 | 436 | public updateRuntimes(homedirs: string[], updater?: (r: IJavaRuntime) => IJavaRuntime) { 437 | for (const h of homedirs) { 438 | this.updateRuntime(h, updater); 439 | } 440 | } 441 | 442 | public updateRuntime(homedir: string, updater?: (r: IJavaRuntime) => IJavaRuntime) { 443 | const runtime = this.map.get(homedir) || { homedir }; 444 | this.map.set(homedir, updater?.(runtime) ?? runtime); 445 | } 446 | 447 | public allRuntimes() { 448 | return Array.from(this.map.values()); 449 | } 450 | } 451 | 452 | interface CanValidate { 453 | /** 454 | * Whether java or java.exe exists, indicating it's a valid runtime. 455 | */ 456 | isValid?: boolean; 457 | } 458 | -------------------------------------------------------------------------------- /src/logger.ts: -------------------------------------------------------------------------------- 1 | export function log(...args: any[]) { 2 | // to implement 3 | } 4 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import * as fs from "fs"; 2 | import { homedir } from "os"; 3 | import { dirname, join } from "path"; 4 | import * as logger from "./logger"; 5 | 6 | // platform 7 | export const isWindows: boolean = process.platform.indexOf("win") === 0; 8 | export const isMac: boolean = process.platform.indexOf("darwin") === 0; 9 | export const isLinux: boolean = process.platform.indexOf("linux") === 0; 10 | 11 | // arch 12 | export const isArm: boolean = process.arch.indexOf("arm") === 0; // used to distinguish macOS Intel/Apple Sillicon 13 | 14 | export const JAVA_FILENAME = isWindows ? "java.exe" : "java"; 15 | export const JAVAC_FILENAME = isWindows ? "javac.exe" : "javac"; 16 | 17 | export function looksLikeJavaHome(dir: string) { 18 | const lower = dir.toLocaleLowerCase(); 19 | return lower.includes("jdk") || lower.includes("java"); 20 | } 21 | 22 | export function deDup(arr: string[]) { 23 | return Array.from(new Set(arr)); 24 | } 25 | 26 | export function expandTilde(filepath: string) { 27 | if (filepath.charCodeAt(0) === 126 /* ~ */) { 28 | return join(homedir(), filepath.slice(1)); 29 | } else { 30 | 31 | return filepath; 32 | } 33 | } 34 | 35 | /** 36 | * Get real Java Home directory, deducted from real path of 'bin/java', with symbolic links resolved. 37 | * Mainly for Homebrew. 38 | * @param javaHomePathLike e.g. some-path supposed to have 'bin/java' under it. 39 | * @returns a valid java home 40 | */ 41 | export async function getRealHome(javaHomePathLike: string): Promise { 42 | const javaBinaryPath = expandTilde(join(javaHomePathLike, "bin", JAVA_FILENAME)); 43 | try { 44 | const rp = await fs.promises.realpath(javaBinaryPath); 45 | return dirname(dirname(rp)); 46 | } catch (error) { 47 | logger.log(error); 48 | } 49 | return undefined; 50 | } 51 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | const expect = require("chai").expect; 3 | 4 | describe("test this module", () => { 5 | const utils = require("../dist/index"); 6 | it("should work with require", () => { 7 | expect(utils).to.not.undefined; 8 | }); 9 | 10 | it("should list valid JDKs", async () => { 11 | const label = "cost"; 12 | console.time(label); 13 | const jdks = await utils.findRuntimes(); 14 | console.timeEnd(label); 15 | console.log("JDK found: ", jdks.length); 16 | jdks.forEach(jdk => console.log(jdk.homedir)); 17 | }); 18 | 19 | it("should fetch versions", async () => { 20 | const label = "withVersion"; 21 | console.time(label); 22 | const jdks = await utils.findRuntimes({ withVersion: true }); 23 | console.timeEnd(label); 24 | console.log("JDK found: ", jdks.length); 25 | console.log("homedir", "majorVersion"); 26 | jdks.forEach(jdk => console.log(jdk.homedir, jdk.version?.major)); 27 | }); 28 | 29 | it("should check javac", async () => { 30 | const label = "checkJavac"; 31 | console.time(label); 32 | const jdks = await utils.findRuntimes({ checkJavac: true }); 33 | console.timeEnd(label); 34 | console.log("JDK found: ", jdks.length); 35 | console.log("homedir", "hasJavac"); 36 | jdks.forEach(jdk => console.log(jdk.homedir, jdk.hasJavac)); 37 | }); 38 | 39 | it("should list all possible JDKs with version", async () => { 40 | const label = "checkJavac,withVersion"; 41 | console.time(label); 42 | const jdks = await utils.findRuntimes({ checkJavac: true, withVersion: true }); 43 | console.timeEnd(label); 44 | console.log("JDK found: ", jdks.length); 45 | console.log("homedir", "hasJava", "hasJavac", "majorVersion"); 46 | jdks.forEach(jdk => console.log(jdk.homedir, jdk.hasJavac, jdk.version?.major)); 47 | }); 48 | 49 | it("should list with tags", async () => { 50 | const label = "withTags"; 51 | console.time(label); 52 | const jdks = await utils.findRuntimes({ withTags: true, withVersion: true, checkJavac: true }); 53 | console.timeEnd(label); 54 | console.log("JDK found: ", jdks.length); 55 | console.log(jdks); 56 | }); 57 | it("should list sources", async () => { 58 | const label = "getSources"; 59 | console.time(label); 60 | const jdks = await utils.findRuntimes({ withTags: true, withVersion: true, checkJavac: true }); 61 | console.timeEnd(label); 62 | jdks.forEach(jdk => console.log(jdk.homedir, utils.getSources(jdk))); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ 22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | 26 | /* Modules */ 27 | "module": "commonjs", /* Specify what module code is generated. */ 28 | // "rootDir": "./", /* Specify the root folder within your source files. */ 29 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ 34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 36 | // "resolveJsonModule": true, /* Enable importing .json files */ 37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ 38 | 39 | /* JavaScript Support */ 40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ 41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ 43 | 44 | /* Emit */ 45 | "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 46 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 48 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ 50 | "outDir": "dist", /* Specify an output folder for all emitted files. */ 51 | // "removeComments": true, /* Disable emitting comments. */ 52 | // "noEmit": true, /* Disable emitting files from a compilation. */ 53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ 55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 61 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ 63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ 64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ 66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 67 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 68 | 69 | /* Interop Constraints */ 70 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 71 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 72 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ 73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 74 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 75 | 76 | /* Type Checking */ 77 | "strict": true, /* Enable all strict type-checking options. */ 78 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ 79 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ 80 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 81 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ 82 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 83 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ 84 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ 85 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 86 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ 87 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ 88 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 89 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 90 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 91 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 92 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 93 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ 94 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 95 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 96 | 97 | /* Completeness */ 98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 100 | } 101 | } 102 | --------------------------------------------------------------------------------