├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .npmignore ├── CODEOWNERS ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── constants.ts ├── index.ts └── types.d.ts └── tsconfig.json /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: [ master ] 5 | pull_request: 6 | branches: [ master ] 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Use Node.js 13 | uses: actions/setup-node@v1 14 | with: 15 | node-version: 12.x 16 | - run: npm ci 17 | - run: npm run lint 18 | - run: npm run build 19 | -------------------------------------------------------------------------------- /.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 | 106 | lib/ -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | /* 2 | !/lib/*.js 3 | src/* 4 | !/src/types.d.ts 5 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @mmarkelov @mxschmitt 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 playwright-community 2 | Copyright 2018 Smooth Code (forked) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jest-process-manager 2 | 3 | **This project was forked because the package [`jest-dev-server`](https://github.com/smooth-code/jest-puppeteer/tree/master/packages/jest-dev-server) is no longer maintained.** 4 | 5 | [![CI](https://github.com/playwright-community/jest-process-manager/workflows/CI/badge.svg)](https://github.com/playwright-community/jest-process-manager/actions) 6 | [![npm](https://img.shields.io/npm/v/jest-process-manager)](http://npmjs.com/package/jest-process-manager) 7 | 8 | Starts a server before your Jest tests and tears it down after. 9 | 10 | ## Why 11 | 12 | [`jest-playwright-preset`](https://github.com/playwright-community/jest-playwright) or `jest-puppeteer` works great for running tests in Jest using your preferred end-to-end testing library. 13 | It's also useful for starting a local development server during the tests without letting Jest hang. 14 | This package extracts just the local development server spawning without any ties to Puppeteer. 15 | 16 | ## Install 17 | 18 | ```bash 19 | npm install --save-dev jest-process-manager 20 | ``` 21 | 22 | ## Usage 23 | 24 | `jest-process-manager` exports `setup`,`teardown` and `getServers` functions. 25 | 26 | ```js 27 | // global-setup.js 28 | const { setup: setupDevServer } = require('jest-process-manager') 29 | 30 | module.exports = async function globalSetup() { 31 | await setupDevServer({ 32 | command: `node config/start.js --port=3000`, 33 | launchTimeout: 50000, 34 | port: 3000, 35 | }) 36 | // Your global setup 37 | } 38 | ``` 39 | 40 | It is also possible to specify several servers: 41 | 42 | ```js 43 | // global-setup.js 44 | const { setup: setupDevServer } = require('jest-process-manager') 45 | 46 | module.exports = async function globalSetup() { 47 | await setupDevServer([ 48 | { 49 | command: 'node server.js', 50 | port: 4444, 51 | }, 52 | { 53 | command: 'node server2.js', 54 | port: 4445, 55 | }, 56 | ]) 57 | // Your global setup 58 | } 59 | ``` 60 | 61 | ```js 62 | // global-setup.js 63 | const { setup: setupDevServer, getServers } = require('jest-process-manager') 64 | 65 | module.exports = async function globalSetup() { 66 | await setupDevServer({ 67 | command: `node config/start.js --port=3000`, 68 | launchTimeout: 50000, 69 | port: 3000, 70 | }) 71 | getServers.then(servers => { 72 | // You can get to the servers and do whatever you want 73 | }) 74 | // Your global setup 75 | } 76 | ``` 77 | 78 | ```js 79 | // global-teardown.js 80 | const { teardown: teardownDevServer } = require('jest-process-manager') 81 | 82 | module.exports = async function globalTeardown() { 83 | await teardownDevServer() 84 | // Your global teardown 85 | } 86 | ``` 87 | 88 | ## Options 89 | 90 | ### `command` 91 | 92 | Type: `string`, required. 93 | 94 | Command to execute to start the port. 95 | Directly passed to [`spawnd`](https://www.npmjs.com/package/spawnd). 96 | 97 | ```js 98 | module.exports = { 99 | command: 'npm run start', 100 | } 101 | ``` 102 | 103 | ### `debug` 104 | 105 | Type: `boolean`, default to `false`. 106 | 107 | Log server output, useful if server is crashing at start. 108 | 109 | ```js 110 | module.exports = { 111 | command: 'npm run start', 112 | debug: true, 113 | } 114 | ``` 115 | 116 | ### `launchTimeout` 117 | 118 | Type: `number`, default to `5000`. 119 | 120 | How many milliseconds to wait for the spawned server to be available before giving up. 121 | Defaults to [`wait-port`](https://www.npmjs.com/package/wait-port)'s default. 122 | 123 | ```js 124 | module.exports = { 125 | command: 'npm run start', 126 | launchTimeout: 30000, 127 | } 128 | ``` 129 | 130 | --- 131 | 132 | Following options are linked to [`spawnd`](https://www.npmjs.com/package/spawnd). 133 | 134 | ### `host` 135 | 136 | Type: `string`, default to `localhost`. 137 | 138 | Host to wait for activity on before considering the server running. 139 | Must be used in conjunction with `port`. 140 | 141 | ```js 142 | module.exports = { 143 | command: 'npm run start --port 3000', 144 | host: 'customhost.com', 145 | port: 3000, 146 | } 147 | ``` 148 | 149 | ### `protocol` 150 | 151 | Type: (`https`, `http`, `http-get`, `https-get`, `tcp`, `socket`) default to `tcp`. 152 | 153 | To wait for an HTTP or TCP endpoint before considering the server running, include `http` or `tcp` as a protocol. 154 | Must be used in conjunction with `port`. 155 | This give you ability to define resource prefix for [`wait-on`](https://github.com/jeffbski/wait-on) package. 156 | 157 | ```js 158 | module.exports = { 159 | command: 'npm run start --port 3000', 160 | protocol: 'http', 161 | port: 3000, 162 | } 163 | ``` 164 | 165 | ### `port` 166 | 167 | Type: `number`, default to `3000`. 168 | 169 | Port to wait for activity on before considering the server running. 170 | If not provided, the server is assumed to immediately be running. 171 | 172 | ```js 173 | module.exports = { 174 | command: 'npm run start --port 3000', 175 | port: 3000, 176 | } 177 | ``` 178 | 179 | ### `basePath` 180 | 181 | Type: `string` 182 | 183 | Option for a basePath where server is running. 184 | 185 | ```js 186 | module.exports = { 187 | command: 'npm run start', 188 | basePath: '/myservice', 189 | } 190 | ``` 191 | 192 | ### `usedPortAction` 193 | 194 | Type: `string` (`ask`, `error`, `ignore`, `kill`) default to `ask`. 195 | 196 | It defines the action to take if port is already used: 197 | 198 | - `ask`: a prompt is shown to decide if you want to kill the process or not 199 | - `error`: an errow is thrown 200 | - `ignore`: your test are executed, we assume that the server is already started 201 | - `kill`: the process is automatically killed without a prompt 202 | 203 | ```js 204 | module.exports = { 205 | command: 'npm run start --port 3000', 206 | port: 3000, 207 | usedPortAction: 'kill', 208 | } 209 | ``` 210 | 211 | ### `waitOnScheme` 212 | 213 | `jest-dev-server` use the [`wait-on`](https://www.npmjs.com/package/wait-on) npm package to wait for resources to become available before calling callback. 214 | 215 | Type: `object`, default to `{}`. 216 | 217 | - `delay`: optional initial delay in ms, default 0 218 | - `interval`: optional poll resource interval in ms, default 250ms 219 | - `log`: optional flag which outputs to stdout, remaining resources waited on and when complete or errored 220 | - `reverse`: optional flag to reverse operation so checks are for resources being NOT available, default false 221 | - `timeout`: optional timeout in ms, default Infinity. Aborts with error 222 | - `tcpTimeout`: optional tcp timeout in ms, default 300ms 223 | - `verbose`: optional flag which outputs debug output, default false 224 | - `window`: optional stabilization time in ms, default 750ms. Waits this amount of time for file sizes to stabilize or other resource availability to remain unchanged 225 | 226 | **Note:** http(s) specific options, see https://github.com/request/request#readme for specific details 227 | 228 | ```js 229 | module.exports = { 230 | command: 'npm run start --port 3000', 231 | port: 3000, 232 | usedPortAction: 'kill', 233 | waitOnScheme: { 234 | delay: 1000, 235 | }, 236 | } 237 | ``` 238 | 239 | ### `options` 240 | 241 | Options which will be passed down to the [spawn](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options) of the process. For example environment variables: 242 | 243 | ```js 244 | // global-setup.js 245 | const { setup: setupDevServer, getServers } = require('jest-process-manager') 246 | 247 | module.exports = async function globalSetup() { 248 | await setupDevServer({ 249 | command: `node config/start.js --port=3000`, 250 | launchTimeout: 50000, 251 | port: 3000, 252 | options: { 253 | env: { 254 | "FOO": "bar", 255 | } 256 | } 257 | }) 258 | getServers.then(servers => { 259 | // You can get to the servers and do whatever you want 260 | }) 261 | // Your global setup 262 | } 263 | ``` 264 | 265 | ## Troubleshooting 266 | 267 | - If using `port` makes the terminal to ask for root password although the port is valid and accessible then use `usePortAction: 'ignore'`. 268 | 269 | ## License 270 | 271 | https://github.com/playwright-community/jest-process-manager/blob/master/LICENSE 272 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jest-process-manager", 3 | "version": "0.4.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "jest-process-manager", 9 | "version": "0.4.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@types/wait-on": "^5.2.0", 13 | "chalk": "^4.1.0", 14 | "cwd": "^0.10.0", 15 | "exit": "^0.1.2", 16 | "find-process": "^1.4.4", 17 | "prompts": "^2.4.1", 18 | "signal-exit": "^3.0.3", 19 | "spawnd": "^5.0.0", 20 | "tree-kill": "^1.2.2", 21 | "wait-on": "^7.0.0" 22 | }, 23 | "devDependencies": { 24 | "@types/cwd": "^0.10.0", 25 | "@types/exit": "^0.1.31", 26 | "@types/prompts": "^2.0.10", 27 | "@types/signal-exit": "^3.0.0", 28 | "typescript": "^4.2.4" 29 | } 30 | }, 31 | "node_modules/@hapi/hoek": { 32 | "version": "9.3.0", 33 | "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", 34 | "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" 35 | }, 36 | "node_modules/@hapi/topo": { 37 | "version": "5.1.0", 38 | "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", 39 | "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", 40 | "dependencies": { 41 | "@hapi/hoek": "^9.0.0" 42 | } 43 | }, 44 | "node_modules/@sideway/address": { 45 | "version": "4.1.4", 46 | "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", 47 | "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", 48 | "dependencies": { 49 | "@hapi/hoek": "^9.0.0" 50 | } 51 | }, 52 | "node_modules/@sideway/formula": { 53 | "version": "3.0.1", 54 | "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", 55 | "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" 56 | }, 57 | "node_modules/@sideway/pinpoint": { 58 | "version": "2.0.0", 59 | "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", 60 | "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" 61 | }, 62 | "node_modules/@types/color-name": { 63 | "version": "1.1.1", 64 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 65 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" 66 | }, 67 | "node_modules/@types/cwd": { 68 | "version": "0.10.0", 69 | "resolved": "https://registry.npmjs.org/@types/cwd/-/cwd-0.10.0.tgz", 70 | "integrity": "sha512-DpCQLallLsMpPxUp+OIkN5zHZV64w8ESDPCbjjbzdX5S6ycVSYiTVURx+B19zQkNQxFD5TB/9TRH8564iCWemQ==", 71 | "dev": true 72 | }, 73 | "node_modules/@types/exit": { 74 | "version": "0.1.31", 75 | "resolved": "https://registry.npmjs.org/@types/exit/-/exit-0.1.31.tgz", 76 | "integrity": "sha512-ghT0E6Bw64RXc6lM30ExMNlYbUCsyR8oucl/q+ESGGhNOXOmBPpZHYGXCH2T/yTFq9YtudNCnZEQ4puX6aq87A==", 77 | "dev": true, 78 | "dependencies": { 79 | "@types/node": "*" 80 | } 81 | }, 82 | "node_modules/@types/node": { 83 | "version": "13.13.5", 84 | "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.5.tgz", 85 | "integrity": "sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g==", 86 | "dev": true 87 | }, 88 | "node_modules/@types/prompts": { 89 | "version": "2.0.10", 90 | "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.10.tgz", 91 | "integrity": "sha512-W3PEl3l4vmxdgfY6LUG7ysh+mLJOTOFYmSpiLe6MCo1OdEm8b5s6ZJfuTQgEpYNwcMiiaRzJespPS5Py2tqLlQ==", 92 | "dev": true, 93 | "dependencies": { 94 | "@types/node": "*" 95 | } 96 | }, 97 | "node_modules/@types/signal-exit": { 98 | "version": "3.0.0", 99 | "resolved": "https://registry.npmjs.org/@types/signal-exit/-/signal-exit-3.0.0.tgz", 100 | "integrity": "sha512-MaJ+16SOXz0Z27EMf3d88+B6UDglq1sn140a+5X/ROLkIcEfRq0CPg+1B2efF1GXQn4n+aKH4ti2hHG4Ya+Dzg==", 101 | "dev": true 102 | }, 103 | "node_modules/@types/wait-on": { 104 | "version": "5.2.0", 105 | "resolved": "https://registry.npmjs.org/@types/wait-on/-/wait-on-5.2.0.tgz", 106 | "integrity": "sha512-3+jsMyPm8aot1mqDUDLOl+dejPvpysUUoUXD6CCRY20MNNhcjEfvdcBnGdnk7DEYs9Hr16ubGJA/9/QW0Df/9g==" 107 | }, 108 | "node_modules/ansi-styles": { 109 | "version": "4.2.1", 110 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 111 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 112 | "dependencies": { 113 | "@types/color-name": "^1.1.1", 114 | "color-convert": "^2.0.1" 115 | }, 116 | "engines": { 117 | "node": ">=8" 118 | } 119 | }, 120 | "node_modules/ansi-styles/node_modules/color-convert": { 121 | "version": "2.0.1", 122 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 123 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 124 | "dependencies": { 125 | "color-name": "~1.1.4" 126 | }, 127 | "engines": { 128 | "node": ">=7.0.0" 129 | } 130 | }, 131 | "node_modules/asynckit": { 132 | "version": "0.4.0", 133 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 134 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 135 | }, 136 | "node_modules/axios": { 137 | "version": "1.6.1", 138 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", 139 | "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", 140 | "dependencies": { 141 | "follow-redirects": "^1.15.0", 142 | "form-data": "^4.0.0", 143 | "proxy-from-env": "^1.1.0" 144 | } 145 | }, 146 | "node_modules/chalk": { 147 | "version": "4.1.0", 148 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 149 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 150 | "dependencies": { 151 | "ansi-styles": "^4.1.0", 152 | "supports-color": "^7.1.0" 153 | }, 154 | "engines": { 155 | "node": ">=10" 156 | } 157 | }, 158 | "node_modules/chalk/node_modules/has-flag": { 159 | "version": "4.0.0", 160 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 161 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 162 | "engines": { 163 | "node": ">=8" 164 | } 165 | }, 166 | "node_modules/chalk/node_modules/supports-color": { 167 | "version": "7.1.0", 168 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 169 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 170 | "dependencies": { 171 | "has-flag": "^4.0.0" 172 | }, 173 | "engines": { 174 | "node": ">=8" 175 | } 176 | }, 177 | "node_modules/color-convert": { 178 | "version": "1.9.3", 179 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 180 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 181 | "dependencies": { 182 | "color-name": "1.1.3" 183 | } 184 | }, 185 | "node_modules/color-convert/node_modules/color-name": { 186 | "version": "1.1.3", 187 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 188 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 189 | }, 190 | "node_modules/color-name": { 191 | "version": "1.1.4", 192 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 193 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 194 | }, 195 | "node_modules/combined-stream": { 196 | "version": "1.0.8", 197 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 198 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 199 | "dependencies": { 200 | "delayed-stream": "~1.0.0" 201 | }, 202 | "engines": { 203 | "node": ">= 0.8" 204 | } 205 | }, 206 | "node_modules/commander": { 207 | "version": "5.1.0", 208 | "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", 209 | "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", 210 | "engines": { 211 | "node": ">= 6" 212 | } 213 | }, 214 | "node_modules/cwd": { 215 | "version": "0.10.0", 216 | "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", 217 | "integrity": "sha1-FyQAaUBXwioTsM8WFix+S3p/5Wc=", 218 | "dependencies": { 219 | "find-pkg": "^0.1.2", 220 | "fs-exists-sync": "^0.1.0" 221 | }, 222 | "engines": { 223 | "node": ">=0.8" 224 | } 225 | }, 226 | "node_modules/debug": { 227 | "version": "4.1.1", 228 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 229 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 230 | "dependencies": { 231 | "ms": "^2.1.1" 232 | } 233 | }, 234 | "node_modules/debug/node_modules/ms": { 235 | "version": "2.1.2", 236 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 237 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 238 | }, 239 | "node_modules/delayed-stream": { 240 | "version": "1.0.0", 241 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 242 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", 243 | "engines": { 244 | "node": ">=0.4.0" 245 | } 246 | }, 247 | "node_modules/escape-string-regexp": { 248 | "version": "1.0.5", 249 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 250 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 251 | "engines": { 252 | "node": ">=0.8.0" 253 | } 254 | }, 255 | "node_modules/exit": { 256 | "version": "0.1.2", 257 | "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", 258 | "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", 259 | "engines": { 260 | "node": ">= 0.8.0" 261 | } 262 | }, 263 | "node_modules/expand-tilde": { 264 | "version": "1.2.2", 265 | "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", 266 | "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", 267 | "dependencies": { 268 | "os-homedir": "^1.0.1" 269 | }, 270 | "engines": { 271 | "node": ">=0.10.0" 272 | } 273 | }, 274 | "node_modules/find-file-up": { 275 | "version": "0.1.3", 276 | "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", 277 | "integrity": "sha1-z2gJG8+fMApA2kEbN9pczlovvqA=", 278 | "dependencies": { 279 | "fs-exists-sync": "^0.1.0", 280 | "resolve-dir": "^0.1.0" 281 | }, 282 | "engines": { 283 | "node": ">=0.10.0" 284 | } 285 | }, 286 | "node_modules/find-pkg": { 287 | "version": "0.1.2", 288 | "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", 289 | "integrity": "sha1-G9wiwG42NlUy4qJIBGhUuXiNpVc=", 290 | "dependencies": { 291 | "find-file-up": "^0.1.2" 292 | }, 293 | "engines": { 294 | "node": ">=0.10.0" 295 | } 296 | }, 297 | "node_modules/find-process": { 298 | "version": "1.4.4", 299 | "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.4.tgz", 300 | "integrity": "sha512-rRSuT1LE4b+BFK588D2V8/VG9liW0Ark1XJgroxZXI0LtwmQJOb490DvDYvbm+Hek9ETFzTutGfJ90gumITPhQ==", 301 | "dependencies": { 302 | "chalk": "^4.0.0", 303 | "commander": "^5.1.0", 304 | "debug": "^4.1.1" 305 | }, 306 | "bin": { 307 | "find-process": "bin/find-process.js" 308 | } 309 | }, 310 | "node_modules/follow-redirects": { 311 | "version": "1.15.3", 312 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", 313 | "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", 314 | "funding": [ 315 | { 316 | "type": "individual", 317 | "url": "https://github.com/sponsors/RubenVerborgh" 318 | } 319 | ], 320 | "engines": { 321 | "node": ">=4.0" 322 | }, 323 | "peerDependenciesMeta": { 324 | "debug": { 325 | "optional": true 326 | } 327 | } 328 | }, 329 | "node_modules/form-data": { 330 | "version": "4.0.0", 331 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 332 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 333 | "dependencies": { 334 | "asynckit": "^0.4.0", 335 | "combined-stream": "^1.0.8", 336 | "mime-types": "^2.1.12" 337 | }, 338 | "engines": { 339 | "node": ">= 6" 340 | } 341 | }, 342 | "node_modules/fs-exists-sync": { 343 | "version": "0.1.0", 344 | "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", 345 | "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", 346 | "engines": { 347 | "node": ">=0.10.0" 348 | } 349 | }, 350 | "node_modules/global-modules": { 351 | "version": "0.2.3", 352 | "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", 353 | "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", 354 | "dependencies": { 355 | "global-prefix": "^0.1.4", 356 | "is-windows": "^0.2.0" 357 | }, 358 | "engines": { 359 | "node": ">=0.10.0" 360 | } 361 | }, 362 | "node_modules/global-prefix": { 363 | "version": "0.1.5", 364 | "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", 365 | "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", 366 | "dependencies": { 367 | "homedir-polyfill": "^1.0.0", 368 | "ini": "^1.3.4", 369 | "is-windows": "^0.2.0", 370 | "which": "^1.2.12" 371 | }, 372 | "engines": { 373 | "node": ">=0.10.0" 374 | } 375 | }, 376 | "node_modules/has-flag": { 377 | "version": "3.0.0", 378 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 379 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 380 | "engines": { 381 | "node": ">=4" 382 | } 383 | }, 384 | "node_modules/homedir-polyfill": { 385 | "version": "1.0.3", 386 | "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", 387 | "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", 388 | "dependencies": { 389 | "parse-passwd": "^1.0.0" 390 | }, 391 | "engines": { 392 | "node": ">=0.10.0" 393 | } 394 | }, 395 | "node_modules/ini": { 396 | "version": "1.3.8", 397 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 398 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" 399 | }, 400 | "node_modules/is-windows": { 401 | "version": "0.2.0", 402 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", 403 | "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", 404 | "engines": { 405 | "node": ">=0.10.0" 406 | } 407 | }, 408 | "node_modules/isexe": { 409 | "version": "2.0.0", 410 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 411 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 412 | }, 413 | "node_modules/joi": { 414 | "version": "17.11.0", 415 | "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", 416 | "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", 417 | "dependencies": { 418 | "@hapi/hoek": "^9.0.0", 419 | "@hapi/topo": "^5.0.0", 420 | "@sideway/address": "^4.1.3", 421 | "@sideway/formula": "^3.0.1", 422 | "@sideway/pinpoint": "^2.0.0" 423 | } 424 | }, 425 | "node_modules/kleur": { 426 | "version": "3.0.3", 427 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", 428 | "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", 429 | "engines": { 430 | "node": ">=6" 431 | } 432 | }, 433 | "node_modules/lodash": { 434 | "version": "4.17.21", 435 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 436 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 437 | }, 438 | "node_modules/mime-db": { 439 | "version": "1.52.0", 440 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 441 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 442 | "engines": { 443 | "node": ">= 0.6" 444 | } 445 | }, 446 | "node_modules/mime-types": { 447 | "version": "2.1.35", 448 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 449 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 450 | "dependencies": { 451 | "mime-db": "1.52.0" 452 | }, 453 | "engines": { 454 | "node": ">= 0.6" 455 | } 456 | }, 457 | "node_modules/minimist": { 458 | "version": "1.2.8", 459 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 460 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 461 | "funding": { 462 | "url": "https://github.com/sponsors/ljharb" 463 | } 464 | }, 465 | "node_modules/os-homedir": { 466 | "version": "1.0.2", 467 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 468 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", 469 | "engines": { 470 | "node": ">=0.10.0" 471 | } 472 | }, 473 | "node_modules/parse-passwd": { 474 | "version": "1.0.0", 475 | "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", 476 | "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", 477 | "engines": { 478 | "node": ">=0.10.0" 479 | } 480 | }, 481 | "node_modules/prompts": { 482 | "version": "2.4.1", 483 | "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", 484 | "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", 485 | "dependencies": { 486 | "kleur": "^3.0.3", 487 | "sisteransi": "^1.0.5" 488 | }, 489 | "engines": { 490 | "node": ">= 6" 491 | } 492 | }, 493 | "node_modules/proxy-from-env": { 494 | "version": "1.1.0", 495 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 496 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 497 | }, 498 | "node_modules/resolve-dir": { 499 | "version": "0.1.1", 500 | "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", 501 | "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", 502 | "dependencies": { 503 | "expand-tilde": "^1.2.2", 504 | "global-modules": "^0.2.3" 505 | }, 506 | "engines": { 507 | "node": ">=0.10.0" 508 | } 509 | }, 510 | "node_modules/rxjs": { 511 | "version": "7.8.1", 512 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", 513 | "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", 514 | "dependencies": { 515 | "tslib": "^2.1.0" 516 | } 517 | }, 518 | "node_modules/signal-exit": { 519 | "version": "3.0.3", 520 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 521 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" 522 | }, 523 | "node_modules/sisteransi": { 524 | "version": "1.0.5", 525 | "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", 526 | "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" 527 | }, 528 | "node_modules/spawnd": { 529 | "version": "5.0.0", 530 | "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-5.0.0.tgz", 531 | "integrity": "sha512-28+AJr82moMVWolQvlAIv3JcYDkjkFTEmfDc503wxrF5l2rQ3dFz6DpbXp3kD4zmgGGldfM4xM4v1sFj/ZaIOA==", 532 | "dependencies": { 533 | "exit": "^0.1.2", 534 | "signal-exit": "^3.0.3", 535 | "tree-kill": "^1.2.2", 536 | "wait-port": "^0.2.9" 537 | } 538 | }, 539 | "node_modules/supports-color": { 540 | "version": "5.5.0", 541 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 542 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 543 | "dependencies": { 544 | "has-flag": "^3.0.0" 545 | }, 546 | "engines": { 547 | "node": ">=4" 548 | } 549 | }, 550 | "node_modules/tree-kill": { 551 | "version": "1.2.2", 552 | "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", 553 | "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", 554 | "bin": { 555 | "tree-kill": "cli.js" 556 | } 557 | }, 558 | "node_modules/tslib": { 559 | "version": "2.6.2", 560 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", 561 | "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" 562 | }, 563 | "node_modules/typescript": { 564 | "version": "4.2.4", 565 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", 566 | "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", 567 | "dev": true, 568 | "bin": { 569 | "tsc": "bin/tsc", 570 | "tsserver": "bin/tsserver" 571 | }, 572 | "engines": { 573 | "node": ">=4.2.0" 574 | } 575 | }, 576 | "node_modules/wait-on": { 577 | "version": "7.2.0", 578 | "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", 579 | "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", 580 | "dependencies": { 581 | "axios": "^1.6.1", 582 | "joi": "^17.11.0", 583 | "lodash": "^4.17.21", 584 | "minimist": "^1.2.8", 585 | "rxjs": "^7.8.1" 586 | }, 587 | "bin": { 588 | "wait-on": "bin/wait-on" 589 | }, 590 | "engines": { 591 | "node": ">=12.0.0" 592 | } 593 | }, 594 | "node_modules/wait-port": { 595 | "version": "0.2.9", 596 | "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-0.2.9.tgz", 597 | "integrity": "sha512-hQ/cVKsNqGZ/UbZB/oakOGFqic00YAMM5/PEj3Bt4vKarv2jWIWzDbqlwT94qMs/exAQAsvMOq99sZblV92zxQ==", 598 | "dependencies": { 599 | "chalk": "^2.4.2", 600 | "commander": "^3.0.2", 601 | "debug": "^4.1.1" 602 | }, 603 | "bin": { 604 | "wait-port": "bin/wait-port.js" 605 | }, 606 | "engines": { 607 | "node": ">=8" 608 | } 609 | }, 610 | "node_modules/wait-port/node_modules/ansi-styles": { 611 | "version": "3.2.1", 612 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 613 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 614 | "dependencies": { 615 | "color-convert": "^1.9.0" 616 | }, 617 | "engines": { 618 | "node": ">=4" 619 | } 620 | }, 621 | "node_modules/wait-port/node_modules/chalk": { 622 | "version": "2.4.2", 623 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 624 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 625 | "dependencies": { 626 | "ansi-styles": "^3.2.1", 627 | "escape-string-regexp": "^1.0.5", 628 | "supports-color": "^5.3.0" 629 | }, 630 | "engines": { 631 | "node": ">=4" 632 | } 633 | }, 634 | "node_modules/wait-port/node_modules/commander": { 635 | "version": "3.0.2", 636 | "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", 637 | "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" 638 | }, 639 | "node_modules/which": { 640 | "version": "1.3.1", 641 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 642 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 643 | "dependencies": { 644 | "isexe": "^2.0.0" 645 | }, 646 | "bin": { 647 | "which": "bin/which" 648 | } 649 | } 650 | }, 651 | "dependencies": { 652 | "@hapi/hoek": { 653 | "version": "9.3.0", 654 | "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", 655 | "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" 656 | }, 657 | "@hapi/topo": { 658 | "version": "5.1.0", 659 | "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", 660 | "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", 661 | "requires": { 662 | "@hapi/hoek": "^9.0.0" 663 | } 664 | }, 665 | "@sideway/address": { 666 | "version": "4.1.4", 667 | "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", 668 | "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", 669 | "requires": { 670 | "@hapi/hoek": "^9.0.0" 671 | } 672 | }, 673 | "@sideway/formula": { 674 | "version": "3.0.1", 675 | "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", 676 | "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" 677 | }, 678 | "@sideway/pinpoint": { 679 | "version": "2.0.0", 680 | "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", 681 | "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" 682 | }, 683 | "@types/color-name": { 684 | "version": "1.1.1", 685 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 686 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" 687 | }, 688 | "@types/cwd": { 689 | "version": "0.10.0", 690 | "resolved": "https://registry.npmjs.org/@types/cwd/-/cwd-0.10.0.tgz", 691 | "integrity": "sha512-DpCQLallLsMpPxUp+OIkN5zHZV64w8ESDPCbjjbzdX5S6ycVSYiTVURx+B19zQkNQxFD5TB/9TRH8564iCWemQ==", 692 | "dev": true 693 | }, 694 | "@types/exit": { 695 | "version": "0.1.31", 696 | "resolved": "https://registry.npmjs.org/@types/exit/-/exit-0.1.31.tgz", 697 | "integrity": "sha512-ghT0E6Bw64RXc6lM30ExMNlYbUCsyR8oucl/q+ESGGhNOXOmBPpZHYGXCH2T/yTFq9YtudNCnZEQ4puX6aq87A==", 698 | "dev": true, 699 | "requires": { 700 | "@types/node": "*" 701 | } 702 | }, 703 | "@types/node": { 704 | "version": "13.13.5", 705 | "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.5.tgz", 706 | "integrity": "sha512-3ySmiBYJPqgjiHA7oEaIo2Rzz0HrOZ7yrNO5HWyaE5q0lQ3BppDZ3N53Miz8bw2I7gh1/zir2MGVZBvpb1zq9g==", 707 | "dev": true 708 | }, 709 | "@types/prompts": { 710 | "version": "2.0.10", 711 | "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.0.10.tgz", 712 | "integrity": "sha512-W3PEl3l4vmxdgfY6LUG7ysh+mLJOTOFYmSpiLe6MCo1OdEm8b5s6ZJfuTQgEpYNwcMiiaRzJespPS5Py2tqLlQ==", 713 | "dev": true, 714 | "requires": { 715 | "@types/node": "*" 716 | } 717 | }, 718 | "@types/signal-exit": { 719 | "version": "3.0.0", 720 | "resolved": "https://registry.npmjs.org/@types/signal-exit/-/signal-exit-3.0.0.tgz", 721 | "integrity": "sha512-MaJ+16SOXz0Z27EMf3d88+B6UDglq1sn140a+5X/ROLkIcEfRq0CPg+1B2efF1GXQn4n+aKH4ti2hHG4Ya+Dzg==", 722 | "dev": true 723 | }, 724 | "@types/wait-on": { 725 | "version": "5.2.0", 726 | "resolved": "https://registry.npmjs.org/@types/wait-on/-/wait-on-5.2.0.tgz", 727 | "integrity": "sha512-3+jsMyPm8aot1mqDUDLOl+dejPvpysUUoUXD6CCRY20MNNhcjEfvdcBnGdnk7DEYs9Hr16ubGJA/9/QW0Df/9g==" 728 | }, 729 | "ansi-styles": { 730 | "version": "4.2.1", 731 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 732 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 733 | "requires": { 734 | "@types/color-name": "^1.1.1", 735 | "color-convert": "^2.0.1" 736 | }, 737 | "dependencies": { 738 | "color-convert": { 739 | "version": "2.0.1", 740 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 741 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 742 | "requires": { 743 | "color-name": "~1.1.4" 744 | } 745 | } 746 | } 747 | }, 748 | "asynckit": { 749 | "version": "0.4.0", 750 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 751 | "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" 752 | }, 753 | "axios": { 754 | "version": "1.6.1", 755 | "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz", 756 | "integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==", 757 | "requires": { 758 | "follow-redirects": "^1.15.0", 759 | "form-data": "^4.0.0", 760 | "proxy-from-env": "^1.1.0" 761 | } 762 | }, 763 | "chalk": { 764 | "version": "4.1.0", 765 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 766 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 767 | "requires": { 768 | "ansi-styles": "^4.1.0", 769 | "supports-color": "^7.1.0" 770 | }, 771 | "dependencies": { 772 | "has-flag": { 773 | "version": "4.0.0", 774 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 775 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" 776 | }, 777 | "supports-color": { 778 | "version": "7.1.0", 779 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 780 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 781 | "requires": { 782 | "has-flag": "^4.0.0" 783 | } 784 | } 785 | } 786 | }, 787 | "color-convert": { 788 | "version": "1.9.3", 789 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 790 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 791 | "requires": { 792 | "color-name": "1.1.3" 793 | }, 794 | "dependencies": { 795 | "color-name": { 796 | "version": "1.1.3", 797 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 798 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 799 | } 800 | } 801 | }, 802 | "color-name": { 803 | "version": "1.1.4", 804 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 805 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 806 | }, 807 | "combined-stream": { 808 | "version": "1.0.8", 809 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", 810 | "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", 811 | "requires": { 812 | "delayed-stream": "~1.0.0" 813 | } 814 | }, 815 | "commander": { 816 | "version": "5.1.0", 817 | "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", 818 | "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" 819 | }, 820 | "cwd": { 821 | "version": "0.10.0", 822 | "resolved": "https://registry.npmjs.org/cwd/-/cwd-0.10.0.tgz", 823 | "integrity": "sha1-FyQAaUBXwioTsM8WFix+S3p/5Wc=", 824 | "requires": { 825 | "find-pkg": "^0.1.2", 826 | "fs-exists-sync": "^0.1.0" 827 | } 828 | }, 829 | "debug": { 830 | "version": "4.1.1", 831 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 832 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 833 | "requires": { 834 | "ms": "^2.1.1" 835 | }, 836 | "dependencies": { 837 | "ms": { 838 | "version": "2.1.2", 839 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 840 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 841 | } 842 | } 843 | }, 844 | "delayed-stream": { 845 | "version": "1.0.0", 846 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 847 | "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" 848 | }, 849 | "escape-string-regexp": { 850 | "version": "1.0.5", 851 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 852 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 853 | }, 854 | "exit": { 855 | "version": "0.1.2", 856 | "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", 857 | "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" 858 | }, 859 | "expand-tilde": { 860 | "version": "1.2.2", 861 | "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", 862 | "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", 863 | "requires": { 864 | "os-homedir": "^1.0.1" 865 | } 866 | }, 867 | "find-file-up": { 868 | "version": "0.1.3", 869 | "resolved": "https://registry.npmjs.org/find-file-up/-/find-file-up-0.1.3.tgz", 870 | "integrity": "sha1-z2gJG8+fMApA2kEbN9pczlovvqA=", 871 | "requires": { 872 | "fs-exists-sync": "^0.1.0", 873 | "resolve-dir": "^0.1.0" 874 | } 875 | }, 876 | "find-pkg": { 877 | "version": "0.1.2", 878 | "resolved": "https://registry.npmjs.org/find-pkg/-/find-pkg-0.1.2.tgz", 879 | "integrity": "sha1-G9wiwG42NlUy4qJIBGhUuXiNpVc=", 880 | "requires": { 881 | "find-file-up": "^0.1.2" 882 | } 883 | }, 884 | "find-process": { 885 | "version": "1.4.4", 886 | "resolved": "https://registry.npmjs.org/find-process/-/find-process-1.4.4.tgz", 887 | "integrity": "sha512-rRSuT1LE4b+BFK588D2V8/VG9liW0Ark1XJgroxZXI0LtwmQJOb490DvDYvbm+Hek9ETFzTutGfJ90gumITPhQ==", 888 | "requires": { 889 | "chalk": "^4.0.0", 890 | "commander": "^5.1.0", 891 | "debug": "^4.1.1" 892 | } 893 | }, 894 | "follow-redirects": { 895 | "version": "1.15.3", 896 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", 897 | "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" 898 | }, 899 | "form-data": { 900 | "version": "4.0.0", 901 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", 902 | "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", 903 | "requires": { 904 | "asynckit": "^0.4.0", 905 | "combined-stream": "^1.0.8", 906 | "mime-types": "^2.1.12" 907 | } 908 | }, 909 | "fs-exists-sync": { 910 | "version": "0.1.0", 911 | "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", 912 | "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=" 913 | }, 914 | "global-modules": { 915 | "version": "0.2.3", 916 | "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", 917 | "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", 918 | "requires": { 919 | "global-prefix": "^0.1.4", 920 | "is-windows": "^0.2.0" 921 | } 922 | }, 923 | "global-prefix": { 924 | "version": "0.1.5", 925 | "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", 926 | "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", 927 | "requires": { 928 | "homedir-polyfill": "^1.0.0", 929 | "ini": "^1.3.4", 930 | "is-windows": "^0.2.0", 931 | "which": "^1.2.12" 932 | } 933 | }, 934 | "has-flag": { 935 | "version": "3.0.0", 936 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 937 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 938 | }, 939 | "homedir-polyfill": { 940 | "version": "1.0.3", 941 | "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", 942 | "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", 943 | "requires": { 944 | "parse-passwd": "^1.0.0" 945 | } 946 | }, 947 | "ini": { 948 | "version": "1.3.8", 949 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", 950 | "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" 951 | }, 952 | "is-windows": { 953 | "version": "0.2.0", 954 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", 955 | "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=" 956 | }, 957 | "isexe": { 958 | "version": "2.0.0", 959 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 960 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 961 | }, 962 | "joi": { 963 | "version": "17.11.0", 964 | "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", 965 | "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", 966 | "requires": { 967 | "@hapi/hoek": "^9.0.0", 968 | "@hapi/topo": "^5.0.0", 969 | "@sideway/address": "^4.1.3", 970 | "@sideway/formula": "^3.0.1", 971 | "@sideway/pinpoint": "^2.0.0" 972 | } 973 | }, 974 | "kleur": { 975 | "version": "3.0.3", 976 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", 977 | "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" 978 | }, 979 | "lodash": { 980 | "version": "4.17.21", 981 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 982 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 983 | }, 984 | "mime-db": { 985 | "version": "1.52.0", 986 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 987 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 988 | }, 989 | "mime-types": { 990 | "version": "2.1.35", 991 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 992 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 993 | "requires": { 994 | "mime-db": "1.52.0" 995 | } 996 | }, 997 | "minimist": { 998 | "version": "1.2.8", 999 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1000 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" 1001 | }, 1002 | "os-homedir": { 1003 | "version": "1.0.2", 1004 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 1005 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" 1006 | }, 1007 | "parse-passwd": { 1008 | "version": "1.0.0", 1009 | "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", 1010 | "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" 1011 | }, 1012 | "prompts": { 1013 | "version": "2.4.1", 1014 | "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", 1015 | "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", 1016 | "requires": { 1017 | "kleur": "^3.0.3", 1018 | "sisteransi": "^1.0.5" 1019 | } 1020 | }, 1021 | "proxy-from-env": { 1022 | "version": "1.1.0", 1023 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 1024 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 1025 | }, 1026 | "resolve-dir": { 1027 | "version": "0.1.1", 1028 | "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", 1029 | "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", 1030 | "requires": { 1031 | "expand-tilde": "^1.2.2", 1032 | "global-modules": "^0.2.3" 1033 | } 1034 | }, 1035 | "rxjs": { 1036 | "version": "7.8.1", 1037 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", 1038 | "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", 1039 | "requires": { 1040 | "tslib": "^2.1.0" 1041 | } 1042 | }, 1043 | "signal-exit": { 1044 | "version": "3.0.3", 1045 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 1046 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" 1047 | }, 1048 | "sisteransi": { 1049 | "version": "1.0.5", 1050 | "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", 1051 | "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" 1052 | }, 1053 | "spawnd": { 1054 | "version": "5.0.0", 1055 | "resolved": "https://registry.npmjs.org/spawnd/-/spawnd-5.0.0.tgz", 1056 | "integrity": "sha512-28+AJr82moMVWolQvlAIv3JcYDkjkFTEmfDc503wxrF5l2rQ3dFz6DpbXp3kD4zmgGGldfM4xM4v1sFj/ZaIOA==", 1057 | "requires": { 1058 | "exit": "^0.1.2", 1059 | "signal-exit": "^3.0.3", 1060 | "tree-kill": "^1.2.2", 1061 | "wait-port": "^0.2.9" 1062 | } 1063 | }, 1064 | "supports-color": { 1065 | "version": "5.5.0", 1066 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1067 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1068 | "requires": { 1069 | "has-flag": "^3.0.0" 1070 | } 1071 | }, 1072 | "tree-kill": { 1073 | "version": "1.2.2", 1074 | "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", 1075 | "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==" 1076 | }, 1077 | "tslib": { 1078 | "version": "2.6.2", 1079 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", 1080 | "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" 1081 | }, 1082 | "typescript": { 1083 | "version": "4.2.4", 1084 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", 1085 | "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", 1086 | "dev": true 1087 | }, 1088 | "wait-on": { 1089 | "version": "7.2.0", 1090 | "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-7.2.0.tgz", 1091 | "integrity": "sha512-wCQcHkRazgjG5XoAq9jbTMLpNIjoSlZslrJ2+N9MxDsGEv1HnFoVjOCexL0ESva7Y9cu350j+DWADdk54s4AFQ==", 1092 | "requires": { 1093 | "axios": "^1.6.1", 1094 | "joi": "^17.11.0", 1095 | "lodash": "^4.17.21", 1096 | "minimist": "^1.2.8", 1097 | "rxjs": "^7.8.1" 1098 | } 1099 | }, 1100 | "wait-port": { 1101 | "version": "0.2.9", 1102 | "resolved": "https://registry.npmjs.org/wait-port/-/wait-port-0.2.9.tgz", 1103 | "integrity": "sha512-hQ/cVKsNqGZ/UbZB/oakOGFqic00YAMM5/PEj3Bt4vKarv2jWIWzDbqlwT94qMs/exAQAsvMOq99sZblV92zxQ==", 1104 | "requires": { 1105 | "chalk": "^2.4.2", 1106 | "commander": "^3.0.2", 1107 | "debug": "^4.1.1" 1108 | }, 1109 | "dependencies": { 1110 | "ansi-styles": { 1111 | "version": "3.2.1", 1112 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 1113 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 1114 | "requires": { 1115 | "color-convert": "^1.9.0" 1116 | } 1117 | }, 1118 | "chalk": { 1119 | "version": "2.4.2", 1120 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 1121 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 1122 | "requires": { 1123 | "ansi-styles": "^3.2.1", 1124 | "escape-string-regexp": "^1.0.5", 1125 | "supports-color": "^5.3.0" 1126 | } 1127 | }, 1128 | "commander": { 1129 | "version": "3.0.2", 1130 | "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", 1131 | "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" 1132 | } 1133 | } 1134 | }, 1135 | "which": { 1136 | "version": "1.3.1", 1137 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1138 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1139 | "requires": { 1140 | "isexe": "^2.0.0" 1141 | } 1142 | } 1143 | } 1144 | } 1145 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jest-process-manager", 3 | "description": "Starts a server before your Jest tests and tears it down after.", 4 | "version": "0.4.0", 5 | "main": "lib/index.js", 6 | "types": "src/types.d.ts", 7 | "repository": "https://github.com/playwright-community/jest-process-manager", 8 | "author": "Playwright Community", 9 | "license": "MIT", 10 | "keywords": [ 11 | "jest", 12 | "jest-environment", 13 | "server" 14 | ], 15 | "scripts": { 16 | "prebuild": "rm -rf lib/", 17 | "prepublishOnly": "yarn build", 18 | "build": "tsc", 19 | "dev": "tsc --watch", 20 | "lint": "tsc --noEmit" 21 | }, 22 | "dependencies": { 23 | "@types/wait-on": "^5.2.0", 24 | "chalk": "^4.1.0", 25 | "cwd": "^0.10.0", 26 | "exit": "^0.1.2", 27 | "find-process": "^1.4.4", 28 | "prompts": "^2.4.1", 29 | "signal-exit": "^3.0.3", 30 | "spawnd": "^5.0.0", 31 | "tree-kill": "^1.2.2", 32 | "wait-on": "^7.0.0" 33 | }, 34 | "devDependencies": { 35 | "@types/cwd": "^0.10.0", 36 | "@types/exit": "^0.1.31", 37 | "@types/prompts": "^2.0.10", 38 | "@types/signal-exit": "^3.0.0", 39 | "typescript": "^4.2.4" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | import { JestProcessManagerOptions } from './types'; 2 | 3 | export const ERROR_TIMEOUT = 'ERROR_TIMEOUT' 4 | export const ERROR_PORT_USED = 'ERROR_PORT_USED' 5 | export const ERROR_NO_COMMAND = 'ERROR_NO_COMMAND' 6 | 7 | export const DEFAULT_CONFIG: JestProcessManagerOptions = { 8 | command: 'npm run start', 9 | debug: false, 10 | options: {}, 11 | launchTimeout: 5000, 12 | host: 'localhost', 13 | port: 3000, 14 | protocol: 'tcp', 15 | usedPortAction: 'ask', 16 | waitOnScheme: {}, 17 | } 18 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import stream from 'stream' 3 | import net from 'net' 4 | import chalk from 'chalk' 5 | import cwd from 'cwd' 6 | import waitOn from 'wait-on' 7 | import findProcess from 'find-process' 8 | import { promisify } from 'util' 9 | import treeKill from 'tree-kill' 10 | import prompts from 'prompts' 11 | 12 | import { spawn, exec } from 'child_process' 13 | import exit from 'exit' 14 | import onExit from 'signal-exit' 15 | 16 | import type { ChildProcess, SpawnOptions } from 'child_process' 17 | import type { CustomSpawnD, JestProcessManagerOptions } from './types'; 18 | 19 | import { DEFAULT_CONFIG, ERROR_NO_COMMAND, ERROR_PORT_USED, ERROR_TIMEOUT } from './constants'; 20 | 21 | const pTreeKill = promisify(treeKill) 22 | const pExec = promisify(exec); 23 | 24 | function spawnd(command: string, options: SpawnOptions): CustomSpawnD { 25 | const proc = spawn(command, options) 26 | const cleanExit = (code = 1) => { 27 | if (proc?.pid) { 28 | treeKill(proc.pid, () => exit(code)) 29 | } else { 30 | exit(code) 31 | } 32 | } 33 | if (proc.stderr !== null) { 34 | proc.stderr.pipe(process.stderr) 35 | } 36 | proc.on('exit', cleanExit) 37 | proc.on('error', () => cleanExit(1)) 38 | 39 | const removeExitHandler = onExit(code => { 40 | cleanExit(typeof code === 'number' ? code : 1) 41 | }); 42 | 43 | proc.destroy = async (): Promise => { 44 | removeExitHandler() 45 | proc.removeAllListeners('exit') 46 | proc.removeAllListeners('error') 47 | return pTreeKill(proc.pid).catch(() => { 48 | /* ignore error */ 49 | }) 50 | } 51 | return proc as CustomSpawnD 52 | } 53 | 54 | const createServerLogPrefix = () => new stream.Transform({ 55 | transform(chunk, encoding, callback) { 56 | this.push(chalk.magentaBright(`[Jest Process Manager] ${chunk.toString()}`)) 57 | callback() 58 | }, 59 | }) 60 | 61 | export class JestProcessManagerError extends Error { 62 | code?: string 63 | constructor(message: string, code?: string) { 64 | super(message) 65 | this.code = code 66 | } 67 | } 68 | 69 | const servers: CustomSpawnD[] = [] 70 | 71 | const logProcDetection = (procName: string, port: number) => { 72 | console.log( 73 | chalk.blue( 74 | `🕵️ Detecting a process "${procName}" running on port "${port}"`, 75 | ), 76 | ) 77 | } 78 | 79 | type Unwrap = T extends (...args: any) => Promise ? U : T 80 | 81 | async function killProc(proc: Unwrap[0]): Promise { 82 | console.log(chalk.yellow(`Killing process ${proc.name}...`)) 83 | await pTreeKill(proc.pid) 84 | console.log(chalk.green(`Successfully killed process ${proc.name}`)) 85 | } 86 | 87 | function runServer(config: JestProcessManagerOptions, index: number) { 88 | if (!config.command) { 89 | throw new JestProcessManagerError( 90 | 'You must define a `command`', 91 | ERROR_NO_COMMAND, 92 | ) 93 | } 94 | 95 | servers[index] = spawnd(config.command, { 96 | shell: true, 97 | cwd: cwd(), 98 | ...config.options, 99 | env: { 100 | ...process.env, 101 | ...(config.options?.env ? config.options.env : {}) 102 | } 103 | }) 104 | 105 | if (config.debug) { 106 | console.log(chalk.magentaBright('\nJest dev-server output:')) 107 | servers[index].stdout!.pipe(createServerLogPrefix()).pipe(process.stdout) 108 | } 109 | } 110 | 111 | async function outOfStin(block: () => Promise) { 112 | const { stdin } = process 113 | const listeners = stdin.listeners('data') 114 | const result = await block() 115 | listeners.forEach(listener => stdin.on('data', listener as (...args: any[]) => void)) 116 | stdin.setRawMode(true) 117 | stdin.setEncoding('utf8') 118 | stdin.resume() 119 | return result 120 | } 121 | 122 | async function getIsPortTaken(config: JestProcessManagerOptions) { 123 | // TODO Make it configurable through config? 124 | const timeout = 1000 125 | const {port, host} = config 126 | const promise = new Promise(((resolve, reject) => { 127 | const socket = new net.Socket() 128 | 129 | const onError = () => { 130 | socket.destroy() 131 | reject() 132 | }; 133 | 134 | socket.setTimeout(timeout); 135 | socket.once('error', onError) 136 | socket.once('timeout', onError) 137 | 138 | socket.connect(port, host as string, () => { 139 | socket.end() 140 | resolve(true) 141 | }) 142 | })) 143 | 144 | try { 145 | await promise 146 | return true 147 | } catch (_) { 148 | return false 149 | } 150 | } 151 | 152 | const basePathUrlPostfix = (basePath?: string): string => { 153 | if (basePath) { 154 | return basePath.startsWith('/') ? basePath : `/${basePath}` 155 | } 156 | return '' 157 | } 158 | 159 | export async function setup(providedConfigs: JestProcessManagerOptions | JestProcessManagerOptions[]): Promise { 160 | // Compatible with older versions 161 | const configs = Array.isArray(providedConfigs) 162 | ? providedConfigs 163 | : [providedConfigs] 164 | await Promise.all( 165 | configs.map((providedConfig, index) => 166 | setupJestServer(providedConfig, index), 167 | ), 168 | ) 169 | } 170 | 171 | async function setupJestServer(providedConfig: JestProcessManagerOptions, index: number) { 172 | const config = { ...DEFAULT_CONFIG, ...providedConfig } 173 | 174 | const usedPortHandlers = { 175 | error() { 176 | throw new JestProcessManagerError( 177 | `Port ${config.port} is in use`, 178 | ERROR_PORT_USED, 179 | ) 180 | }, 181 | async kill() { 182 | console.log('') 183 | console.log( 184 | `Killing process listening to ${config.port}. On linux, this may require you to enter your password.`, 185 | ) 186 | const [portProcess] = await findProcess('port', config.port) 187 | logProcDetection(portProcess.name, config.port) 188 | await killProc(portProcess) 189 | }, 190 | async ask() { 191 | console.log('') 192 | const answers = await outOfStin<{ kill: boolean }>(() => 193 | prompts({ 194 | type: 'confirm', 195 | name: 'kill', 196 | message: `Another process is listening on ${config.port}. Should I kill it for you? On linux, this may require you to enter your password.`, 197 | initial: true, 198 | }), 199 | ) 200 | if (answers.kill) { 201 | const [portProcess] = await findProcess('port', config.port) 202 | logProcDetection(portProcess.name, config.port) 203 | await killProc(portProcess) 204 | } else { 205 | process.exit(1) 206 | } 207 | }, 208 | ignore() { }, 209 | } 210 | 211 | const usedPortHandler = usedPortHandlers[config.usedPortAction] 212 | if (!usedPortHandler) { 213 | const availableActions = Object.keys(usedPortHandlers) 214 | .map(action => `\`${action}\``) 215 | .join(', ') 216 | throw new JestProcessManagerError( 217 | `Invalid \`usedPortAction\`, only ${availableActions} are possible`, 218 | ) 219 | } 220 | 221 | if (config.port) { 222 | const { launchTimeout, protocol, host, port, basePath, waitOnScheme } = config 223 | const isPortTaken = await getIsPortTaken(config) 224 | if (isPortTaken) { 225 | await usedPortHandler() 226 | } 227 | 228 | if (config.usedPortAction === 'ignore' && isPortTaken) { 229 | console.log('') 230 | console.log('Port is already taken. Assuming server is already running.') 231 | } else { 232 | runServer(config, index) 233 | } 234 | 235 | const urlPostfix = basePathUrlPostfix(basePath) 236 | 237 | let url = `${protocol}://${host}:${port}${urlPostfix}` 238 | if (protocol === 'tcp' || protocol === 'socket') { 239 | url = `${protocol}:${host}:${port}${urlPostfix}` 240 | } 241 | const opts = { 242 | resources: [url], 243 | timeout: launchTimeout, 244 | ...waitOnScheme, 245 | } 246 | 247 | try { 248 | await waitOn(opts) 249 | } catch (err) { 250 | const [portProcess] = await findProcess('port', config.port) 251 | if (portProcess) { 252 | await killProc(portProcess) 253 | } 254 | throw new JestProcessManagerError( 255 | `Server has taken more than ${launchTimeout}ms to start.`, 256 | ERROR_TIMEOUT, 257 | ) 258 | } 259 | } else { 260 | runServer(config, index) 261 | } 262 | 263 | } 264 | 265 | export function getServers(): ChildProcess[] { 266 | return servers 267 | } 268 | 269 | export async function teardown(command?: string): Promise { 270 | if (servers.length) { 271 | await Promise.all(servers.map(server => server.destroy())) 272 | } 273 | if (command) { 274 | try { 275 | await pExec(command); 276 | } catch (e) { 277 | console.error(e); 278 | } 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /src/types.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { ChildProcess, SpawnOptions } from "child_process"; 3 | import { WaitOnOptions } from "wait-on"; 4 | 5 | export interface CustomSpawnD extends ChildProcess { 6 | destroy: () => Promise; 7 | } 8 | 9 | export interface JestProcessManagerOptions { 10 | /** 11 | * Command to execute to start the port. Directly passed to spawnd. 12 | * 13 | * ```js 14 | * module.exports = { 15 | * command: 'npm run start', 16 | * } 17 | * ``` 18 | */ 19 | command: string; 20 | /** 21 | * Log server output, useful if server is crashing at start. 22 | * @default false 23 | * ```js 24 | * module.exports = { 25 | * command: 'npm run start', 26 | * debug: true, 27 | * } 28 | * ``` 29 | */ 30 | debug?: boolean; 31 | /** 32 | * How many milliseconds to wait for the spawned server to be available before giving up. Defaults to wait-port's default. 33 | * @default 5000 34 | * ```js 35 | * module.exports = { 36 | * command: 'npm run start', 37 | * launchTimeout: 30000, 38 | * } 39 | * ``` 40 | */ 41 | launchTimeout?: number; 42 | /** 43 | * Host to wait for activity on before considering the server running. Must be used in conjunction with port. 44 | * @default 'localhost' 45 | * 46 | * ```js 47 | * module.exports = { 48 | * command: 'npm run start --port 3000', 49 | * host: 'customhost.com', 50 | * port: 3000 51 | * } 52 | * ``` 53 | */ 54 | host?: string; 55 | /** 56 | * To wait for an HTTP or TCP endpoint before considering the server running, include http or tcp as a protocol. Must be used in conjunction with port. 57 | * @default 'tcp' 58 | * ```js 59 | * module.exports = { 60 | * command: 'npm run start --port 3000', 61 | * protocol: 'http', 62 | * port: 3000, 63 | * } 64 | * ``` 65 | */ 66 | protocol?: 'https' | 'https-get' | 'http' | 'http-get' | 'tcp' | 'socket'; 67 | /** 68 | * Port to wait for activity on before considering the server running. If not provided, the server is assumed to immediately be running. 69 | * @default null 70 | * 71 | * ```js 72 | * module.exports = { 73 | * command: 'npm run start --port 3000', 74 | * port: 3000, 75 | * } 76 | * ``` 77 | */ 78 | port: number; 79 | /** 80 | * Option for a basePath where server is running 81 | * 82 | * ```js 83 | * module.exports = { 84 | * command: 'npm run start', 85 | * basePath: '/myservice', 86 | * } 87 | * ``` 88 | */ 89 | basePath?: string; 90 | /** 91 | * It defines the action to take if port is already used: 92 | * @default 'ask' 93 | * 94 | * - ask: a prompt is shown to decide if you want to kill the process or not 95 | * - error: an errow is thrown 96 | * - ignore: your test are executed, we assume that the server is already started 97 | * - kill: the process is automatically killed without a prompt 98 | * 99 | * ```js 100 | * module.exports = { 101 | * command: 'npm run start --port 3000', 102 | * port: 3000, 103 | * usedPortAction: 'kill', 104 | * } 105 | */ 106 | usedPortAction: 'ask' | 'error' | 'ignore' | 'kill'; 107 | /** 108 | * jest-process-manager uses the wait-on npm package to wait for resources to become available before calling callback. 109 | * @default {} 110 | * 111 | * ```js 112 | * module.exports = { 113 | * command: 'npm run start --port 3000', 114 | * port: 3000, 115 | * usedPortAction: 'kill', 116 | * waitOnScheme: { 117 | * delay: 1000, 118 | * }, 119 | * } 120 | */ 121 | waitOnScheme?: Partial; 122 | /** 123 | * Options which will be passed down to the spawn of the process 124 | */ 125 | options?: SpawnOptions; 126 | } 127 | 128 | export declare class JestProcessManagerError extends Error { 129 | code?: string; 130 | constructor(message: string, code?: string); 131 | } 132 | export declare function setup(providedConfigs: JestProcessManagerOptions | JestProcessManagerOptions[]): Promise; 133 | export declare function getServers(): ChildProcess[]; 134 | export declare function teardown(command?: string): Promise; 135 | 136 | export declare const ERROR_TIMEOUT = "ERROR_TIMEOUT"; 137 | export declare const ERROR_PORT_USED = "ERROR_PORT_USED"; 138 | export declare const ERROR_NO_COMMAND = "ERROR_NO_COMMAND"; 139 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "strict": true, 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "outDir": "lib", 9 | "rootDir": "src" 10 | } 11 | } 12 | --------------------------------------------------------------------------------